Scrapy框架的学习
1. Scrapy的工作原理
2. 实现一个简单的爬虫框架所需要进行的步骤
1. 创建一个start.py文件
这个纯粹是为了不想每次启动爬虫都重新输入一下命令(毕竟也不是记得所有爬虫的名字)
1 | # 导入cmdline用于执行cmd命令的 |
2. 修改settings.py
2.1 ROBOTSTXT_OBEY = False
默认选项是True
,即遵守robots.txt
的规则。而这个robots.txt
是遵循Robot
协议的一个文件,它保存在网站的服务器中,作用是:告诉搜索引擎,本网站哪些目录下的网页 不希望 你进行爬取收录。在Scrapy启动后,会在第一时间访问网站的robots.txt
文件,然后决定该网站的爬取范围。
当然,我们并不是在做搜索引擎,而且在某些情况下我们想要获取的内容恰恰是被robots.txt
所禁止访问的。所以,有些时候,我们就要将此配置项设置为False
,拒绝遵守robot
协议。
2.2 启用DEFAULT_REQUEST_HEADERS
因为现在的大部分网站都进行了反爬虫措施,比如知乎,豆瓣等等。作为一个spider就要学会反反爬虫。最简单实用的措施就是设置headers。
在settings.py
里面开启DEFAULT_REQUEST_HEADERS
,根据需要设置相关内容即可,主要就是配置User-Agent
1 | DEFAULT_REQUEST_HEADERS = { |
2.3 如果想要将爬取的数据记录在文件(json格式等)中,需要开启ITEM_PIPELINES
1 | ITEM_PIPELINES = { |
Ps:后面的数字表示优先级,数字越小表示优先级越高
3. 完善items.py
默认有一个Item
类,里面需要填写你要获取的内容,如下:
1 | class HouseItem(scrapy.Item): |
Field
对象用于为每个字段指定元数据。我们可以为每个字段指定任何种类的元数据。对Field
对象接受的值没有限制。处于同样原因,没有所有可用元数据键的参考列表。Field
对象中定义的每个键可以由不同的组件使用,并且只有那些组件知道它。Field
对象的主要目标是提供一种在一个地方定义所有字段元数据的方法。通常,那些行为取决于每个字段的组件使用某些字段键来配置该行为、
4. 创建spider.py
运行cmd命令
scrapy genspider xxx(爬虫名字) “XXX(网址域名)”
里面默认应该有name(爬虫名字), allowed_domains(允许爬取的网站的域名), start_urls(首先爬取的网页的url,注意这个是一个列表,意味着可以有很多网址)
还有一个parse(self, response)
方法:这个是用来具体在爬取到一个页面,然后对这个页面进行解析的一个方法,最后需要返回爬取的东西(即上一步定义过的一些属性)
在这个parse
方法中,我们需要定义爬取该网页的什么内容。首先需要了解网页的组成。然后通过浏览器带有的右键->检查
来查看网页元素,然后获取我们所需要的内容在网页的什么地方。可以学习xPath的表示方法,不过直接找到该元素,然后右键->Copy->Copy xPath
即可轻松获取到xpath
1 | def parse(self, response): |
5. 修改pipelines.py
该文件中默认有process_item(self, item, spider)
方法,该方法主要是将获取到的item写入文件。在此之前,我们需要定义open_spider(self, spider)和close_spider(self, spider)
方法
当然,也可以先写一个__init__(self)
方法
1 | class HousePipeline(object): |
基本上就大功告成了。最后只需要python start.py
即可。
3. CrawlSpider
创建爬虫文件:
scrapy genspider -t crawl xxx(爬虫名字) “XXXX(网站域名)”
需要使用LinkWxtractor
和Rule
。这两个东西决定爬虫的具体走向。
- allow设置规则的方法:要能够限制在我们想要的
url
上面,不要跟其他的url
产生相同的正则表达式即可 - 什么情况下使用
follow
:如果在爬取页面的时候,需要将满足当前条件的url
再进行跟进,那么就设置为True
,否则设置为False
- 什么情况下指定
callback
:如果这个url对应的页面,只是为了获取更多的url
,并不需要里面的数据,那么就可以不指定callback
,如果想要获取url
对应页面中的数据,那么就需要指定一个callback
来解析数据
如下:
1 | class WxappSpiderSpider(CrawlSpider): |
Ps: 还有一个稍微不同的地方,因为这个pipelines的方式有很多,这边我们采取了exporter的方式,写法如下:
1 | from scrapy.exporters import JsonLinesItemExporter |
Scrapy Shell
我们想要在爬虫中使用xpath, beautifulsoup, 正则表达式, css选择器
等来提取想要的数据。但是因为Scrapy
是一个比较重的框架。每次运行起来都需要等待一段时间。因此要去验证我们写的提取规则是否正确,是一个比较麻烦的事情。因此Scrapy
提供了一个shell
,用来方便的测试规则。当然也不局限于这一个功能。
如果想要执行Scrapy
命令,需要进入到Scrapy
所在的环境中
如果想要读取某个项目的配置信息,那么先应该进入到这个项目中,再执行下面的命令:
scrapy shell XXX(网站地址)
然后,就像在写代码一样操作即可
Request和Response对象
GET & POST
在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET
和POST
GET:从指定的资源请求数据
POST:向指定的资源提交要被处理的数据
GET | POST | |
---|---|---|
后退按钮/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交) |
缓存 | 能被缓存 | 不能缓存 |
对数据长度的限制 | 是的。当发送数据时,GET方法向URL添加数据;URL的长度是被限制的(URL的最大长度是2048个字符) | 无限制 |
对数据类型的限制 | 只允许ASCII字符 | 没有限制,也允许二进制字符 |
安全性 | 与POST相比,GET的安全性较差,因为发送的数据是URL的一部分。(在发送密码或其他敏感信息的时候绝对不要使用GET!) | POST比GET更安全,因为参数不会被保存在浏览器历史或web服务器日志中 |
可见性 | 数据在URL中对所有人是可见的 | 数据不会显示在URL中 |
Request对象
Request对象在我们写爬虫时,爬去一页的数据需要重新发送一个请求的时候调用。这个类需要传递一些参数,较常用的有以下:
-
url
:这个request对象发送请求的url
-
callback
:在下载器下载完相应的数据后执行的回调函数 -
method
:请求的方法,默认为GET方法,可以设置为其他方法(如POST)如果我们想要在请求数据的时候发送
post
对象,那么这时候需要使用Request
的子类FormRequest
来实现。如果想要在爬虫一开始的时候我们就发送POST
请求,那么需要在爬虫类中重写start_requests(self)
方法,并且不再调用start_urls
里的url
。(如果不重写的话,就回默认从startUrls
中读取url
,并且是发送GET
请求) -
headers
:请求头,对于一些固定的设置,放在settings.py
中指定就可以了。对于那些非固定的,可以在发送请求的时候指定 -
meta
:比较常用。用于在不同的请求之间传递数据 比如,我们在浏览概览页和浏览详情页的时候,有些东西我们在概览页就可以得知,例如文章名字,作者,发布时间等等,那么我们在详情页中就可以只获取文章的内容,那么我们有些数据就需要共享,可以写在meta中。
-
encoding
:编码,默认为utf-8
-
dont_filter
:表示不由调度器过滤,在执行多次重复的请求的时候用的比较多不发送重复的请求~~
-
errback
:在发生错误的时候执行
Response对象
Response
对象一般是由Scrapy
给你自动构建的。因此开发者不需要关心如何创建Response
对象,而是如何使用。Response
对象有很多属性,可以用来提取数据的。主要有以下属性:
-
meta
:从其他请求传过来的meta属性。可以用来保持多个请求之间的数据连接 -
encoding
:返回当前字符串编码和解码的格式 -
text
:将返回来的数据作为unicode
字符串返回其实
text
和body
保存的都是网页源代码,但是body
是没有解码过的,而text
是解码成unicode
字符的,如果想要解码成别的字符,则可以通过body
自己解码 -
body
:将返回来的数据作为byte
字符串返回(在网络和硬盘之间通信的时候,其实用的是byte
类型) -
xpath
:xpath
选择器 -
css
:css
选择器
下载文件和图片
Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的item pipelines。这些pipelines有些共同的方法和结构,我们称之为media pipeline
。一般来说你会使用File pipelines
或者Image Pipeline
为什么要使用scrapy内置的下载方法?
- 可避免重新下载最近已经下载过的数据
- 可以方便的指定文件存储的路径
- 可以将下载的图片转换成通用的格式,比如jpg, png等
- 可以方便的生成缩略图
- 可以方便的检测图片的宽和高,确保满足最小限制
- 异步下载,效率非常高
下载文件的Files Pipeline
当使用Files Pipeline
下载文件的时候,按照以下步骤来完成:
- 定义好一个
Item
,然后在这个item
中定义两个属性,分别为file_urls
以及files
。file_urls
是用来存储需要下载的文件的url链接,需要给一个列表。 - 当文件下载完成后,会把文件下载的相关信息存储到
item
的files
属性中。比如下载路径,下载的url
和文件的校验码等 - 在配置文件的
settings.py
中设置FILE_STORE
,这个配置是用来设置文件下载下来的路径 - 启动
pipeline
:在ITEM_PIPELINES
中设置scrapy.pipelines.files.FilesPipeline:1
下载图片的Images Pipeline
当使用Images Pipeline
下载文件的时候,按照以下步骤来完成:
-
定义好一个
Item
,然后在这个item
中定义两个属性,分别为image_urls
以及images
。Image_urls
是用来存储需要下载的图片的url链接,需要给一个列表 -
当文件下载完成后,会把文件下载的相关信息存储到
item
的images
属性中。比如下载路径、下载的url和图片的校验码等等呢个 -
在配置文件的
settings.py
中设置IMAGES_STORE
,这个配置是用来设置图片下载下来的路径 -
启动
pipeline
:在ITEM_PIPELINES
中设置scrapy.pipelines, images,scrapy.pipelines.images.ImagesPipeline:1