之前的代码中,我们有很大一部分时间在寻找下一页的URL地址或者内容的URL地址上面,这个过程能更简单一些吗?

思路:
1.从response中提取所有的a标签对应的URL地址
2.自动的构造自己resquests请求,发送给引擎

目标:通过爬虫了解crawlspider的使用

生成crawlspider的命令:scrapy genspider -t crawl 爬虫名字 域名

1、LinkExtractors链接提取器

使用LinkExtractors可以不用程序员自己提取想要的url,然后发送请求。这些工作都可以交给LinkExtractors,他会在所有爬的页面中找到满足规则的url,实现自动的爬取。

  1. class scrapy.linkextractors.LinkExtractor(
  2. allow = (),
  3. deny = (),
  4. allow_domains = (),
  5. deny_domains = (),
  6. deny_extensions = None,
  7. restrict_xpaths = (),
  8. tags = ('a','area'),
  9. attrs = ('href'),
  10. canonicalize = True,
  11. unique = True,
  12. process_value = None
  13. )

主要参数讲解:

  • allow:允许的url。所有满足这个正则表达式的url都会被提取。
  • deny:禁止的url。所有满足这个正则表达式的url都不会被提取。
  • allow_domains:允许的域名。只有在这个里面指定的域名的url才会被提取。
  • deny_domains:禁止的域名。所有在这个里面指定的域名的url都不会被提取。
  • restrict_xpaths:严格的xpath。和allow共同过滤链接。

    2、Rule规则类

    定义爬虫的规则类。
  1. class scrapy.spiders.Rule(
  2. link_extractor,
  3. callback = None,
  4. cb_kwargs = None,
  5. follow = None,
  6. process_links = None,
  7. process_request = None
  8. )

主要参数讲解:

  • link_extractor:一个LinkExtractor对象,用于定义爬取规则。
  • callback:满足这个规则的url,应该要执行哪个回调函数。因为CrawlSpider使用了parse作为回调函数,因此不要覆盖parse作为回调函数自己的回调函数。
  • follow:指定根据该规则从response中提取的链接是否需要跟进。
  • process_links:从link_extractor中获取到链接后会传递给这个函数,用来过滤不需要爬取的链接。
  1. import scrapy
  2. from scrapy.linkextractors import LinkExtractor
  3. from scrapy.spiders import CrawlSpider, Rule
  4. class CygSpider(CrawlSpider):
  5. name = 'cyg'
  6. allowed_domains = ['wz.sun0769.com']
  7. start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']
  8. rules = (
  9. Rule(LinkExtractor(allow=r'http:\/\/wz\.sun0769\.com\/political\/index\/politicsNewest\?id=1&page=\d+'), follow=True),
  10. Rule(LinkExtractor(allow=r'http:\/\/wz\.sun0769\.com\/political\/politics\/index\?id=\d+'), callback='parse_item'),
  11. )
  12. def parse_item(self, response):
  13. content_dict = {}
  14. content_dict['username'] = response.xpath("//span[@class='fl details-head']/text()").extract()[-1].strip()
  15. content_dict['content'] = response.xpath("//div[@class='details-box']/pre/text()").extract_first().strip()
  16. img = response.xpath("//div[@class='clear details-img-list Picture-img']/img/@src").extract()
  17. if img:
  18. content_dict['img'] = img
  19. else:
  20. content_dict['img'] = "暂无图片"
  21. yield content_dict

注意点
1.用命令创建一个crawlspider的模板:scrapy genspider -t crawl <爬虫名字> ,也可以手动创建
2.CrawlSpider中不能再有以parse为名字的数据提取方法,这个方法被CrawlSpider用来实现基础URL提取等功能
3.一个Rule对象接受很多参数,首先第一个是包含URL规则的LinkExtractor对象,常用的还有callback和follow

  • callback:连接提取器提取出来的URL地址对应的响应交给他处理
  • follow:连接提取器提取出来的URL地址对应的响应是否继续被rules来过滤

4.不指定callback函数的请求下,如果follow为True,满足该rule的URL还会继续被请求
5.如果多个Rule都满足某一个URL,会从rules中选择第一个满足的进行操作

CrawlSpider爬取微信小程序社区

http://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1

  1. from scrapy.linkextractors import LinkExtractor
  2. from scrapy.spiders import CrawlSpider, Rule
  3. from wechatapp.items import WechatappItem
  4. class WxSpider(CrawlSpider):
  5. name = 'wx'
  6. allowed_domains = ['wxapp-union.com']
  7. start_urls = ['http://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1']
  8. rules = (
  9. Rule(LinkExtractor(allow=r'http:\/\/www\.wxapp-union\.com\/portal\.php\?mod=list&catid=2&page=\d+'), follow=True),
  10. Rule(LinkExtractor(allow=r'http:\/\/www\.wxapp-union\.com\/article-\d-1\.html'), callback='parse_item'),
  11. )
  12. def parse_item(self, response):
  13. print('-' * 30)
  14. title = response.xpath("//h1[@class='ph']/text()").extract_first()
  15. author = response.xpath("//p[@class='authors']/a/text()").extract_first()
  16. content = response.xpath("//td[@id='article_content']/p/text()").extract()
  17. build_time = response.xpath("//span[@class='time']/text()").extract_first()
  18. item = WechatappItem(title=title, author=author, content=content, build_time=build_time)
  19. print('-'*30)
  20. print(item)
  21. yield item