scrapy学习笔记(二)进阶使用

 

From:https://www.imooc.com/article/21839

scrapy提升篇之配置:https://segmentfault.com/a/1190000009321902

 

 

前面我写了一篇《scrapy快速入门》,简单介绍了一点scrapy的知识。这次就来介绍一些scrapy的进阶知识,做一些真正有用的爬虫来。

scrapy组件介绍

首先先来介绍一下scrapy的体系结构和组件。

  • scrapy引擎。顾名思义,它负责调用爬虫爬取页面并将数据交给管道来处理。
  • 调度程序。调度程序从引擎获取请求,然后将这些请求交给相应的处理者来处理。
  • 下载器。下载器负责获取web页面,然后将它们交给引擎来处理。
  • 爬虫。这是我们要编写的部分,爬虫负责从页面抽取要处理的数据,然后交由管道来处理。
  • 项目管道。爬虫抽取出来的数据,就要交给管道来处理,我们可以编写自己的管道来清洗、验证和持久化数据。
  • 下载器中间件。下载器中间件在下载器和scrapy引擎之间工作,我们可以利用下载器中间件在将页面交给爬虫之前做一些事情。scrapy内置了一些下载器中间件,这些中间件将在后面介绍。
  • 爬虫中间件。爬虫中间件可以让我们控制爬虫的回调等等。在后面会介绍一些内置的爬虫中间件。

下面是scrapy官网的结构图,可以帮助我们理解scrapy的体系。

 

项目(Item)

在以前的爬虫中我们都是直接返回一个字典,其实这并不是最佳实践。scrapy提供了一个Item基类,我们可以通过继承这个类定义自己的结构化数据,比到处传递字典更好。下面是官方文档的例子。

import scrapyclass Product(scrapy.Item):name = scrapy.Field()price = scrapy.Field()stock = scrapy.Field()last_updated = scrapy.Field(serializer=str)

这些项目类一般都定义在scrapy项目的items.py文件中。定义好之后,在爬虫中我们就不应该在反掌字典了,而是初始化并返回我们自定义的Item对象。

请求和响应对象

scrapy通过请求和响应对象来处理网页请求,这部分的文档可以参考https://doc.scrapy.org/en/latest/topics/request-response.html。请求和响应还有一些子类,可以帮助我们完成更具体的工作。例如Request的子类FormRequest就可以帮助我们模拟用户登录。

有时候需要模拟用户登录,这时候可以使用FormRequest.from_response方法。这时候爬虫功能稍有变化,parse函数用来发送用户名和密码,抽取数据的操作放在回调函数中进行。

import scrapyclass LoginSpider(scrapy.Spider):name = 'example.com'start_urls = ['http://www.example.com/users/login.php']def parse(self, response):return scrapy.FormRequest.from_response(response,formdata={'username': 'john', 'password': 'secret'},callback=self.after_login)def after_login(self, response):# 检查是否登录成功if "authentication failed" in response.body:self.logger.error("Login failed")return# 在这里继续爬取数据

管道(pipeline)

管道用来处理爬虫抽取到的数据,我们可以通过管道对数据进行验证和持久化等操作。管道其实就是带有process_item(self, item, spider)函数的一个普通类。下面是scrapy官方文档的例子,这个例子验证获取到的数据是否存在价格字段,并丢弃没有价格字段的无效数据。这里还引用了scrapy预定义的DropItem异常,这个异常必须在管道中抛出,表示管道应该丢弃这个数据。如果想了解scrapy异常,可以查看官方文档。

from scrapy.exceptions import DropItemclass PricePipeline(object):vat_factor = 1.15def process_item(self, item, spider):if item['price']:if item['price_excludes_vat']:item['price'] = item['price'] * self.vat_factorreturn itemelse:raise DropItem("Missing price in %s" % item)

管道不是一定义好就能用的,还需要在配置文件settings.py中激活。

ITEM_PIPELINES = {'myproject.pipelines.PricePipeline': 300,'myproject.pipelines.JsonWriterPipeline': 800,
}

将数据保存到MongoDB的管道

管道除了验证数据,还可以将数据保存到数据库中。这时候仅仅一个process_item(self, item, spider)函数就不够了。所以操作数据库的管道还应该包含几个函数用于建立和关闭数据库连接。

下面的例子也是scrapy官方文档的例子,演示了持久化数据管道的用法。这个管道是从类方法from_crawler(cls, crawler)中初始化出来的,该方法实际上读取了scrapy的配置文件。这和直接将数据库连接写在代码中相比,是更加通用的方式。初始化和关闭数据库连接的操作都在对应的方法中执行。

import pymongoclass MongoPipeline(object):collection_name = 'scrapy_items'def __init__(self, mongo_uri, mongo_db):self.mongo_uri = mongo_uriself.mongo_db = mongo_db@classmethoddef from_crawler(cls, crawler):return cls(mongo_uri=crawler.settings.get('MONGO_URI'),mongo_db=crawler.settings.get('MONGO_DATABASE', 'items'))def open_spider(self, spider):self.client = pymongo.MongoClient(self.mongo_uri)self.db = self.client[self.mongo_db]def close_spider(self, spider):self.client.close()def process_item(self, item, spider):self.db[self.collection_name].insert_one(dict(item))return item

使用文件和图片管道

文件和图片管道处理过程

除了自己编写管道之外,scrapy还预定义了几个管道,可以帮助我们方便的保存文件和图片。这些管道有以下特点:

  • 可以避免重复下载最近的文件。
  • 指定文件保存位置(文件系统或者亚马逊S3)

对于图片管道来说还有额外功能:

  • 将图片转换成常见格式(JPG)和模式(RGB)
  • 生成图片缩略图
  • 只下载大于某长宽的图片

使用文件管道的过程如下:

  1. 首先需要Item类中有file_urlsfiles两个属性,然后在爬虫中将想爬取的文件地址放到file_urls属性中,然后返回
  2. 在Item传递到文件管道的时候,调度程序会用下载器将地址对应的文件下载下来,将文件属性(包括保存路径等)放到files属性中,file_urlsfiles中是一一对应的

使用图片管道的过程是相似的,不过要操作的属性是image_urlsimages

如果你不想使用这几个属性,其实属性名也是可以修改的,需要修改下面四个属性。

FILES_URLS_FIELD = 'field_name_for_your_files_urls'
FILES_RESULT_FIELD = 'field_name_for_your_processed_files'
IMAGES_URLS_FIELD = 'field_name_for_your_images_urls'
IMAGES_RESULT_FIELD = 'field_name_for_your_processed_images'

管道配置

要启用文件管道和图片管道,同样需要激活,当然如果同时激活这两个管道也是可行的。

ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 1}
# 或者
ITEM_PIPELINES = {'scrapy.pipelines.files.FilesPipeline': 1}

文件和图片保存位置需要分别指定。

FILES_STORE = '/path/to/valid/dir'
IMAGES_STORE = '/path/to/valid/dir'

文件和图片管道可以避免下载最近的文件,对应的文件过期时间也可以配置,单位是天。

# 120 days of delay for files expiration
FILES_EXPIRES = 120# 30 days of delay for images expiration
IMAGES_EXPIRES = 30

图片管道可以在保存图片的时候同时生成缩略图,缩略图配置是一个字典,键是缩略图的名字,值是缩略图长和宽。

IMAGES_THUMBS = {'small': (50, 50),'big': (270, 270),
}

最后图片会保存成下面这样,图片的文件名是图片路径的SHA1哈希值。

/图片保存路径/full/完整图片.jpg
/图片保存路径/thumbs/small/小图片.jpg
/图片保存路径/thumbs/big/中图片.jpg

如果不想使用SHA1哈希值作为文件名,可以继承ImagesPipeline基类并重写file_path函数,这里是另外一位简书作者的爬虫项目,他重写了这个函数。我们可以作为参考。

如果要过滤小图片,启用下面的配置。默认情况下对图片尺寸没有约束,所以所有图片都会下载。

IMAGES_MIN_HEIGHT = 110
IMAGES_MIN_WIDTH = 110

默认情况下文件和图片管道不支持重定向,遇到需要重定向的链接意味着下载失败,不过我们也可以启用重定向。

MEDIA_ALLOW_REDIRECTS = True

下载器中间件

下载器中间件可以在scrapy引擎和爬虫之间操纵请求和响应对象。要启用下载器中间件,启用下面的配置。这是一个字典,字典的键是要启用的中间件,值会用来比较中间件之间的顺序。

DOWNLOADER_MIDDLEWARES = {'myproject.middlewares.CustomDownloaderMiddleware': 543,
}

如果希望禁用某些内置的中间件,可以将值设置为None

DOWNLOADER_MIDDLEWARES = {'myproject.middlewares.CustomDownloaderMiddleware': 543,'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
}

编写自己的下载器中间件

自定义下载器中间件应该继承scrapy.downloadermiddlewares.DownloaderMiddleware类,该类有如下几个方法,用于操纵请求和响应,我们只要重写这几个方法即可。这几个方法的作用请参考官方文档,它们比较复杂,所以我就不说了。

  • process_request(request, spider)
  • process_response(request, response, spider)
  • process_exception(request, exception, spider)

内置的下载器中间件

scrapy内置了14个下载器中间件,我简单介绍一下其中的几个。详情参考文档。

CookiesMiddleware

用于在爬虫发起请求和获取响应的时候保持Cookie。

DefaultHeadersMiddleware

用于设置请求的默认请求头。

该配置位于DEFAULT_REQUEST_HEADERS,默认值如下。

{'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'en',
}

HttpProxyMiddleware

设置使用的网络代理。

UserAgentMiddleware

设置使用的用户代理。

爬虫中间件

与下载器中间件类似,启用爬虫中间件需要一个字典来配置。

SPIDER_MIDDLEWARES = {'myproject.middlewares.CustomSpiderMiddleware': 543,
}

想要关闭某个中间件的时候传递None值。

SPIDER_MIDDLEWARES = {'myproject.middlewares.CustomSpiderMiddleware': 543,'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None,
}

自定义爬虫中间件

编写自己的爬虫中间件需要继承scrapy.spidermiddlewares.SpiderMiddleware基类,并重写以下几个方法。

  • process_spider_input(response, spider)
  • process_spider_output(response, result, spider)
  • process_spider_exception(response, exception, spider)
  • process_start_requests(start_requests, spider)

内置的爬虫中间件

scrapy内置了5个爬虫中间件,这里我仅介绍一两个。

DepthMiddleware

该中间件记录了爬虫爬取请求地址的深度。

我们可以使用DEPTH_LIMIT来指定爬虫爬取的深度。

UrlLengthMiddleware

该中间件会过滤掉超出最大允许长度的URL,爬虫不会访问这些超长URL。

最大长度通过URLLENGTH_LIMIT配置来指定,默认值是2083。

URLLENGTH_LIMIT = 2083

内建服务

scrapy内置了几个服务,可以让我们使用scrapy更加方便。

日志

爬虫类定义了log函数,我们可以方便的在爬虫类中记录日志。

import scrapyclass MySpider(scrapy.Spider):name = 'myspider'start_urls = ['https://scrapinghub.com']def parse(self, response):self.logger.info('Parse function called on %s', response.url)

日志相关的配置,点击可以跳转到官方文档查看详细信息。

  • LOG_FILE
  • LOG_ENABLED
  • LOG_ENCODING
  • LOG_LEVEL
  • LOG_FORMAT
  • LOG_DATEFORMAT
  • LOG_STDOUT
  • LOG_SHORT_NAMES

发送电子邮件

有时候我们可能希望爬到一定数量的数据就发送电子邮件进行提醒。scrapy也内置了这个功能。我们可以通过构造函数参数来创建邮件发送器。

from scrapy.mail import MailSender
mailer = MailSender(这里是构造函数参数)

也可以从配置文件实例化。

mailer = MailSender.from_settings(settings)

然后调用send方法就可以发送邮件了。

mailer.send(to=["someone@example.com"], subject="Some subject", body="Some body", cc=["another@example.com"])

电子邮件相关配置参考官方文档。

web服务

这个功能本来是写在官方文档内建服务条目下的,但是实际上这个功能已经变成了一个单独的项目,需要额外安装。

pip install scrapy-jsonrpc

然后在扩展中包含这个功能。

EXTENSIONS = {'scrapy_jsonrpc.webservice.WebService': 500,
}

还需要在配置中启用该功能。

JSONRPC_ENABLED = True

然后在爬虫运行的时候访问http://localhost:6080/crawler即可查看爬虫运行情况了。

该项目的其他配置查看其官方文档。

优化爬虫

爬虫项目可以通过修改一些配置进行优化。

增大并发数

并发数可以通过下面的配置进行设置。具体的并发数需要根据服务器的CPU等设置来进行更改。一般来说服务器CPU使用在80%-90%之间利用率比较高。我们可以从并发数100开始反复进行测试。

CONCURRENT_REQUESTS = 100

增大线程池

scrapy通过一个线程池来进行DNS查询,增大这个线程池一般也可以提高scrapy性能。

REACTOR_THREADPOOL_MAXSIZE = 20

降低日志级别

默认情况下scrapy使用debug级别来打印日志,通过降低日志级别,我们可以减少日志打印,从而提高程序运行速度。

LOG_LEVEL = 'INFO'

禁用Cookie

如果不是必须的,我们可以通过禁用Cookie来提高性能。如果需要登录用户才能爬取数据,不要禁用Cookie。

COOKIES_ENABLED = False

关闭重试

频繁重试可能导致目标服务器响应缓慢,我们自己访问不了别人也访问不了。所以可以考虑关闭重试。

RETRY_ENABLED = False

减少下载超时

如果网络连接比较快的话,我们可以减少下载超时,让爬虫卡住的请求中跳出来,一般可以提高爬虫效率。

DOWNLOAD_TIMEOUT = 15

关闭重定向

如果不是必要的话,我们可以关闭重定向来提高爬虫性能。

REDIRECT_ENABLED = False

自动调整爬虫负载

scrapy有一个扩展可以自动调节服务器负载,它通过一个算法来确定最佳的爬虫延时等设置。它的文档在这里。

相关配置如下,点击链接可以跳转到对应文档。

  • AUTOTHROTTLE_ENABLED
  • AUTOTHROTTLE_START_DELAY
  • AUTOTHROTTLE_MAX_DELAY
  • AUTOTHROTTLE_TARGET_CONCURRENCY
  • AUTOTHROTTLE_DEBUG
  • CONCURRENT_REQUESTS_PER_DOMAIN
  • CONCURRENT_REQUESTS_PER_IP
  • DOWNLOAD_DELAY

部署爬虫

官方文档介绍了两种部署爬虫的方式,可以将爬虫部署到服务器上远程执行。第一种是通过Scrapyd开源项目来部署,也是这里要介绍的方式。第二种是通过scrapy公司提供的商业收费版服务Scrapy Cloud部署,推荐有财力的公司考虑。

服务器端

首先服务器需要安装scrapyd包,如果是Linux系统还可以考虑使用对应的包管理器来安装。

pip install scrapyd
apt-get install scrapyd

然后运行scrapyd服务,如果使用系统包管理器安装,那么可能已经配置好了systemd文件。

scrapyd
# 或者
systemctl enable scrapyd

scrapyd附带了一个简单的web界面可以帮助我们查看爬虫运行情况,默认情况下访问http://localhost:6800/来查看这个界面。

scrapyd的配置文件可以是~/.scrapyd.conf或者/etc/scrapyd/scrapyd.conf。下面是一个简单配置,绑定所有端口,这样一来从任意位置都可以访问web界面。

[scrapyd]
bind_address = 0.0.0.0

scrapyd的功能可以查看其API文档。

客户端

客户端如果要上传爬虫,可以通过服务器API的端点addversion.json来实现,或者安装一个简便工具scrapyd-client。

首先安装客户端工具。

pip install scrapyd-client

这个客户端目前好像有bug,在windows下运行scrapy-deploy命令不会直接执行,而是弹出一个文件关联对话框。如果你遇到这种情况,可以找到Python安装路径下的脚本路径(例如C:\Program Files\Python36\Scripts),然后编写一个scrapyd-deploy.bat批处理文件,内容如下。这样就可以正常运行了。

@"c:\program files\python36\python.exe" "c:\program files\python36\Scripts\scrapyd-deploy" %*

然后切换到项目路径,编辑项目全局配置文件scrapy.cfg,添加部署路径。

[deploy]
url = http://192.168.64.136:6800/
project = quotesbot

然后直接运行scrapy-deploy命令,就可以看到项目已经成功部署到服务器上了。

 

运行爬虫需要使用scrapyd的API,例如使用curl,可以用下面的命令。

 curl http://192.168.64.136:6800/schedule.json -d project=quotesbot -d spider=toscrape-css

或者使用Jetbrains 系列IDE 2017.3的基于编辑器的HTTP客户端。

然后点击Jobs就可以看到爬虫已经开始运行了。如果要查看状态,点击右边的log即可。

以上就是scrapy的进阶介绍了,利用这些功能,我们可以编写更加实用的爬虫,并将它们部署到服务器上。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王爽 汇编语言第三版 第7章 --- 更灵活的定位内存地址的方法(可以理解为 数组形式的内存定位)

汇编语言(第三版)王爽著 的十二个实验:https://blog.csdn.net/OrangeHap/article/details/89791064 大小端 字节对齐 对于 arm,intel 这种 x86 构架的复杂指令 CPU,整数在内存中是倒着存放的,低地址放低位&…

从文本分类问题中的特征词选择算法追踪如何将数学知识,数学理论迁移到实际工程中去...

博文转载请注明作者和出处(作者:finallyliuyu :出处博客园) 附:《卡方特征词选择算法》 《DF特征词选择算法》 一.数学背景 将数学知识、数学理论以及数学思想迁移到实际工程问题中,经常会促进工程问题的圆…

裁掉杰森伯恩,招揽人工智能,AI间谍厉害在哪?

来源:智能相对论 作者: 岳文纶摘要:CIA宣布,计划用人工智能取代间谍。其技术开发副主任Dawn Meyerriecks表示,CIA正在适应新的情形,其主要对手是一台机器,而不是一名外国间谍。间谍&#xff0…

一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-通过SQL实现特殊业务...

前面的四篇文章演示ORM的一些常规操作与配置,通过前面的文章,应用开发人员要可以使用ORM开发出简单的应用,但是,ORM也不是万能钥匙,在业务应用中,还有很多是ORM解决不了的问题,对于这些问题&…

英特尔详解5G将如何助力VR的未来发展

来源:亿欧智库摘要:英特尔中国研究院通过重点研究通信和计算融合的方式,解释了5G在面对巨大数据洪流时数据处理和传输的方式,通过边缘计算的新方法,使VR达到传输要求。打造一个高效的通信和计算系统,通往我…

王爽 汇编语言第三版 第8章( 寻址方式 ) --- 数据处理的两个问题

第八章 数据处理的两个基本问题 8.6 综合应用 示例代码 1: assume cs:codesg,ds:datasgdatasg segmentdb 1024 dup (0) datasg endscodesg segmentstart:mov ax,datasgmov ds,axmov bx,60h ; 确定记录地址 ds:bxmov word ptr [bx0ch],38 ;…

综述AI未来:神经科学启发的类脑计算

来源:运筹OR帷幄 作者:周岩摘要:脑科学是一门实践性很强的交叉学科,包含了神经科学,医学,数学,计算科学等多门学科。随着近几年深度学习的迅速发展,人工智能成为了无论学术界还是互…

[翻译]Wine完全使用指南——从基本到高级[转]

转载自 : http://forum.ubuntu.org.cn/viewtopic.php?t72933为了回应最近网友的一些普遍问题,特此作以下说明: 1、如果发现wine的注册表没有相应的键值,要自己创建。有时候用命令不行的话,只能手动一个个添加。 2、wine还是一个…

Flask --- 框架快速入门

From:http://docs.jinkan.org/docs/flask/quickstart.html Flask 用户指南:http://docs.jinkan.org/docs/flask/index.html w3cschool.cn 的 Flask 教程:https://www.w3cschool.cn/flask/ 《Flask Web开发:基于Python的Web应用…

AI与基因科学的对话:从“人工智能”到“动物智能”

来源:亿欧网有人的地方就有江湖,巨头们一次次的“技术战役”就是现代江湖的样子。各家企业牢牢把握住科技就是第一生产力的关键,不断的较量平台、技术、场景、生态等多方面的综合实力,你方唱罢我登场好不热闹。在我们的认知中&…

顺序程序设计03 - 零基础入门学习C语言09

第三章:顺序程序设计03 让编程改变世界 Change the world by program 题目:输入三角形的三边长,求三角形面积。 已知三角形的三边长a,b,c,则该三角形的面积公式为: [caption id"attachment_64" align"a…

王爽 汇编语言第三版 第9章 转移指令的原理

第九章 转移指令的原理 汇编代码: assume cs:codesgcodesg segments: mov ax,bx ; mov ax,bx 的机器码占两个字节mov si, offset smov di, offset s0mov ax, cs:[si]mov cs:[di], axs0:nop ; nop 机器码占一个字节nopmov ax, 4c00hint 21h codesg ends end s 9…

触摸心灵-触觉感知和发展的模型

来源:计算机触觉触觉感知和发展的模型触觉感知模型是数学结构,试图解释触觉积累关于环境中的物体和试剂的信息的过程。 由于触觉是一种主动的感觉,即感觉器官在感觉过程中被移动,所以这些模型经常描述优化感知结果的运动策略。 触…

MFC 最详细入门教程

From:https://blog.csdn.net/wang18323834864/article/details/78621633/ Visual Studio 2019:https://visualstudio.microsoft.com/zh-hans/ 鸡啄米 ----- VS2010/MFC编程入门教程之目录和总结:http://www.jizhuomi.com/software/257.html …

没中、美这么大的统一市场,欧盟人工智能发展面临双重挑战

来源:澎湃新闻 作者:胡逸涵为在人工智能领域追赶中美两国,近日,欧盟将2020年前对人工智能(AI)的投资额增加约70%,至15亿欧元。欧盟希望到2020年底,整个欧盟在AI技术领域&#xff0…

人生的闲言碎语

1.人的一生 选对老师,智慧一生;选对伴侣,幸福一生;选对环境,快乐一生;选对朋友,甜蜜一生;选对行业,成就一生。 2.头头是道 人生一世,要起好头:…

error LNK2019: 无法解析的外部符号 WinMain,该符号在函数 int __cdecl invoke_main(void)”中被引用

From:https://blog.csdn.net/u012570056/article/details/74639894 一,问题描述 MSVCRTD.lib(exe_winmain.obj) : error LNK2019: 无法解析的外部符号 WinMain,该符号在函数 "int __cdecl invoke_main(void)" (?invoke_mainYAHXZ…

德国人工智能研究中心波尔特:人工智能与工业4.0并驾齐驱

来源:科技日报摘要:2013年德国政府提出的“工业4.0”战略就涵盖了人工智能。“工业4.0”战略着重在制造业等领域相互利用。以深度学习、自我升级为主要特征的人工智能有望将人类各方面智能拓展到极限,从而在各领域做到极致。人工智能的研发在…

C++ 基本数据类型 的 字节数

From:https://www.cnblogs.com/qiumingcheng/p/7824919.html C语言入门经典——基础知识(数据类型):https://blog.csdn.net/weixin_42167759/article/details/80404815 闲聊c/c: 各平台下基本数据类型的字节长度:htt…