irpas技术客

Python爬虫第三课 Scrapy和Scrapy-redis_办公模板库 素材蛙_scrapy和redis

网络投稿 6384

scrapy的概念和流程 学习目标: 了解 scrapy的概念了解 scrapy框架的作用掌握 scrapy框架的运行流程掌握 scrapy中每个模块的作用


1. scrapy的概念

Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架。

Scrapy 使用了Twisted['tw?st?d]异步网络框架,可以加快我们的下载速度。

Scrapy文档地址:http://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/overview.html

2. scrapy框架的作用

少量的代码,就能够快速的抓取

3. scrapy的工作流程 3.1 回顾之前的爬虫流程 3.2 上面的流程可以改写为 3.3 scrapy的流程 其流程可以描述如下: 爬虫中起始的url构造成request对象–>爬虫中间件–>引擎–>调度器调度器把request–>引擎–>下载中间件—>下载器下载器发送请求,获取response响应---->下载中间件---->引擎—>爬虫中间件—>爬虫爬虫提取url地址,组装成request对象---->爬虫中间件—>引擎—>调度器,重复步骤2爬虫提取数据—>引擎—>管道处理和保存数据 注意: 图中中文是为了方便理解后加上去的图中绿色线条的表示数据的传递注意图中中间件的位置,决定了其作用注意其中引擎的位置,所有的模块之前相互独立,只和引擎进行交互 3.4 scrapy的三个内置对象 request请求对象:由url method post_data headers等构成response响应对象:由url body status headers等构成item数据对象:本质是个字典 3.5 scrapy中每个模块的具体作用 注意: 爬虫中间件和下载中间件只是运行逻辑的位置不同,作用是重复的:如替换UA等
小结 scrapy的概念:Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架scrapy框架的运行流程以及数据传递过程: 爬虫中起始的url构造成request对象–>爬虫中间件–>引擎–>调度器调度器把request–>引擎–>下载中间件—>下载器下载器发送请求,获取response响应---->下载中间件---->引擎—>爬虫中间件—>爬虫爬虫提取url地址,组装成request对象---->爬虫中间件—>引擎—>调度器,重复步骤2爬虫提取数据—>引擎—>管道处理和保存数据 scrapy框架的作用:通过少量代码实现快速抓取掌握scrapy中每个模块的作用: 引擎(engine):负责数据和信号在不腰痛模块间的传递 调度器(scheduler):实现一个队列,存放引擎发过来的request请求对象 下载器(downloader):发送引擎发过来的request请求,获取响应,并将响应交给引擎 爬虫(spider):处理引擎发过来的response,提取数据,提取url,并交给引擎 管道(pipeline):处理引擎传递过来的数据,比如存储 下载中间件(downloader middleware):可以自定义的下载扩展,比如设置代理ip 爬虫中间件(spider middleware):可以自定义request请求和进行response过滤,与下载中间件作用重复
scrapy的入门使用 学习目标: 掌握 scrapy的安装应用 创建scrapy的项目应用 创建scrapy爬虫应用 运行scrapy爬虫应用 scrapy定位以及提取数据或属性值的方法掌握 response响应对象的常用属性
1 安装scrapy

命令: ????sudo apt-get install scrapy 或者: ????pip/pip3 install scrapy

2 scrapy项目开发流程 创建项目: ????scrapy startproject mySpider生成一个爬虫: ????scrapy genspider itcast itcast.cn提取数据: ????根据网站结构在spider中实现数据采集相关内容保存数据: ????使用pipeline进行数据后续处理和保存 3. 创建项目

通过命令将scrapy项目的的文件生成出来,后续步骤都是在项目文件中进行相关操作,下面以抓取传智师资库来学习scrapy的入门使用:http://·/channel/teacher.shtml

创建scrapy项目的命令: ????scrapy startproject <项目名字> 示例: ????scrapy startproject myspider

生成的目录和文件结果如下:

4. 创建爬虫

通过命令创建出爬虫文件,爬虫文件为主要的代码作业文件,通常一个网站的爬取动作都会在爬虫文件中进行编写。

命令: ????在项目路径下执行: ????scrapy genspider <爬虫名字> <允许爬取的域名>

爬虫名字: 作为爬虫运行时的参数 允许爬取的域名: 为对于爬虫设置的爬取范围,设置之后用于过滤要爬取的url,如果爬取的url与允许的域不通则被过滤掉。

示例:

cd myspider scrapy genspider itcast itcast.cn

生成的目录和文件结果如下:

5. 完善爬虫

在上一步生成出来的爬虫文件中编写指定网站的数据采集操作,实现数据提取

5.1 在/myspider/myspider/spiders/itcast.py中修改内容如下: import scrapy class ItcastSpider(scrapy.Spider): # 继承scrapy.spider # 爬虫名字 name = 'itcast' # 允许爬取的范围 allowed_domains = ['itcast.cn'] # 开始爬取的url地址 start_urls = ['http://·/channel/teacher.shtml'] # 数据提取的方法,接受下载中间件传过来的response def parse(self, response): # scrapy的response对象可以直接进行xpath names = response.xpath('//div[@class="tea_con"]//li/div/h3/text()') print(names) # 获取具体数据文本的方式如下 # 分组 li_list = response.xpath('//div[@class="tea_con"]//li') for li in li_list: # 创建一个数据字典 item = {} # 利用scrapy封装好的xpath选择器定位元素,并通过extract()或extract_first()来获取结果 item['name'] = li.xpath('.//h3/text()').extract_first() # 老师的名字 item['level'] = li.xpath('.//h4/text()').extract_first() # 老师的级别 item['text'] = li.xpath('.//p/text()').extract_first() # 老师的介绍 print(item) 注意: scrapy.Spider爬虫类中必须有名为parse的解析如果网站结构层次比较复杂,也可以自定义其他解析函数在解析函数中提取的url地址如果要发送请求,则必须属于allowed_domains范围内,但是start_urls中的url地址不受这个限制,我们会在后续的课程中学习如何在解析函数中构造发送请求启动爬虫的时候注意启动的位置,是在项目路径下启动parse()函数中使用yield返回数据,注意:解析函数中的yield能够传递的对象只能是:BaseItem, Request, dict, None 5.2 定位元素以及提取数据、属性值的方法

解析并获取scrapy爬虫中的数据: 利用xpath规则字符串进行定位和提取

response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法额外方法extract():返回一个包含有字符串的列表额外方法extract_first():返回列表中的第一个字符串,列表为空没有返回None 5.3 response响应对象的常用属性 response.url:当前响应的url地址response.request.url:当前响应对应的请求的url地址response.headers:响应头response.requests.headers:当前响应的请求头response.body:响应体,也就是html代码,byte类型response.status:响应状态码 6 保存数据

利用管道pipeline来处理(保存)数据

6.1 在pipelines.py文件中定义对数据的操作 定义一个管道类重写管道类的process_item方法process_item方法处理完item之后必须返回给引擎 import json class ItcastPipeline(): # 爬虫文件中提取数据的方法每yield一次item,就会运行一次 # 该方法为固定名称函数 def process_item(self, item, spider): print(item) return item 6.2 在settings.py配置启用管道 ITEM_PIPELINES = { 'myspider.pipelines.ItcastPipeline': 400 }

配置项中键为使用的管道类,管道类使用.进行分割,第一个为项目目录,第二个为文件,第三个为定义的管道类。 配置项中值为管道的使用顺序,设置的数值约小越优先执行,该值一般设置为1000以内。

7. 运行scrapy

命令:在项目目录下执行scrapy crawl <爬虫名字>

示例:scrapy crawl itcast


小结 scrapy的安装:pip install scrapy创建scrapy的项目: scrapy startproject myspider创建scrapy爬虫:在项目目录下执行 scrapy genspider itcast itcast.cn运行scrapy爬虫:在项目目录下执行 scrapy crawl itcast解析并获取scrapy爬虫中的数据: response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法extract() 返回一个包含有字符串的列表extract_first() 返回列表中的第一个字符串,列表为空没有返回None scrapy管道的基本使用: 完善pipelines.py中的process_item函数在settings.py中设置开启pipeline response响应对象的常用属性 response.url:当前响应的url地址response.request.url:当前响应对应的请求的url地址response.headers:响应头response.requests.headers:当前响应的请求头response.body:响应体,也就是html代码,byte类型response.status:响应状态码
scrapy数据建模与请求 学习目标: 应用 在scrapy项目中进行建模应用 构造Request对象,并发送请求应用 利用meta参数在不同的解析函数中传递数据
1. 数据建模

通常在做项目的过程中,在items.py中进行数据建模

1.1 为什么建模 定义item即提前规划好哪些字段需要抓,防止手误,因为定义好之后,在运行过程中,系统会自动检查配合注释一起可以清晰的知道要抓取哪些字段,没有定义的字段不能抓取,在目标字段少的时候可以使用字典代替使用scrapy的一些特定组件需要Item做支持,如scrapy的ImagesPipeline管道类,百度搜索了解更多 1.2 如何建模

在items.py文件中定义要提取的字段:

class MyspiderItem(scrapy.Item): name = scrapy.Field() # 讲师的名字 title = scrapy.Field() # 讲师的职称 desc = scrapy.Field() # 讲师的介绍 1.3 如何使用模板类

模板类定义以后需要在爬虫中导入并且实例化,之后的使用方法和使用字典相同

job.py:

from myspider.items import MyspiderItem # 导入Item,注意路径 ... def parse(self, response) item = MyspiderItem() # 实例化后可直接使用 item['name'] = node.xpath('./h3/text()').extract_first() item['title'] = node.xpath('./h4/text()').extract_first() item['desc'] = node.xpath('./p/text()').extract_first() print(item)

注意:

from myspider.items import MyspiderItem这一行代码中 注意item的正确导入路径,忽略pycharm标记的错误python中的导入路径要诀:从哪里开始运行,就从哪里开始导入 1.4 开发流程总结 创建项目 scrapy startproject 项目名明确目标 在items.py文件中进行建模创建爬虫 3.1 创建爬虫 scrapy genspider 爬虫名 允许的域 3.2 完成爬虫 修改start_urls 检查修改allowed_domains 编写解析方法保存数据 在pipelines.py文件中定义对数据处理的管道 在settings.py文件中注册启用管道 2. 翻页请求的思路

对于要提取如下图中所有页面上的数据该怎么办?

回顾requests模块是如何实现翻页请求的:

找到下一页的URL地址调用requests.get(url)

scrapy实现翻页的思路:

找到下一页的url地址构造url地址的请求对象,传递给引擎 3. 构造Request对象,并发送请求 3.1 实现方法 确定url地址构造请求,scrapy.Request(url,callback) callback:指定解析函数名称,表示该请求返回的响应使用哪一个函数进行解析 把请求交给引擎:yield scrapy.Request(url,callback) 3.2 网易招聘爬虫

通过爬取网易招聘的页面的招聘信息,学习如何实现翻页请求

地址:https://hr.163.com/position/list.do

思路分析: 获取首页的数据寻找下一页的地址,进行翻页,获取数据 注意: 可以在settings中设置ROBOTS协议 # False表示忽略网站的robots.txt协议,默认为True ROBOTSTXT_OBEY = False 可以在settings中设置User-Agent: # scrapy发送的每一个请求的默认UA都是设置的这个User-Agent USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36' 3.3 代码实现

在爬虫文件的parse方法中:

...... # 提取下一页的href next_url = response.xpath('//a[contains(text(),">")]/@href').extract_first() # 判断是否是最后一页 if next_url != 'javascript:void(0)': # 构造完整url url = 'https://hr.163.com/position/list.do' + next_url # 构造scrapy.Request对象,并yield给引擎 # 利用callback参数指定该Request对象之后获取的响应用哪个函数进行解析 yield scrapy.Request(url, callback=self.parse) ...... 3.4 scrapy.Request的更多参数 scrapy.Request(url[,callback,method="GET",headers,body,cookies,meta,dont_filter=False]) 参数解释 中括号里的参数为可选参数callback:表示当前的url的响应交给哪个函数去处理meta:实现数据在不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,请求深度等dont_filter:默认为False,会过滤请求的url地址,即请求过的url地址不会继续被请求,对需要重复请求的url地址可以把它设置为Ture,比如贴吧的翻页请求,页面的数据总是在变化;start_urls中的地址会被反复请求,否则程序不会启动method:指定POST或GET请求headers:接收一个字典,其中不包括cookiescookies:接收一个字典,专门放置cookiesbody:接收json字符串,为POST的数据,发送payload_post请求时使用(在下一章节中会介绍post请求) 4. meta参数的使用

meta的作用:meta可以实现数据在不同的解析函数中的传递

在爬虫文件的parse方法中,提取详情页增加之前callback指定的parse_detail函数:

def parse(self,response): ... yield scrapy.Request(detail_url, callback=self.parse_detail,meta={"item":item}) ... def parse_detail(self,response): #获取之前传入的item item = resposne.meta["item"] 特别注意 meta参数是一个字典meta字典中有一个固定的键proxy,表示代理ip,关于代理ip的使用我们将在scrapy的下载中间件的学习中进行介绍
小结 完善并使用Item数据类:在items.py中完善要爬取的字段在爬虫文件中先导入Item实力化Item对象后,像字典一样直接使用构造Request对象,并发送请求:导入scrapy.Request类在解析函数中提取urlyield scrapy.Request(url, callback=self.parse_detail, meta={})利用meta参数在不同的解析函数中传递数据:通过前一个解析函数 yield scrapy.Request(url, callback=self.xxx, meta={}) 来传递meta在self.xxx函数中 response.meta.get(‘key’, ‘’) 或 response.meta[‘key’] 的方式取出传递的数据
参考代码

wangyi/spiders/job.py

import scrapy class JobSpider(scrapy.Spider): name = 'job' # 2.检查允许的域名 allowed_domains = ['163.com'] # 1 设置起始的url start_urls = ['https://hr.163.com/position/list.do'] def parse(self, response): # 获取所有的职位节点列表 node_list = response.xpath('//*[@class="position-tb"]/tbody/tr') # print(len(node_list)) # 遍历所有的职位节点列表 for num, node in enumerate(node_list): # 索引为值除2取余为0的才是含有数据的节点,通过判断进行筛选 if num % 2 == 0: item = {} item['name'] = node.xpath('./td[1]/a/text()').extract_first() item['link'] = node.xpath('./td[1]/a/@href').extract_first() item['depart'] = node.xpath('./td[2]/text()').extract_first() item['category'] = node.xpath('./td[3]/text()').extract_first() item['type'] = node.xpath('./td[4]/text()').extract_first() item['address'] = node.xpath('./td[5]/text()').extract_first() item['num'] = node.xpath('./td[6]/text()').extract_first().strip() item['date'] = node.xpath('./td[7]/text()').extract_first() yield item # 翻页处理 # 获取翻页url part_url = response.xpath('//a[contains(text(),">")]/@href').extract_first() # 判断是否为最后一页,如果不是最后一页则进行翻页操作 if part_url != 'javascript:void(0)': # 拼接完整翻页url next_url = 'https://hr.163.com/position/list.do' + part_url yield scrapy.Request( url=next_url, callback=self.parse )

wangyi/items.py

class WangyiItem(scrapy.Item): # define the fields for your item here like: name = scrapy.Field() link = scrapy.Field() depart = scrapy.Field() category = scrapy.Field() type = scrapy.Field() address = scrapy.Field() num = scrapy.Field() date = scrapy.Field() scrapy管道的使用 学习目标: 掌握 scrapy管道(pipelines.py)的使用

之前我们在scrapy入门使用一节中学习了管道的基本使用,接下来我们深入的学习scrapy管道的使用

1. pipeline中常用的方法: process_item(self,item,spider): 管道类中必须有的函数实现对item数据的处理必须return item open_spider(self, spider): 在爬虫开启的时候仅执行一次close_spider(self, spider): 在爬虫关闭的时候仅执行一次 2. 管道文件的修改

继续完善wangyi爬虫,在pipelines.py代码中完善

import json from pymongo import MongoClient class WangyiFilePipeline(object): def open_spider(self, spider): # 在爬虫开启的时候仅执行一次 if spider.name == 'itcast': self.f = open('json.txt', 'a', encoding='utf-8') def close_spider(self, spider): # 在爬虫关闭的时候仅执行一次 if spider.name == 'itcast': self.f.close() def process_item(self, item, spider): if spider.name == 'itcast': self.f.write(json.dumps(dict(item), ensure_ascii=False, indent=2) + ',\n') # 不return的情况下,另一个权重较低的pipeline将不会获得item return item class WangyiMongoPipeline(object): def open_spider(self, spider): # 在爬虫开启的时候仅执行一次 if spider.name == 'itcast': # 也可以使用isinstanc函数来区分爬虫类: con = MongoClient(host='127.0.0.1', port=27017) # 实例化mongoclient self.collection = con.itcast.teachers # 创建数据库名为itcast,集合名为teachers的集合操作对象 def process_item(self, item, spider): if spider.name == 'itcast': self.collection.insert(item) # 此时item对象必须是一个字典,再插入 # 如果此时item是BaseItem则需要先转换为字典:dict(BaseItem) # 不return的情况下,另一个权重较低的pipeline将不会获得item return item 3. 开启管道

在settings.py设置开启pipeline

...... ITEM_PIPELINES = { 'myspider.pipelines.ItcastFilePipeline': 400, # 400表示权重 'myspider.pipelines.ItcastMongoPipeline': 500, # 权重值越小,越优先执行! } ......

别忘了开启mongodb数据库 sudo service mongodb start 并在mongodb数据库中查看 mongo

思考:在settings中能够开启多个管道,为什么需要开启多个?

不同的pipeline可以处理不同爬虫的数据,通过spider.name属性来区分不同的pipeline能够对一个或多个爬虫进行不同的数据处理的操作,比如一个进行数据清洗,一个进行数据的保存同一个管道类也可以处理不同爬虫的数据,通过spider.name属性来区分 4. pipeline使用注意点 使用之前需要在settings中开启pipeline在setting中键表示位置(即pipeline在项目中的位置可以自定义),值表示距离引擎的远近,越近数据会越先经过:权重值小的优先执行有多个pipeline的时候,process_item的方法必须return item,否则后一个pipeline取到的数据为None值pipeline中process_item的方法必须有,否则item没有办法接受和处理process_item方法接受item和spider,其中spider表示当前传递item过来的spideropen_spider(spider) :能够在爬虫开启的时候执行一次close_spider(spider) :能够在爬虫关闭的时候执行一次上述俩个方法经常用于爬虫和数据库的交互,在爬虫开启的时候建立和数据库的连接,在爬虫关闭的时候断开和数据库的连接
小结 管道能够实现数据的清洗和保存,能够定义多个管道实现不同的功能,其中有个三个方法 process_item(self,item,spider):实现对item数据的处理open_spider(self, spider): 在爬虫开启的时候仅执行一次close_spider(self, spider): 在爬虫关闭的时候仅执行一次
scrapy中间件的使用 学习目标: 应用 scrapy中使用间件使用随机UA的方法应用 scrapy中使用代理ip的的方法应用 scrapy与selenium配合使用
1. scrapy中间件的分类和作用 1.1 scrapy中间件的分类

根据scrapy运行流程中所在位置不同分为:

下载中间件爬虫中间件 1.2 scrapy中间的作用:预处理request和response对象 对header以及cookie进行更换和处理使用代理ip等对请求进行定制化操作,

但在scrapy默认的情况下 两种中间件都在middlewares.py一个文件中

爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件

2. 下载中间件的使用方法:

接下来我们对腾讯招聘爬虫进行修改完善,通过下载中间件来学习如何使用中间件 编写一个Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启

Downloader Middlewares默认的方法:

process_request(self, request, spider):

当每个request通过下载中间件时,该方法被调用。 2. 返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法 3. 返回Response对象:不再请求,把response返回给引擎 4. 返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法

process_response(self, request, response, spider):

当下载器完成http请求,传递响应给引擎的时候调用 2. 返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法 3. 返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法

在settings.py中配置开启中间件,权重值越小越优先执行

3. 定义实现随机User-Agent的下载中间件 3.1 在middlewares.py中完善代码 import random from Tencent.settings import USER_AGENTS_LIST # 注意导入路径,请忽视pycharm的错误提示 class UserAgentMiddleware(object): def process_request(self, request, spider): user_agent = random.choice(USER_AGENTS_LIST) request.headers['User-Agent'] = user_agent # 不写return class CheckUA: def process_response(self,request,response,spider): print(request.headers['User-Agent']) return response # 不能少! 3.2 在settings中设置开启自定义的下载中间件,设置方法同管道 DOWNLOADER_MIDDLEWARES = { 'Tencent.middlewares.UserAgentMiddleware': 543, # 543是权重值 'Tencent.middlewares.CheckUA': 600, # 先执行543权重的中间件,再执行600的中间件 } 3.3 在settings中添加UA的列表 USER_AGENTS_LIST = [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5" ] 运行爬虫观察现象 4. 代理ip的使用 4.1 思路分析 代理添加的位置:request.meta中增加proxy字段获取一个代理ip,赋值给request.meta['proxy'] 代理池中随机选择代理ip代理ip的webapi发送请求获取一个代理ip 4.2 具体实现

免费代理ip:

class ProxyMiddleware(object): def process_request(self,request,spider): # proxies可以在settings.py中,也可以来源于代理ip的webapi # proxy = random.choice(proxies) # 免费的会失效,报 111 connection refused 信息!重找一个代理ip再试 proxy = 'https://1.71.188.37:3128' request.meta['proxy'] = proxy return None # 可以不写return

收费代理ip:

# 人民币玩家的代码(使用abuyun提供的代理ip) import base64 # 代理隧道验证信息 这个是在那个网站上申请的 proxyServer = 'http://proxy.abuyun.com:9010' # 收费的代理ip服务器地址,这里是abuyun proxyUser = 用户名 proxyPass = 密码 proxyAuth = "Basic " + base64.b64encode(proxyUser + ":" + proxyPass) class ProxyMiddleware(object): def process_request(self, request, spider): # 设置代理 request.meta["proxy"] = proxyServer # 设置认证 request.headers["Proxy-Authorization"] = proxyAuth 4.3 检测代理ip是否可用

在使用了代理ip的情况下可以在下载中间件的process_response()方法中处理代理ip的使用情况,如果该代理ip不能使用可以替换其他代理ip

class ProxyMiddleware(object): ...... def process_response(self, request, response, spider): if response.status != '200': request.dont_filter = True # 重新发送的请求对象能够再次进入队列 return requst 在settings.py中开启该中间件 5. 在中间件中使用selenium

以github登陆为例

5.1 完成爬虫代码 import scrapy class Login4Spider(scrapy.Spider): name = 'login4' allowed_domains = ['github.com'] start_urls = ['https://github.com/1596930226'] # 直接对验证的url发送请求 def parse(self, response): with open('check.html', 'w') as f: f.write(response.body.decode()) 5.2 在middlewares.py中使用selenium import time from selenium import webdriver def getCookies(): # 使用selenium模拟登陆,获取并返回cookie username = input('输入github账号:') password = input('输入github密码:') options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--disable-gpu') driver = webdriver.Chrome('/home/worker/Desktop/driver/chromedriver', chrome_options=options) driver.get('https://github.com/login') time.sleep(1) driver.find_element_by_xpath('//*[@id="login_field"]').send_keys(username) time.sleep(1) driver.find_element_by_xpath('//*[@id="password"]').send_keys(password) time.sleep(1) driver.find_element_by_xpath('//*[@id="login"]/form/div[3]/input[3]').click() time.sleep(2) cookies_dict = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()} driver.quit() return cookies_dict class LoginDownloaderMiddleware(object): def process_request(self, request, spider): cookies_dict = getCookies() print(cookies_dict) request.cookies = cookies_dict # 对请求对象的cookies属性进行替换 配置文件中设置开启该中间件后,运行爬虫可以在日志信息中看到selenium相关内容
小结

中间件的使用:

完善中间件代码:

process_request(self, request, spider):

当每个request通过下载中间件时,该方法被调用。返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法返回Response对象:不再请求,把response返回给引擎返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法

process_response(self, request, response, spider):

当下载器完成http请求,传递响应给引擎的时候调用返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法 需要在settings.py中开启中间件 DOWNLOADER_MIDDLEWARES = { ‘myspider.middlewares.UserAgentMiddleware’: 543, }
scrapy_redis概念作用和流程 学习目标 了解 分布式的概念及特点了解 scarpy_redis的概念了解 scrapy_redis的作用了解 scrapy_redis的工作流程

在前面scrapy框架中我们已经能够使用框架实现爬虫爬取网站数据,如果当前网站的数据比较庞大, 我们就需要使用分布式来更快的爬取数据

1. 分布式是什么

简单的说 分布式就是不同的节点(服务器,ip不同)共同完成一个任务

2. scrapy_redis的概念

scrapy_redis是scrapy框架的基于redis的分布式组件

3. scrapy_redis的作用

Scrapy_redis在scrapy的基础上实现了更多,更强大的功能,具体体现在:

通过持久化请求队列和请求的指纹集合来实现:

断点续爬分布式快速抓取 4. scrapy_redis的工作流程 4.1 回顾scrapy的流程 思考:那么,在这个基础上,如果需要实现分布式,即多台服务器同时完成一个爬虫,需要怎么做呢? 4.2 scrapy_redis的流程

在scrapy_redis中,所有的待抓取的request对象和去重的request对象指纹都存在所有的服务器公用的redis中

所有的服务器中的scrapy进程公用同一个redis中的request对象的队列

所有的request对象存入redis前,都会通过该redis中的request指纹集合进行判断,之前是否已经存入过

在默认情况下所有的数据会保存在redis中

具体流程如下:


小结

scarpy_redis的分布式工作原理

在scrapy_redis中,所有的待抓取的对象和去重的指纹都存在公用的redis中所有的服务器公用同一redis中的请求对象的队列所有的request对象存入redis前,都会通过请求对象的指纹进行判断,之前是否已经存入过
scrapy_redis原理分析并实现断点续爬以及分布式爬虫 学习目标 了解 scrapy实现去重的原理了解 scrapy中请求入队的条件掌握 scrapy_redis基于url地址的增量式单机爬虫掌握 scrapy_redis分布式爬虫
1. 下载github的demo代码

clone github scrapy-redis源码文件

git clone https://github.com/rolando/scrapy-redis.git

研究项目自带的demo

mv scrapy-redis/example-project ~/scrapyredis-project

2. 观察dmoz文件

在domz爬虫文件中,实现方式就是之前的crawlspider类型的爬虫

from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule class DmozSpider(CrawlSpider): """Follow categories and extract links.""" name = 'dmoz' allowed_domains = ['dmoztools.net'] start_urls = ['http://dmoztools.net/'] # 这里修改了url # 定义数据提取规则,使用了css选择器 rules = [ Rule(LinkExtractor( restrict_css=('.top-cat', '.sub-cat', '.cat-item') ), callback='parse_directory', follow=True), ] def parse_directory(self, response): for div in response.css('.title-and-desc'): yield { 'name': div.css('.site-title::text').extract_first(), 'description': div.css('.site-descr::text').extract_first().strip(), 'link': div.css('a::attr(href)').extract_first(), }

但是在settings.py中多了以下内容,这几行表示scrapy_redis中重新实现的了去重的类,以及调度器,并且使用RedisPipeline管道类

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" SCHEDULER = "scrapy_redis.scheduler.Scheduler" SCHEDULER_PERSIST = True ITEM_PIPELINES = { 'example.pipelines.ExamplePipeline': 300, 'scrapy_redis.pipelines.RedisPipeline': 400, } 3. 运行dmoz爬虫,观察现象 首先我们需要添加redis的地址,程序才能够使用redis REDIS_URL = "redis://127.0.0.1:6379" #或者使用下面的方式 # REDIS_HOST = "127.0.0.1" # REDIS_PORT = 6379 我们执行domz的爬虫,会发现redis中多了一下三个键: 中止进程后再次运行dmoz爬虫

继续执行程序,会发现程序在前一次的基础之上继续往后执行,所以domz爬虫是一个基于url地址的增量式的爬虫

4. scrapy_redis的原理分析

我们从settings.py中的三个配置来进行分析 分别是:

RedisPipeline # 管道类RFPDupeFilter # 指纹去重类Scheduler # 调度器类SCHEDULER_PERSIST # 是否持久化请求队列和指纹集合 4.1 Scrapy_redis之RedisPipeline

RedisPipeline中观察process_item,进行数据的保存,存入了redis中

4.2 Scrapy_redis之RFPDupeFilter

RFPDupeFilter 实现了对request对象的加密

4.3 Scrapy_redis之Scheduler

scrapy_redis调度器的实现了决定什么时候把request对象加入带抓取的队列,同时把请求过的request对象过滤掉

4.4 由此可以总结出request对象入队的条件 request的指纹不在集合中request的dont_filter为True,即不过滤 start_urls中的url地址会入队,因为他们默认是不过滤 4.5 实现单机断点续爬

改写网易招聘爬虫,该爬虫就是一个经典的基于url地址的增量式爬虫

5. 实现分布式爬虫 5.1 分析demo中代码

打开example-project项目中的myspider_redis.py文件

通过观察代码:

继承自父类为RedisSpider增加了一个redis_key的键,没有start_urls,因为分布式中,如果每台电脑都请求一次start_url就会重复多了__init__方法,该方法不是必须的,可以手动指定allow_domains启动方法: 在每个节点正确的目录下执行scrapy crawl 爬虫名,使该节点的scrapy_redis爬虫程序就位在共用的redis中 lpush redis_key 'start_url',使全部节点真正的开始运行 settings.py中关键的配置 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" SCHEDULER = "scrapy_redis.scheduler.Scheduler" SCHEDULER_PERSIST = True ITEM_PIPELINES = { 'example.pipelines.ExamplePipeline': 300, 'scrapy_redis.pipelines.RedisPipeline': 400, } REDIS_URL = "redis://127.0.0.1:6379" 5.2 动手实现分布式爬虫

改写tencent爬虫为分布式爬虫

注意:启动方式发生改变
小结

scrapy_redis的含义和能够实现的功能

scrapy是框架scrapy_redis是scrapy的组件scrapy_redis能够实现断点续爬和分布式爬虫

scrapy_redis流程和实现原理

在scrapy框架流程的基础上,把存储request对象放到了redis的有序集合中,利用该有序集合实现了请求队列并对request对象生成指纹对象,也存储到同一redis的集合中,利用request指纹避免发送重复的请求

request对象进入队列的条件

request的指纹不在集合中request的dont_filter为True,即不过滤

request指纹的实现

请求方法排序后的请求地址排序并处理过的请求体或空字符串用hashlib.sha1()对以上内容进行加密

scarpy_redis实现增量式爬虫、布式爬虫

对setting进行如下设置 DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”SCHEDULER = “scrapy_redis.scheduler.Scheduler”SCHEDULER_PERSIST = TrueITEM_PIPELINES = {‘scrapy_redis.pipelines.RedisPipeline’: 400,}REDIS_URL = “redis://127.0.0.1:6379” # 请正确配置REDIS_URL 爬虫文件中的爬虫类继承RedisSpider类爬虫类中redis_key替代了start_urls启动方式不同 通过scrapy crawl spider启动爬虫后,向redis_key放入一个或多个起始url(lpush或rpush都可以),才能够让scrapy_redis爬虫运行 除了以上差异点以外,scrapy_redis爬虫和scrapy爬虫的使用方法都是一样的
scrapy_splash组件的使用 学习目标 了解 scrapy_splash组件的作用了解 scrapy_splash组件的使用
1. 什么是scrapy_splash?

scrapy_splash是scrapy的一个组件

scrapy-splash加载js数据是基于Splash来实现的。Splash是一个Javascript渲染服务。它是一个实现了HTTP API的轻量级浏览器,Splash是用Python和Lua语言实现的,基于Twisted和QT等模块构建。使用scrapy-splash最终拿到的response相当于是在浏览器全部渲染完成以后的网页源代码。

splash官方文档 https://splash.readthedocs.io/en/stable/

2. scrapy_splash的作用

scrapy-splash能够模拟浏览器加载js,并返回js运行后的数据

3. scrapy_splash的环境安装 3.1 使用splash的docker镜像

splash的dockerfile https://github.com/scrapinghub/splash/blob/master/Dockerfile

观察发现splash依赖环境略微复杂,所以我们可以直接使用splash的docker镜像

如果不使用docker镜像请参考 splash官方文档 安装相应的依赖环境

3.1.1 安装并启动docker服务

安装参考 https://blog.csdn.net/sanpic/article/details/81984683

3.1.2 获取splash的镜像

在正确安装docker的基础上pull取splash的镜像

sudo docker pull scrapinghub/splash

3.1.3 验证是否安装成功

运行splash的docker服务,并通过浏览器访问8050端口验证安装是否成功

前台运行 sudo docker run -p 8050:8050 scrapinghub/splash

后台运行 sudo docker run -d -p 8050:8050 scrapinghub/splash

访问 http://127.0.0.1:8050 看到如下截图内容则表示成功

3.1.4 解决获取镜像超时:修改docker的镜像源

以ubuntu18.04为例

创建并编辑docker的配置文件

sudo vi /etc/docker/daemon.json

写入国内docker-cn.com的镜像地址配置后保存退出 { "registry-mirrors": ["https://registry.docker-cn.com"] }

重启电脑或docker服务后重新获取splash镜像

这时如果还慢,请使用手机热点(流量orz)

3.1.5 关闭splash服务

需要先关闭容器后,再删除容器

sudo docker ps -a sudo docker stop CONTAINER_ID sudo docker rm CONTAINER_ID 3.2 在python虚拟环境中安装scrapy-splash包

pip install scrapy-splash

4. 在scrapy中使用splash

以baidu为例

4.1 创建项目创建爬虫 scrapy startproject test_splash cd test_splash scrapy genspider no_splash baidu.com scrapy genspider with_splash baidu.com 4.2 完善settings.py配置文件

在settings.py文件中添加splash的配置以及修改robots协议

# 渲染服务的url SPLASH_URL = 'http://127.0.0.1:8050' # 下载器中间件 DOWNLOADER_MIDDLEWARES = { 'scrapy_splash.SplashCookiesMiddleware': 723, 'scrapy_splash.SplashMiddleware': 725, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, } # 去重过滤器 DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' # 使用Splash的Http缓存 HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage' # Obey robots.txt rules ROBOTSTXT_OBEY = False 4.3 不使用splash

在spiders/no_splash.py中完善

import scrapy class NoSplashSpider(scrapy.Spider): name = 'no_splash' allowed_domains = ['baidu.com'] start_urls = ['https://·blogs.com/zhangxinqi/p/9279014.html

关于scrapy_splash(截屏,get_cookies等) https://·/content/qita/800748


小结

scrapy_splash组件的作用

splash类似selenium,能够像浏览器一样访问请求对象中的url地址能够按照该url对应的响应内容依次发送请求并将多次请求对应的多次响应内容进行渲染最终返回渲染后的response响应对象

scrapy_splash组件的使用

需要splash服务作为支撑构造的request对象变为splash.SplashRequest以下载中间件的形式使用需要scrapy_splash特定配置

scrapy_splash的特定配置

SPLASH_URL = 'http://127.0.0.1:8050' DOWNLOADER_MIDDLEWARES = { 'scrapy_splash.SplashCookiesMiddleware': 723, 'scrapy_splash.SplashMiddleware': 725, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, } DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
scrapy的日志信息与配置 学习目标: 了解 scrapy的日志信息掌握 scrapy的常用配置掌握 scrapy_redis配置了解scrapy_splash配置了解scrapy_redis和scrapy_splash配合使用的配置
1. 了解scrapy的日志信息 2. scrapy的常用配置

ROBOTSTXT_OBEY 是否遵守robots协议,默认是遵守

关于robots协议 在百度搜索中,不能搜索到淘宝网中某一个具体的商品的详情页面,这就是robots协议在起作用Robots协议:网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取,但它仅仅是互联网中的一般约定例如:淘宝的robots协议

USER_AGENT 设置ua

DEFAULT_REQUEST_HEADERS 设置默认请求头,这里加入了USER_AGENT将不起作用

ITEM_PIPELINES 管道,左位置右权重:权重值越小,越优先执行

SPIDER_MIDDLEWARES 爬虫中间件,设置过程和管道相同

DOWNLOADER_MIDDLEWARES 下载中间件

COOKIES_ENABLED 默认为True表示开启cookie传递功能,即每次请求带上前一次的cookie,做状态保持

COOKIES_DEBUG 默认为False表示日志中不显示cookie的传递过程

LOG_LEVEL 默认为DEBUG,控制日志的等级

LOG_LEVEL = “WARNING”

LOG_FILE 设置log日志文件的保存路径,如果设置该参数,日志信息将写入文件,终端将不再显示,且受到LOG_LEVEL日志等级的限制

LOG_FILE = “./test.log” 3. scrapy_redis配置 DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter” # 指纹生成以及去重类SCHEDULER = “scrapy_redis.scheduler.Scheduler” # 调度器类SCHEDULER_PERSIST = True # 持久化请求队列和指纹集合ITEM_PIPELINES = {‘scrapy_redis.pipelines.RedisPipeline’: 400} # 数据存入redis的管道REDIS_URL = “redis://host:port” # redis的url 4. scrapy_splash配置 SPLASH_URL = 'http://127.0.0.1:8050' DOWNLOADER_MIDDLEWARES = { 'scrapy_splash.SplashCookiesMiddleware': 723, 'scrapy_splash.SplashMiddleware': 725, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, } DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage' 5. scrapy_redis和scrapy_splash配合使用的配置 5.1 原理 scrapy-redis中配置了”DUPEFILTER_CLASS” : “scrapy_redis.dupefilter.RFPDupeFilter”,与scrapy-splash配置的DUPEFILTER_CLASS = ‘scrapy_splash.SplashAwareDupeFilter’ 相冲突!查看了scrapy_splash.SplashAwareDupeFilter源码后,发现他继承了scrapy.dupefilter.RFPDupeFilter,并重写了request_fingerprint()方法。比较scrapy.dupefilter.RFPDupeFilter和scrapy_redis.dupefilter.RFPDupeFilter中的request_fingerprint()方法后,发现是一样的,因此重写了一个SplashAwareDupeFilter,继承scrapy_redis.dupefilter.RFPDupeFilter,其他代码不变。 5.2 重写dupefilter去重类,并在settings.py中使用 5.2.1 重写去重类 from __future__ import absolute_import from copy import deepcopy from scrapy.utils.request import request_fingerprint from scrapy.utils.url import canonicalize_url from scrapy_splash.utils import dict_hash from scrapy_redis.dupefilter import RFPDupeFilter def splash_request_fingerprint(request, include_headers=None): """ Request fingerprint which takes 'splash' meta key into account """ fp = request_fingerprint(request, include_headers=include_headers) if 'splash' not in request.meta: return fp splash_options = deepcopy(request.meta['splash']) args = splash_options.setdefault('args', {}) if 'url' in args: args['url'] = canonicalize_url(args['url'], keep_fragments=True) return dict_hash(splash_options, fp) class SplashAwareDupeFilter(RFPDupeFilter): """ DupeFilter that takes 'splash' meta key in account. It should be used with SplashMiddleware. """ def request_fingerprint(self, request): return splash_request_fingerprint(request) """以上为重写的去重类,下边为爬虫代码""" from scrapy_redis.spiders import RedisSpider from scrapy_splash import SplashRequest class SplashAndRedisSpider(RedisSpider): name = 'splash_and_redis' allowed_domains = ['baidu.com'] # start_urls = ['https://·/img_convert/5352d0ab1ecacb963f5ac984a53876a5.png#pic_center) scrapy的crawlspider爬虫 学习目标: 了解 crawlspider的作用应用 crawlspider爬虫创建的方法应用 crawlspider中rules的使用
1 crawlspider是什么

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

思路: 从response中提取所有的满足规则的url地址自动的构造自己requests请求,发送给引擎

对应的crawlspider就可以实现上述需求,能够匹配满足条件的url地址,组装成Reuqest对象后自动发送给引擎,同时能够指定callback函数

即:crawlspider爬虫可以按照规则自动获取连接

2 创建crawlspider爬虫并观察爬虫内的默认内容 2.1 创建crawlspider爬虫:

scrapy genspider -t crawl job 163.com

2.2 spider中默认生成的内容如下: class JobSpider(CrawlSpider): name = 'job' allowed_domains = ['163.com'] start_urls = ['https://hr.163.com/position/list.do'] rules = ( Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True), ) def parse_item(self, response): i = {} #i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract() #i['name'] = response.xpath('//div[@id="name"]').extract() #i['description'] = response.xpath('//div[@id="description"]').extract() return i 2.3 观察跟普通的scrapy.spider的区别

在crawlspider爬虫中,没有parse函数

重点在rules中: rules是一个元组或者是列表,包含的是Rule对象Rule表示规则,其中包含LinkExtractor,callback和follow等参数LinkExtractor:连接提取器,可以通过正则或者是xpath来进行url地址的匹配callback :表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理follow:连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,True表示会,Flase表示不会 3. crawlspider网易招聘爬虫

通过crawlspider爬取网易招聘的详情页的招聘信息

url:https://hr.163.com/position/list.do

思路分析: 定义一个规则,来进行列表页翻页,follow需要设置为True定义一个规则,实现从列表页进入详情页,并且指定回调函数在详情页提取数据 注意:连接提取器LinkExtractor中的allow对应的正则表达式匹配的是href属性的值 4 crawlspider使用的注意点: 除了用命令scrapy genspider -t crawl <爬虫名> <allowed_domail>创建一个crawlspider的模板,页可以手动创建crawlspider中不能再有以parse为名的数据提取方法,该方法被crawlspider用来实现基础url提取等功能Rule对象中LinkExtractor为固定参数,其他callback、follow为可选参数不指定callback且follow为True的情况下,满足rules中规则的url还会被继续提取和请求如果一个被提取的url满足多个Rule,那么会从rules中选择一个满足匹配条件的Rule执行 5 了解crawlspider其他知识点

链接提取器LinkExtractor的更多常见参数

allow: 满足括号中的’re’表达式的url会被提取,如果为空,则全部匹配deny: 满足括号中的’re’表达式的url不会被提取,优先级高于allowallow_domains: 会被提取的链接的domains(url范围),如:['hr.tencent.com', 'baidu.com']deny_domains: 不会被提取的链接的domains(url范围)restrict_xpaths: 使用xpath规则进行匹配,和allow共同过滤url,即xpath满足的范围内的url地址会被提取,如:restrict_xpaths='//div[@class="pagenav"]'

Rule常见参数

LinkExtractor: 链接提取器,可以通过正则或者是xpath来进行url地址的匹配callback: 表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理follow: 连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,默认True表示会,Flase表示不会process_links: 当链接提取器LinkExtractor获取到链接列表的时候调用该参数指定的方法,这个自定义方法可以用来过滤url,且这个方法执行后才会执行callback指定的方法 总结 crawlspider的作用:crawlspider可以按照规则自动获取连接crawlspider爬虫的创建:scrapy genspider -t crawl tencent hr.tencent.comcrawlspider中rules的使用:rules是一个元组或者是列表,包含的是Rule对象Rule表示规则,其中包含LinkExtractor,callback和follow等参数LinkExtractor:连接提取器,可以通过正则或者是xpath来进行url地址的匹配callback :表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理follow:连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,True表示会,Flase表示不会完成网易招聘爬虫crawlspider版本

crawlspider爬虫中,没有parse函数

重点在rules中: rules是一个元组或者是列表,包含的是Rule对象Rule表示规则,其中包含LinkExtractor,callback和follow等参数LinkExtractor:连接提取器,可以通过正则或者是xpath来进行url地址的匹配callback :表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理follow:连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,True表示会,Flase表示不会 3. crawlspider网易招聘爬虫

通过crawlspider爬取网易招聘的详情页的招聘信息

url:https://hr.163.com/position/list.do

思路分析: 定义一个规则,来进行列表页翻页,follow需要设置为True定义一个规则,实现从列表页进入详情页,并且指定回调函数在详情页提取数据 注意:连接提取器LinkExtractor中的allow对应的正则表达式匹配的是href属性的值 4 crawlspider使用的注意点: 除了用命令scrapy genspider -t crawl <爬虫名> <allowed_domail>创建一个crawlspider的模板,页可以手动创建crawlspider中不能再有以parse为名的数据提取方法,该方法被crawlspider用来实现基础url提取等功能Rule对象中LinkExtractor为固定参数,其他callback、follow为可选参数不指定callback且follow为True的情况下,满足rules中规则的url还会被继续提取和请求如果一个被提取的url满足多个Rule,那么会从rules中选择一个满足匹配条件的Rule执行 5 了解crawlspider其他知识点

链接提取器LinkExtractor的更多常见参数

allow: 满足括号中的’re’表达式的url会被提取,如果为空,则全部匹配deny: 满足括号中的’re’表达式的url不会被提取,优先级高于allowallow_domains: 会被提取的链接的domains(url范围),如:['hr.tencent.com', 'baidu.com']deny_domains: 不会被提取的链接的domains(url范围)restrict_xpaths: 使用xpath规则进行匹配,和allow共同过滤url,即xpath满足的范围内的url地址会被提取,如:restrict_xpaths='//div[@class="pagenav"]'

Rule常见参数

LinkExtractor: 链接提取器,可以通过正则或者是xpath来进行url地址的匹配callback: 表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理follow: 连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,默认True表示会,Flase表示不会process_links: 当链接提取器LinkExtractor获取到链接列表的时候调用该参数指定的方法,这个自定义方法可以用来过滤url,且这个方法执行后才会执行callback指定的方法 总结 crawlspider的作用:crawlspider可以按照规则自动获取连接crawlspider爬虫的创建:scrapy genspider -t crawl tencent hr.tencent.comcrawlspider中rules的使用:rules是一个元组或者是列表,包含的是Rule对象Rule表示规则,其中包含LinkExtractor,callback和follow等参数LinkExtractor:连接提取器,可以通过正则或者是xpath来进行url地址的匹配callback :表示经过连接提取器提取出来的url地址响应的回调函数,可以没有,没有表示响应不会进行回调函数的处理follow:连接提取器提取的url地址对应的响应是否还会继续被rules中的规则进行提取,True表示会,Flase表示不会完成网易招聘爬虫crawlspider版本


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #scrapy和redis #scrapy的概念了解 #scrapy框架的作用掌握 #scrapy框架的运行流程掌握 #scrapy中每个模块的作用1