scrapy爬虫框架学习笔记
Scrapy入门
一.基础指令
使用命令提示符,cd到想要操作的目录
scrapy startproject name
在该目录下创建项目
scrapy genspider name domain
使用前需要先cd到下一级目录
domain参数不需要带http或者https的头,也不需要引号
scrapy crawl name
启动名字为name的爬虫
二.开始
在name.py中进行编辑
爬虫开启后会把html传到name.py中的parse方法,可以在parse中进行网页解析。
解析可以使用scrapy自带的方法,也可以脱离框架使用BeautifulSoup、XPath、CSS等。
日志信息的屏蔽
如果没有对日志信息屏蔽,会产生大量信息,影响调试。可以在settings.py中加入以下代码,将等级warning以下的日志信息全部屏蔽
1 |
|
三.将数据传输到pipe中
使用yield关键字
yield可以将数据逐个转入,可以使用的数据类型是Request,BaseItem,dict或者None。(不可以直接返回列表!!)
在此之前
使用pipe需要先在设置中开启pipeline,在setting.py中取消列代码的注释:
1 |
|
字典中的键表示pipeline的名字,值表示这个pipeline的权重,数据会先结果权重小的pipeline再经过权重大的。
为什么要有多个pipeline
- 一个项目可能有多个爬虫,爬取不同的网站产生不同的数据,所以需要多个pipeline对数据进行处理。
- 当然也可以使用一个pipeline,通过对item加一个come_from的键来判断该是数据的来源
pipeline.process_item方法的第三个参数spider
spider参数即为创建的爬虫中的类,其有name属性(详见创建的myspider.py),可以通过name来判断数据的来源,从而对不同数据进行处理。
四.logging的使用
1 |
|
将item以warning的方式打印出来。与print不同的地方是,logging可以以更高的等级打印,而且可以将打印的内容保存到本地,方便后续的调试,为开发提供了方便。
这里使用warning是因为之前在settings.py中设置了打印的等级为warning,只有warning级别的日志才能被打印在命令提示符里。
指明输出日志的来源
组装Request对象
语法
1 |
|
在settings中设置User-Agent:
1 |
|
完整的scrapy.Request()对象
scrapy.Request(url[,callback,method=‘GET’,headers,body,cookies,meta,dont_filter=False])
- 注意事项
- callback:制定传入的url参数交给哪个解析函数去处理
- meta:实现在不同解析函数中传递数据,meta默认会携带部分信息,如下载延迟,请求深度等等。meta以字典形式定义,存取数据均与字典操作相同。
- dont_filter:让scrapy不再对url去重,即一个url地址可能访问多次。
- cookies只能储存在函数的参数中,将cookies用字符串形式放在headers中传入将不起作用。
直接使用上面的语句,输出的日志前面总是带有一个[root]标识,这表示了日志的来源,实际上,我们希望每一句日志都能体现出其来源,所以要使用下面的语句。
1 |
|
该函数实例化一个logging,就可以使用下面的语句输出
1 |
|
就可以在输出的日志前面加上[项目.spiders.爬虫名]的提示信息
日志的保存
在settings.py中设置
1 |
|
第一个.号表示当前目录,储存后的文件为log.log。
修改设置后日志不会在命令提示符中输出。
选择器(html解析器)
scrapy拥有自己的一套数据提取机制,成为选择器(selector),因为它们通过特定的xpath或者css表达式来选择HTML文件中的某个部分。scrapy选择器构建于lxml库之上,这意味着它们在速度和解析准确性上非常相似,用法也和之前讲的lxml解析基本相似。当然也可以脱离这些体系,使用bs4库进行解析。
selector的用法
1.xpath():
传入Xpath表达式,返回该表达式所对应的所有节点的selector list列表
2.css()
传入css表达式,返回该表达式所对应的所有节点的selector list列表
3.extract()
序列化该节点为Unicode字符串并返回list列表
re()
根据传入的正则表达式对数据进行提取,返回Unicode字符串列表,regex可以是一个已经编译的正则表达式,也可以是一个即将被编译的正则表达式字符串
更好地配对
方法的调用很简单,更多的时间是花在Xpath和css表达式的构造。scrapy提供了一种简便的方法来查看表达式是否正确、是否真的起作用。
另起一个命令行窗口,在其中输入
1 |
|
记得要加双引号
然后输入response.xpath(“…”)或者response.css(“…”)就可以抽取出当前网站的标签(返回的是Unicode格式)。
通过POST请求登录
一、通过FormRequest类来发送请求(类似Request)
首先查看network中发送请求的请求头,获取请求头中的类似用户名、密码的键值对
特别要注意cookie、token等值,要在源代码中找到对应的值,在python的字典中填入。
二、更方便的方法
FormRequest类有一个from_request的方法,可以自动寻找网页中的表单。
参数:
- response
- formdata 字典
- callback
#如果response中有两个表单怎么办?
可以查看该方法的源代码,通过给其传入xpath、css等参数来定位表单。
三、直接通过Request类来发送请求,不过要将其中的method参数改为POST
中间件
下载中间件
使用方法和pipeline类似,在文件中定义一个类,然后在setting中开启
默认方法
process_request(self,request,spider)
当每个request通过下载中间件时,该方法被调用,可以用来修改请求头等信息(请求时调用)。该方法只能返回None。
返回值:
- 若返回None,Scrapy将继续处理该Request,执行其他的中间件的相应方法,直到合适的下载器处理函数被调用,该Request被执行
- 若返回Response对象,Scrapy不会调用其他的方法,而直接返回该response。
- 若返回Request对象,Scrapy将停止调用其他中间件的process_request,并重新调度返回的Request。
process_response(self,request,response,spider)
当下载器完成http请求,传递响应给引擎时调用(获得请求时调用)。该方法必须return request或者response。
返回值:
- 当返回Response对象时,会将该response交给其他中间件的proce_response处理
- 当返回Request对象是,则中间件链停止,返回的Request会被重新调度并下载。
process_request还可以用于添加代理
用法:
1 |
|
定义Item
在文件items.py中编辑
1 |
|
该类继承自scrapy.Item类,实际上,该类的操作方法和字典一样,不同之处在于,该类使用时需要在items.py中使用scrapy.Field()
“声明”一个键值对,再在解析函数中实例化对象来使用。
这么做的好处
- 目前已知的好处就是防止手抖将键的名字写错,因为当解析函数中键的名字写错时函数会引发异常。
- 把数据交给pipeline时,可以用
isinstance()
来判断数据属于哪个Item,以便进行不同的处理
在mongdoDB中使用Item时的注意事项
由于mongdoDB只支持字典操作,所以要使用dict()函数将Item对象转化为字典类型再储存入数据库中
Scrapy中的CrawlSpider类
创建CrawlSpider爬虫
1 |
|
创建后会发现新建爬虫的父类变成了CrawlSpider,并且出现了一个rules的元组,即为规则。
rules元组冲包含了Rule类,包含以下参数
- LinkExtractor,即为链接提取器
- allow 一个正则表达式
- callback 提取出的url地址会交给callback处理
- follow 当前url地址的响应是否重新经过rules来提取(开启后相当于一个递归,通常在翻页时使用)
当然,也可以不使用rules规则,而在parse_item中yield出一个Request类,并定义一个解析方法来对网页进行解析。
优缺点:
该类为程序员提供了一个创建爬虫的更简便的方式,可以用更少的代码量完成同样的操作,但缺点是无法在解析方法之间传递数据(没有meta参数用于传递)
LinkExtractor参数补充:
- allow 满足正则表达式的url会被提取
- deny 满足正则表达式的url都不会被提取(优先级高于allow)
- allow_domains 会被提取的链接的domain
- deny_domains 不会被提取的链接的domain
- restrict_xpaths 使用xpath表达式,和allow共同作用过滤链接,该xpath满足的url地址都会被提取
spider.Rule常见参数
- Link_extractor:
- callback:
- follow:
- process_link:为一个函数对象,当从Link_extractor中过滤出一个url时会调用这个函数来处理url(一般用于过滤url)
- process_request:一个函数对象,当提取到一个request时会调用该函数(一般用于过滤request)