python爬虫之十_scrapy框架进阶

一 CrawlSpider:URL规则过滤

CrawSpider类可以定义过滤url的规则,当spCrawSpiderder碰到满足条件的url都自动进行爬取,不用像基本爬虫类spider需手动yield Request。

4.1 创建CrawSpider

scrapy genspider -t crawl [爬虫类名] [域名]

与创建基本爬虫相比,这里用 -t 指明了使用的模板为’crawl’,即继承自CrawlSpider。

4.2 URL过滤规则

Rule类:

  1. link_extractor:LinkExtractor对象,用于定义爬取规则
  2. callback:满足规则的url,执行的回调函数
  3. follow:指定根据该规则从response中提取的链接是否需要跟进(指在提取出的url页面中是否还继续执行按规则提取提取url)
  4. process_links:从link_extractor中获取到链接后传递给该函数,用于过滤不需要爬取的链接

LinkExtractors类:链接提取器

  1. allow:允许的url,为一个正则表达式,符合则提取;
  2. deny:禁止的url,为一个正则表达式,符合则不提取;
  3. allow_domain:允许的域名;
  4. deny_domain:禁止的域名;
  5. restrict_xpaths:严格的xpath,和allow共同过滤;

4.3 举例

4.3.1 创建CrawlSpider
scrapy genspider -t crawl wxapp_spider 'wxapp-union.com'
4.3.2 CrawlSpider类

(1) 创建规则列表:可包含多条规则

rules=(
	Rule(LinkExtractor(...)),
	Rule(...)
)

规则列表rules创建后由scrapy框架自动执行,流程如下:

  1. scrapy将下载器返回的Response对象转发给crawlspider;
  2. scrapy自动解析Response对象,提取其中所有url,根据规则列表过滤;
  3. 根据符合规则的url创建Request对象,并将Request对象的callback参数设置为Rule中制定的callback函数;如果Rule中没有指定,则设置为默认解析函数parse;
  4. scrapy将Request对象转发给调度器;

注意:
包含目标数据的页面对应的Rule才需要指定回调函数(解析函数),如果该页面中只是单纯为了提取其他URL,不需要指定回调函数,LinkExtractor已经可以提取URL了;而且,scrapy自带URL去重的功能。

(2)创建解析函数
解析函数作为Rule中的回调函数,作用同基本爬虫类。

二 FormRequest:post请求模拟登录

Post请求要使用Request的子类FormRequest。如果要爬虫一开始就发送POST请求,需要在爬虫类中重写start_request(self)方法,并且不再调用start_urls里的url。因为爬虫类启动时,默认使用start_request方法通过get方式请求start_urls中的URL。

注意:

  1. 登录一个网页往往并不第一个请求就是POST,而是先GET到登录页面,再POST数据登录;
  2. Request对象若不指定回调函数,则默认调用parse函数,为避免,可以定义一个空的回调函数,专门用于这种情况;
  3. 登录后cookie就保存到本地了;

验证码识别: 使用第三方验证码平台,付费识别。对第三方平台发送图片进行请求,以json方式返回识别的验证码。

三 FilesPipeline、ImagesPipeline:文件下载

spider只创建Request对象,下载器也只获取Response对象,下载和存储图片由pipelines进行

3.1 传统下载方式:ulrlib.urlretrieve()

缺陷: 以获取一批图像URL为例,下载图片是按顺序遍历URL,一张一张图片下载,只有前一张下载完才会下载后面的,太慢;且需手动去重;

3.2 Scrapy为下载方法

scrapy框架由pipeline负责文件下载,且提供了FilesPipeline、ImagesPipeline,两个已定义好的pipeline。

FilesPipeline类:用于下载文件,包括视频、图片等;
ImagesPipeline类:专门用于下载图片,继承自FilesPipeline但功能更丰富,包括转格式、生成缩略图等。

优势:

  1. 调度器自动避免下载重复的文件;
  2. 异步下载,效率高;
  3. 可以方便地指定文件存储路径;
  4. 图片可以生成缩略图、转格式、检测图片宽高(可以设置太小的不下载);

FilesPipeline、ImagesPipeline为scrapy内置类,不需要手动创建和调用。通过在setting.py中配置即可创建和实现功能。

3.2.1FilesPipeline类

引擎会将spider解析后的数据转发给pipeline,若数据封装为item且具有file_urls、files属性,scrapy会调用FilesPipeline遍历file_urls中的URL并自动下载。下载完成后,将下载信息存入files属性。

  1. 定义item,包含file_urls属性(为待下载URL的list)、files属性;
  2. setting.py中配置FILES_STORE,作为文件存放路径;
  3. setting.py中配置ITEM_PIPELINE,启动pipeline;
scrapy.pipeline.files.FilesPipeline:1

3.2.2 ImagesPipeline类

与FilesPipeline类似,ImagesPipeline遍历iamge_urls中的URL,自动下载图片。下载完成后,信息存放在iamges中。

  1. 定义item,包含iamge_urls属性(为待下载URL的list)、iamges属性;
  2. setting.py中配置IMAGES_STORE,作为图片存放路径;
  3. setting.py中配置ITEM_PIPELINE,启动pipeline;
scrapy.pipeline.images.ImagesPipeline:1

3.3 自定义FilesPipeline、ImagesPipeline

ImagesPipeline的缺陷:settings.py中只能为ImagesPipeline设置一个统一的存储路径,无法实现图片分类存储。

get_media_requests(item,info)

ImagesPipeline通过调用get_media_requests()方法遍历item的iamge_urls属性生成request对象列表,返回给引擎。在请求前调用。

file_path(request, response, infp)

ImagesPipeline通过调用file_path()方法获得已下载图片的目标存储路径。在请求后调用。file_path返回的路径为"/full/图片名",之后scrapy再获取settings.py中的IMAGES_STORE路径值,最终路径为"(IMAGES_STORE)/full/图片名"。

自定义pipeline类,继承ImagesPipeline类,并对上述两个方法重写。

以图片分类存储为例,请求前的item中包含图片的详细信息,但是请求后无法获取item对象了,导致无法获取分类信息。通过上面两个方法发可以看到:Request对象是从请求前传到请求后的。如果将请求前的信息保存到Request对象中,则可实现 信息传递 了。而python的动态绑定使这一需求很简单满足:直接为Request对象创建一个属性,并将item对象赋为值即可。

重写get_media_requests方法:
先调用原方法获取request列表,再遍历列表为每个request对象增加item属性,并用参数item赋值,这样request对象中就保存了item的信息

重写fiel_path方法:
先根据request.item得到分类信息,从setting.py获取IMAGES_STORE的值。IMAGES_STORE+分类得到分类目录路径,检查是否存在并创建分类目录。然后调用原方法得到"/full/图片名",最后用分类目录路径replace默认存储路径中的full,得到图片路径。

四 下载器中间件:调用selenium

在middlewares.py文件中自定义下载器中间件类,直接继承object,必须至少实现process_request()、process_response()中的一个。在setting.py中配置后,由scrapy自动调用。可为中间件设置优先级。

下载器中间件位于引擎和下载器之间,可以通过 process_request() 方法操作引擎发给下载器的Request对象,也可以通过 process_response() 方法操作下载器发给引擎的Response对象。

4.1 process_request(self,request,spider)

scrapy自动调用,用于对引擎发给下载器的Request对象进行处理。多个下载器可以串联,依次调用各下载器的process_request方法。

参数:

  1. request:Request对象;
  2. spider:创建Request对象的spider对象;

返回值: 依据下载器中间件不同的返回值,scrapy进行不同的后续操作

  1. None:继续调用其他下载器中间件处理该request,直到合适的下载器处理函数被调用;
  2. Response对象:不会再将Request对象发送给下载器,而是直接将Response对象返回给引擎;
  3. Request对象:继续交给下一个下载器中间件处理;
  4. 产生异常:调用process_exception方法;

4.2 process_response(self,request,response,spider)

参数:

  1. request:被下载的request对象;
  2. resposne:处理后resposne对象;
  3. spier:发出request的spider对象;

返回值:

  1. Response对象:继续传给下一个中间件;
  2. Request对象:直接将Request对象重新传给下载器;
  3. 产生异常:调用request的errback方法,如果没有指定该方法则抛出异常;

4.3 应用

4.3.1 设置随机请求头

1.创建下载器中间件

class MyDownloaderMiddleware(object):
    USER_AGENTS={
    	...
    }
    def process_request(self,request,spider):
		user_agent=random.choice(self.USER_AGENT)
		request.headers['User-Agent']=user_agent

注意:www.useragentstring.com中有各种请求头信息

2.在setting.py中启用下载器中间件

DOWNLOADER_MIDDLEWARES={
	#下载器优先级,数字越小越优先,建议以543,544...
	'scrapyTest.middlewares.MyDownloaderMiddleware':543,
}
4.3.2 启动selenium
在这里插入代码片

五 Scrapy Shell

想测试xpath、beautifulsoup、正则表达式、css选择器写法是否正确,而直接运行scrapy太慢,可用Scrapy Shell快速测试。

Scrapy Shell 使用流程:

  1. cmd启动Scrapy框架环境;
  2. cmd进入项目目录;
  3. cmd执行scrapy shell ‘www…’,获取访问URL的response;
  4. cmd执行xpath、beautifulsoup、正则表达式解析response,并输出;
  5. 查看解析结果是否正确
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值