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
LOG_LEVEL = "WARNING"

三.将数据传输到pipe中

使用yield关键字
yield可以将数据逐个转入,可以使用的数据类型是Request,BaseItem,dict或者None。(不可以直接返回列表!!)

在此之前

使用pipe需要先在设置中开启pipeline,在setting.py中取消列代码的注释:

1
2
3
ITEM_PIPELINES = {
'firstscrapy.pipelines.FirstscrapyPipeline': 300,
}

字典中的键表示pipeline的名字,值表示这个pipeline的权重,数据会先结果权重小的pipeline再经过权重大的。

为什么要有多个pipeline

  • 一个项目可能有多个爬虫,爬取不同的网站产生不同的数据,所以需要多个pipeline对数据进行处理。
  • 当然也可以使用一个pipeline,通过对item加一个come_from的键来判断该是数据的来源

pipeline.process_item方法的第三个参数spider

spider参数即为创建的爬虫中的类,其有name属性(详见创建的myspider.py),可以通过name来判断数据的来源,从而对不同数据进行处理。


四.logging的使用

1
2
import logging
logging.warning(item)

将item以warning的方式打印出来。与print不同的地方是,logging可以以更高的等级打印,而且可以将打印的内容保存到本地,方便后续的调试,为开发提供了方便。
这里使用warning是因为之前在settings.py中设置了打印的等级为warning,只有warning级别的日志才能被打印在命令提示符里。

指明输出日志的来源



组装Request对象

语法

1
yield scrapy.Rquest(next_page_url, call_back=self.parse)

在settings中设置User-Agent:

1
USER-AGENT = 'Mozilla/5.0'

完整的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
logger = logging.getlogger(__name__)

该函数实例化一个logging,就可以使用下面的语句输出

1
logger.warning(item)

就可以在输出的日志前面加上[项目.spiders.爬虫名]的提示信息

日志的保存

在settings.py中设置

1
LOG_FILE = "./log.log"

第一个.号表示当前目录,储存后的文件为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
scrapy shell "/爬取网站的网址"

记得要加双引号
然后输入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
2
request.meta["proxy"] = "http://124.115.126.76:808"
#代理的形式为:协议+ip地址+端口


定义Item

在文件items.py中编辑

1
2
3
4
class FirstscrapyItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass

该类继承自scrapy.Item类,实际上,该类的操作方法和字典一样,不同之处在于,该类使用时需要在items.py中使用scrapy.Field()“声明”一个键值对,再在解析函数中实例化对象来使用。
这么做的好处

  • 目前已知的好处就是防止手抖将键的名字写错,因为当解析函数中键的名字写错时函数会引发异常。
  • 把数据交给pipeline时,可以用isinstance()来判断数据属于哪个Item,以便进行不同的处理

在mongdoDB中使用Item时的注意事项

由于mongdoDB只支持字典操作,所以要使用dict()函数将Item对象转化为字典类型再储存入数据库中



Scrapy中的CrawlSpider类

创建CrawlSpider爬虫

1
scrapy genspider -t crawl name domain

创建后会发现新建爬虫的父类变成了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)



scrapy爬虫框架学习笔记
http://zhouhf.top/2022/01/23/scrapy爬虫框架学习笔记/
作者
周洪锋
发布于
2022年1月23日
许可协议