我使用Scrapy Extensions方法将Spider类扩展到一个名为Masterspider 的类,该类包括一个通用解析器。
下面是我的通用扩展解析器的非常“简短”的版本。请注意,一旦开始使用AJAX处理页面,就需要使用Javascript引擎(例如Selenium或BeautifulSoup)实现渲染器。还有许多其他代码来管理站点之间的差异(基于列标题的报废,处理相对URL和长URL,管理不同类型的数据容器等)。
使用Scrapy扩展方法的麻烦之处在于,如果某些不适合但我从未必须使用的方法,您仍然可以覆盖通用解析器方法。Masterspider类检查是否在特定于站点的spider类下创建了某些方法(例如parser_start,next_url_parser …),以允许进行特殊性管理:发送表单,根据页面中的元素构造next_url请求等。
由于我要抓取截然不同的网站,因此始终需要进行管理。这就是为什么我更愿意为每个抓取的站点保留一个类,以便我可以编写一些特定的方法来处理它(预处理/后处理,除了PipeLines,Request generators …)。
masterspider / sitespider / settings.py
EXTENSIONS = { 'masterspider.masterspider.MasterSpider': 500}masterspider / masterspdier / masterspider.py
# -*- coding: utf8 -*-from scrapy.spider import Spiderfrom scrapy.selector import Selectorfrom scrapy.http import Requestfrom sitespider.items import genspiderItemclass MasterSpider(Spider): def start_requests(self): if hasattr(self,'parse_start'): # First page requiring a specific parser fcallback = self.parse_start else: fcallback = self.parse return [ Request(self.spd['start_url'], callback=fcallback, meta={'itemfields': {}}) ] def parse(self, response): sel = Selector(response) lines = sel.xpath(self.spd['xlines']) # ... for line in lines: item = genspiderItem(response.meta['itemfields']) # ... # Get request_url of detailed page and scrap basic item info # ... yield Request(request_url, callback=self.parse_item, meta={'item':item, 'itemfields':response.meta['itemfields']}) for next_url in sel.xpath(self.spd['xnext_url']).extract(): if hasattr(self,'next_url_parser'): # Need to process the next page URL before? yield self.next_url_parser(next_url, response) else: yield Request( request_url, callback=self.parse, meta=response.meta) def parse_item(self, response): sel = Selector(response) item = response.meta['item'] for itemname, xitemname in self.spd['x_ondetailpage'].iteritems(): item[itemname] = "n".join(sel.xpath(xitemname).extract()) return itemmasterspider / sitespider / spiders / somesite_spider.py
# -*- coding: utf8 -*-from scrapy.spider import Spiderfrom scrapy.selector import Selectorfrom scrapy.http import Requestfrom sitespider.items import genspiderItemfrom masterspider.masterspider import MasterSpiderclass targetsiteSpider(MasterSpider): name = "targetsite" allowed_domains = ["www.targetsite.com"] spd = { 'start_url' : "http://www.targetsite.com/startpage", # Start page 'xlines' : "//td[something...]", 'xnext_url' : "//a[contains(@href,'something?page=')]/@href", # Next pages 'x_ondetailpage' : { "itemprop123" : u"id('someid')//text()" } }# def next_url_parser(self, next_url, response): # OPTIonAL next_url regexp pre-processor# ...


