scrapy爬虫起步(3)-- 利用规则实现多页面抓取

第一篇 scrapy爬虫起步(1)–第一个爬虫程序实现了一个简单的爬虫程序,只抓取start_urls里的网页信息。用以实验的页面是社科相关的小组,这只是社科小组下面的第一页地址,如果需要抓取该分组下所有的小组,就需要继续访问其它页。利用scrapy的规则匹配来自动实现。

先贴代码吧:

# coding=utf-8
__author__ = 'Jeffee Chen'

from scrapy.contrib.spiders import CrawlSpider, Rule
from douban.items import DoubanItem
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor

class GroupSpider(CrawlSpider):
    name = "Douban"
    allowed_domains = ["douban.com"]
    start_urls = ["http://www.douban.com/group/explore?tag=%E7%A4%BE%E7%A7%91"]

    rules = [
        Rule(SgmlLinkExtractor(allow=(r'/group/explore\?start=.*', )), callback='parse_next_page'),
    ]

    def parse_next_page(self, response):
        item = DoubanItem()
        sel = response.xpath("//div[@class='group-list']/div[@class='result']")
        for s in sel:
            info = s.xpath("div/div/h3/a/text()").extract()
            item["groupName"] = info
            yield item

接着第一篇来,其它地方不用改,只需要修改spider文件即可。
可以看到,我们还是继承了CrawlSpider类,之前我们也可以继承BaseSpider类,但它不提供Rule规则,不提供页面追踪,而CrawlSpider是支持的。

代码中首先增加了rules的定义,直接扔一下官方文档的解释吧:

class scrapy.contrib.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)

- link_extractor: 是一个 Link Extractor 对象。 其定义了如何从爬取到的页面提取链接。

- callback: 是一个callable或string(该spider中同名的函数将会被调用)。 从link_extractor中每获取到链接时将会调用该函数。该回调函数接受一个response作为其第一个参数, 并返回一个包含 Item 以及(或) Request 对象(或者这两者的子类)的列表(list)。

- cb_kwargs: 包含传递给回调函数的参数(keyword argument)的字典。

- follow: 是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果 callback 为None, follow 默认设置为 True ,否则默认为 False 。

- process_links: 是一个callable或string(该spider中同名的函数将会被调用)。 从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤。

- process_request: 是一个callable或string(该spider中同名的函数将会被调用)。 该规则提取到每个request时都会调用该函数。该函数必须返回一个request或者None。 (用来过滤request)

感觉利用Rule的参数还可以做一些事情,以后再说吧。
然后,最重要的一步
在前面我们的爬虫程序继承了CrawlSpider,还定义了parse(self, response)作为抓取到内容之后的回调函数,实际上这是错误的用法!!!
在官方文档上有这么一段话:

  • 警告

当编写爬虫规则时,请避免使用 parse 作为回调函数。 由于 CrawlSpider 使用 parse 方法来实现其逻辑,如果 您覆盖了 parse 方法,crawl spider 将会运行失败。

也就是说如果我们将自己的回调函数定义为parse,那么实际上相当于CrawlSpider自身的回调函数是不能执行的,相应的Rule也不会处理。最终的结果就和我们最早的抓取结果一样,只会调用parse函数处理当前页面。这个问题的折磨曾让我感觉整个世界都不好了,而且网上搜索基本没有什么结果。
解决方法很简单,直接删除或重命名该函数就可以了。
留几个关键字吧,方便遇到该问题的孩子们能找过来:

Rule不起作用/ Rule不能执行/ scrapy 不追踪

其它的没什么好说的了,将parse函数重命名为parse_next_page函数,然后作为回调函数进行页面解析,运行,看看data.json文件,是不是已经将社科下面所有的小组名称都返回了

Good Luck!

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页