scrapy的运用
scrapy的安装网上教程很多,直接跳过,开始运用
( 官方文档)
scrapy是什么
Scrapy是一种用于抓取网站和提取结构化数据的应用程序框架,可用于数据挖掘、信息处理等。
什么人学习scrapy
- 有一定的python基础以及对爬虫的原理有简单的理解
- 想要快速部署大规模网站数据采集
- 已经使用python采集过很多网站,但是感觉针对不同网站写不同的代码这个工作比较重复
初识scrapy
最开始的命令创建scrapy startproject tutorial
解释:创建命令中tutorial是可变的,根据自己的工程命名。
tutorial/
scrapy.cfg # 用于部署的文件,一般用于scrapyd
tutorial/ # project's Python module, you'll import your code from here
__init__.py
items.py # 这个文件就只有类来存变量,对于小型的爬虫,可用可不用,后面再解释
middlewares.py # 中间件,就是实现各种功能,如处理错误码,重新请求等。
pipelines.py # 数据最后的输出处理,输出控制台、文件或者数据库中
settings.py # 配置文件
spiders/ # 这个文件里放你的爬虫代码文件,也就是创建一个.py文件
__init__.py
那么在spiders文件夹中创建一个叫quotes_spider.py的文件,并将下面的代码放在这个文件里面
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'quotes-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
然后在命令行中进入tutorial/文件,也就是进入第一层(有两个tutorial文件夹,只进入第一个)中,运行scrapy crawl quotes,好的,你的scrapy就完成了。
注意:你是否注意到了,运行命令中最后是quotes,这个正是与上面代码中的name=“quotes”,如果你修改了这个值,那么相应的quotes也应该作修改。那么,聪明的你是否想到了,如果你在同一个工程写两个类爬虫类,那么 可以写两个不同的name。
scrapy的流程
有了上一节的基础,你应该对scrapy有了初步的了解,那么scrapy的调度流程请看下图所示,第一次可能有些懵,不知道这些是啥东西,没关系,现在你只需要记住这张图就行了,随着深入理解,你会慢慢明白它们的含义。
对流程图的初步讲解
######################################################
首先,请看红色的Spiders,我们可以把它理解为上一节中的quotes_spider.py文件中的 QuotesSpider(scrapy.Spider)类,我们的爬虫从它开始出发(实际上不是,之前还会运行配置文件settings.py,现在不用管),运行第一个函数start_requests(),在这个函数里面我们有了初始爬虫链接,并用scrapy.Request(url=url, callback=self.parse)这个函数是将爬虫链接放入Spider Middlewares中包装一下(如加上cookies,headers,代理之类的),yield将包装后的链接通过Scrapy Engine放入Scheduler中。
#####################################################
Scheduler用于调度(比如什么时候可以将爬虫链接给Downloader等等)。当爬虫链接Requests给了Downloader后,访问互联网获取Response,返回Spiders。所以Scheduler与Downloader在这时我们都是使用的默认值,我们没有直接和它们接触。
#####################################################
parse(self, response)函数用于接收Response,本文中的代码是直接将数据写入文件中,结束这个爬虫链接。当然,最好是使用yield函数(样例网上搜),将数据放入Item Pipeline,在那里面进行数据清洗(输出控制台、写入文件或者存入数据库)。
进一步了解scrapy
对于爬虫,针对不同的情况,选择不同的采集策略,因此本节将叙述不同情况下,如何运用scrapy进行逐一解决
1、限制爬虫速率与增加爬虫速率
3、日志问题
4、headers
5、中间件(Middlewares)
1)数值的含义
表示优先级,数字越大优先级越低,也就是越后加载
2)关于DownloaderMiddlewares
使用代理与cookie中间件
有时进行爬虫时,网站会封IP(如世纪佳缘),这时一般人会使用代理池,因此你可以在两个地方设置代理与cookies,一个是Request类中的meta中设置,也就是说如下所示:
scrapy.Request(url, cookies=self.cookies, meta={'proxy':'http://192.168.110.52:5555'}, callback=self.parse)
但是显然这样不够灵活,因此,最好使用中间件,你可以重新定义ProxyMiddleware与CookiesMiddleware,例子可以看看下面的这个例子。
处理超时,链接错误(也就是response之前的error)
举个例子,你需要处理10060链接错误,那么你需要在middlewares.py文件中新定义一个类ReRetryMiddleware,这个类继承了RetryMiddleware类,重写了process_exception方法,实现了遇见链接错误等,就更换代理:
from scrapy.downloadermiddlewares.retry import RetryMiddleware
class ReRetryMiddleware(RetryMiddleware):
"""
overwrite process_exception
由于代理引起的连接错误,所以更改代理
"""
def process_exception(self, request, exception, spider):
if isinstance(exception, self.EXCEPTIONS_TO_RETRY) \
and not request.meta.get('dont_retry', False):
######################下面这段是我自定义的,为了解决链接问题######
try:
response = requests.get('http://192.168.110.52:5555/random')
if response.status_code == 200:
request.meta['proxy'] = "http://{}".format(response.text)
except ConnectionError:
pass
#################################################################
return self._retry(request, exception, spider)
当然,我们还需要在settings.py文件中更改配置:
'scrapy_redis_shijijiayuan.middlewares.ReRetryMiddleware': 100, 添加我定义的中间件
"scrapy.downloadermiddlewares.retry.RetryMiddleware": None, 关闭scrapy提供的中间件
处理response错误
首先,scrapy默认丢弃除了200码以外的所有response,这显然会漏掉很多链接,因此在爬虫一开始就加上,你认为你需要处理的问题码,如下所示:
class MySpider(CrawlSpider):
handle_httpstatus_list = [404]
def parse(self, response):
if int(response.status) == 404:
logging.error("处理")
6、Item的理解
在项目提取的字段往往有很多,这可能会造成key值手写错误,因此,使用Item可以避免这种情况的发生。
7、500错误
现象:
原因:在settings.py文件中,默认了遵从robots.txt规则,将True改为False。
8、编码问题
一般来说python3采集的数据都是bytes数据,特别是将数据写入文件时,需要使用wb模式,即open(’’, ‘wb’)。