加盟型网站建设,网站建设高端品牌,注册网站需要房产证,宣传软文怎么写From#xff1a;https://www.imooc.com/article/21839
scrapy提升篇之配置#xff1a;https://segmentfault.com/a/1190000009321902 前面我写了一篇《scrapy快速入门》#xff0c;简单介绍了一点scrapy的知识。这次就来介绍一些scrapy的进阶知识#xff0c;做一些真正有用…
Fromhttps://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(serializerstr)
这些项目类一般都定义在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.comstart_urls [http://www.example.com/users/login.php]def parse(self, response):return scrapy.FormRequest.from_response(response,formdata{username: john, password: secret},callbackself.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_itemsdef __init__(self, mongo_uri, mongo_db):self.mongo_uri mongo_uriself.mongo_db mongo_dbclassmethoddef from_crawler(cls, crawler):return cls(mongo_uricrawler.settings.get(MONGO_URI),mongo_dbcrawler.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生成图片缩略图只下载大于某长宽的图片
使用文件管道的过程如下
首先需要Item类中有file_urls和files两个属性然后在爬虫中将想爬取的文件地址放到file_urls属性中然后返回在Item传递到文件管道的时候调度程序会用下载器将地址对应的文件下载下来将文件属性包括保存路径等放到files属性中file_urls和files中是一一对应的
使用图片管道的过程是相似的不过要操作的属性是image_urls和images。
如果你不想使用这几个属性其实属性名也是可以修改的需要修改下面四个属性。
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/xhtmlxml,application/xml;q0.9,*/*;q0.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 myspiderstart_urls [https://scrapinghub.com]def parse(self, response):self.logger.info(Parse function called on %s, response.url)
日志相关的配置点击可以跳转到官方文档查看详细信息。
LOG_FILELOG_ENABLEDLOG_ENCODINGLOG_LEVELLOG_FORMATLOG_DATEFORMATLOG_STDOUTLOG_SHORT_NAMES
发送电子邮件
有时候我们可能希望爬到一定数量的数据就发送电子邮件进行提醒。scrapy也内置了这个功能。我们可以通过构造函数参数来创建邮件发送器。
from scrapy.mail import MailSender
mailer MailSender(这里是构造函数参数)
也可以从配置文件实例化。
mailer MailSender.from_settings(settings)
然后调用send方法就可以发送邮件了。
mailer.send(to[someoneexample.com], subjectSome subject, bodySome body, cc[anotherexample.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_ENABLEDAUTOTHROTTLE_START_DELAYAUTOTHROTTLE_MAX_DELAYAUTOTHROTTLE_TARGET_CONCURRENCYAUTOTHROTTLE_DEBUGCONCURRENT_REQUESTS_PER_DOMAINCONCURRENT_REQUESTS_PER_IPDOWNLOAD_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 projectquotesbot -d spidertoscrape-css
或者使用Jetbrains 系列IDE 2017.3的基于编辑器的HTTP客户端。
然后点击Jobs就可以看到爬虫已经开始运行了。如果要查看状态点击右边的log即可。
以上就是scrapy的进阶介绍了利用这些功能我们可以编写更加实用的爬虫并将它们部署到服务器上。