爬虫之Scrapy框架 (6)

自定义一个关于ImagesPipeline该父类的管道类,在pipelines.py中重写如下三个方法

from scrapy.pipelines.images import ImagesPipeline import scrapy class ImgproPipeline(ImagesPipeline): # 发起请求 def get_media_requests(self, item, info): imgSrc = item[\'imgSrc\'] # 请求传参,将meta字典传递给了file_path这个方法 yield scrapy.Request(url=imgSrc, meta={\'item\': item}) # 定制get_media_request请求到数据持久化存储的路径(文件夹路径+文件名称) def file_path(self, request, response=None, info=None): # 通过request.meta接收请求传参传递过来的meta字典 imgName = request.meta[\'item\'][\'imgName\'] return imgName # 如果配置文件中没指定文件夹 # return \'文件夹/%s.jpg\' % (image_guid) def item_completed(self, results, item, info): return item CrawlSpider 全站数据爬取

CrawlSpider就是Spider的一个子类

创建一个基于CrawlSpider爬虫文件

scrapy genspider -t crawl spiderName

LinkExtractor(allow=r\'正则表达式\'):链接提取器

作用:可以根据指定的指定的规则(allow)进行链接提取

Rule(link,callback,follow=True):规则解析器

link:链接提取

callback:回调函数,字符串反射调用函数,解析数据

follow=True:将链接提取器 继续作用到 链接提取器提取到的链接的对应页面中

作用:

1.将链接提取器提取到的链接进行请求发送(get)请求发送

2.请求到的数据根据指定的规则进行数据解析

深度爬取

手动发送请求解析数据,请求传参和LinkExtractor,Rule一起使用实现深度爬取

Rule(LinkExtractor(allow=r\'正则表达式提取指定url\'),callback=\'函数名\',follow=True(提取全站页码url)/Flase(提取当前叶页码url))

使用链接提取器提取详情页的url实现深度爬取

案例:阳光问政

spiderName.py中代码

问题:实例化在持久化存储后无法实现数据一一对应的汇总

import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule # 实例化了两个item对象 from sunPro.items import TitleItem, ContentItem class SunSpider(CrawlSpider): name = \'sun\' # allowed_domains = [\'www.xxx.com\'] start_urls = [\'http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1\'] # 根据正则提取全站页码 link = LinkExtractor(allow=r\'id=1&page=\d+\') # 提取标题对应的详情页链接 link_detail = LinkExtractor(allow=r\'politics/index\?id=\d+\') rules = ( Rule(link, callback=\'parse_item\', follow=True), Rule(link_detail, callback=\'parse_detail\', follow=False), ) def parse_item(self, response): li_list = response.xpath(\'/html/body/div[2]/div[3]/ul[2]/li\') for li in li_list: title = li.xpath(\'./span[3]/a/text()\').extract_first() detail_url = item = TitleItem() item[\'title\'] = title yield item def parse_detail(self, response): content = response.xpath(\'/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()\').extract_first() item = ContentItem() item[\'content\'] = content yield item

解决上述问题

手动发送请求解析详情页的内容,请求传参,传给一个item

import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from sunPro.items import SunproItem class SunSpider(CrawlSpider): name = \'sun\' # allowed_domains = [\'www.xxx.com\'] start_urls = [\'http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1\'] link = LinkExtractor(allow=r\'id=1&page=\d+\') rules = ( Rule(link, callback=\'parse_item\', follow=False), ) def parse_item(self, response): li_list = response.xpath(\'/html/body/div[2]/div[3]/ul[2]/li\') for li in li_list: title = li.xpath(\'./span[3]/a/text()\').extract_first() detail_url = "http://wz.sun0769.com/" + li.xpath(\'./span[3]/a/@href\').extract_first() item = SunproItem() item[\'title\'] = title yield scrapy.Request(url=detail_url, callback=self.parse_detail, meta={\'item\': item}) def parse_detail(self, response): content = response.xpath(\'/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()\').extract_first() item = response.meta[\'item\'] item[\'content\'] = content yield item 分布式

实际应用中很少,一般都是面试时问道,主要是文原理。

概念:搭建一个分布式机群,共同执行一组代码,联合对同一个资源的数据进行分布且联合爬取

实现方式:

简称:scrapy + redis

全称:Scrapy框架 + scrapy-redis组件

原生的scrapy框架无法实现分布式

原生scrapy的调度器和管道无法共享

scrapy-redis组件的作用

可以给原生的scrapy框架,提供可以被共享的管道和调度器

环境安装

pip install scrapy-redis

实现流程

修改爬虫文件中爬虫类对应的操作

导包:from scrapy_redis.spiders import RedisCrawlSpider

CrawlSpider 导入 RedisCrawlSpider Spider 导入 RedisSpider

爬虫类的父类修改成RedisCrawlSpider

将start_urls删除,添加一个redis_key=\'可以被共享调度器队列的名称\'

进行常规的请求和解析和向管道提交item操作即可

对settings.py进行配置

配置管道

ITEM_PIPELINES = { # scrapy组件中有管道,是基于redis的,所以目前只能用redis存储 \'scrapy_redis.pipelines.RedisPipeline\':400, }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzpzyg.html