小编典典

创建一个通用的爬行spider

scrapy

我的问题确实是与上一个问题相同的方法,但是在Scrapy 0.14中。

使用一个Scrapyspider访问多个网站

基本上,我有一个GUI,它接受域,关键字,标签名称等参数,并且我想创建一个通用的爬虫来为那些标签中的关键字搜寻这些域。通过覆盖spider管理器类或动态创建spider,我已经使用较旧的scrapy版本阅读了冲突的内容。首选哪种方法?如何实现和调用正确的解决方案?提前致谢。

这是我想使通用的代码。它还使用BeautifulSoup。我将其配对,因此希望不会删除对理解它至关重要的任何内容。

class MySpider(CrawlSpider):

name = 'MySpider'
allowed_domains = ['somedomain.com', 'sub.somedomain.com']
start_urls = ['http://www.somedomain.com']

rules = (
    Rule(SgmlLinkExtractor(allow=('/pages/', ), deny=('', ))),

    Rule(SgmlLinkExtractor(allow=('/2012/03/')), callback='parse_item'),
)

def parse_item(self, response):
    contentTags = []

    soup = BeautifulSoup(response.body)

    contentTags = soup.findAll('p', itemprop="myProp")

    for contentTag in contentTags:
        matchedResult = re.search('Keyword1|Keyword2', contentTag.text)
        if matchedResult:
            print('URL Found: ' + response.url)

    pass

阅读 632

收藏
2020-04-08

共1个答案

小编典典

我使用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 Spider
from scrapy.selector import Selector
from scrapy.http import Request
from sitespider.items import genspiderItem

class 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 item

masterspider / sitespider / spiders / somesite_spider.py

# -*- coding: utf8 -*-
from scrapy.spider import Spider
from scrapy.selector import Selector
from scrapy.http import Request
from sitespider.items import genspiderItem
from masterspider.masterspider import MasterSpider

class 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
#          ...
2020-04-08