用redis做简单的任务队列(二)

news/2024/7/19 12:25:22 标签: 数据库, python, 爬虫

是用redis做任务队列时,要思考:

  • 用什么数据类型来做任务队列
  • 怎样才能防止重复爬取

上一篇文章已经决定使用list来做任务队列,但是去重问题没有得到解决。这里可以用set来解决思考二的问题,就是防止重复爬取的问题。

 

使用list当作未完成任务队列,存储还没有爬的url(或者是用户id,文章id等唯一标识)
使用set当作已完成任务队列,存储已经爬取的url
每次爬虫程序从list未完成任务队列获取任务的时候,都去set已完成任务队列里面验证一下,如果已完成队列里已经有了,就舍弃掉,如果没有,就开始爬取,并将这个url加入到已爬取的任务队列
这样做的方便之处在于:每当我往list未完成任务队列里加任务的时候,我不用考虑这个任务有没有爬过,这个任务是不是已经在未爬取任务队列了,我只需要往里加就行了,当爬虫去取的时候,让爬虫程序去做这个操作。

以下是具体代码 
算是一个生产消费把,master往队列里塞任务,parser使用get_html的返回值进行解析,然后入库。

协程爬取贴吧里发帖内容(redis做任务队列,mongo存储)

 1 import requests
 2 from lxml import etree
 3 import redis
 4 import asyncio,aiohttp
 5 
 6 import pymongo
 7 conn = pymongo.MongoClient('localhost',27017)
 8 
 9 db = conn.nicedb # 指定数据库名称,连接nicedb数据库,没有则自动创建
10 my_set = db.test_set # 使用test_set集合,没有则自动创建
11 # 以上两步都是延时操作,当往数据库插入第一条数据的时候,才会真正的创建数据库和集合
12 
13 # decode_responses=True,记得加这个参数,不加的话取出来的数据都是bytes类型的
14 r = redis.StrictRedis(host = '127.0.0.1', port = 6379, db = 2,decode_responses=True)
15 # pool = redis.ConnectionPool(host = '127.0.0.1', port = 6379, db = 2)
16 # r = redis.StrictRedis(connection_pool=pool,decode_responses=True)
17 
18 def master(page):
19     url = 'https://tieba.baidu.com/f?kw=美女&ie=utf-8&pn={}'.format(page*50)
20     base = 'https://tieba.baidu.com'
21     res = requests.get(url).text
22     html = etree.HTML(res)
23     half_urls = html.xpath("//div[@class='threadlist_title pull_left j_th_tit ']/a/@href")
24     full_urls = [base + i for i in half_urls]
25     for url in full_urls:
26         # 从url_list列表头部塞任务,也就是url
27         r.lpush('url_list',url)
28     #print(r.llen('url_list'))
29 
30 async def get_html(url):
31     async with asyncio.Semaphore(5):  # 限制并发数为5个
32         async with aiohttp.ClientSession() as session:
33             async with session.get(url) as html:
34                 # errors='ignore',不加这个参数的话,会报错,具体错误内容见下面图片
35                 response = await html.text(encoding='utf-8',errors='ignore')
36                 return response
37 async def parse():
38     while True:
39         # 从redis的url_list列表取任务,从右边开始取
40         url = r.rpop('url_list')
41         if url == None:
42             break
43         # 判断这个任务是否已经做过了,也就是判断这个url在没在redis的history集合里
44         if r.sismember('history',url) == 1:
45             continue
46         response = await get_html(url)
47         html = etree.HTML(response)
48         content = html.xpath("//div[@class='left_section']/div[2]/div[1]//cc/div[1]/text()")[0].strip()
49         if content != '':
50             # 当内容不为空时,将内容存到mongo里
51             my_set.save({'content':content})
52             #print(content)
53         # 将爬取过的任务放到redis的history集合里,也就是已完成任务队列
54         r.sadd('history', url)
55 t1 = time.time()
56 # 爬取前10页
57 for i in range(10):
58     master()
59 
60 # async的一些步骤
61 loop = asyncio.get_event_loop()
62 tasks = [parse() for _ in range(15)]
63 loop.run_until_complete(asyncio.wait(tasks))
64 loop.close()
65 
66 t2 = time.time()
67 print(t2-t1)
68 # 最后用时:32.930299043655396
69 # 把mongo数据库换成mysql后,用时:43.06192493438721
70 
71 原文:https://blog.csdn.net/fiery_heart/article/details/82121237 

 

转载于:https://www.cnblogs.com/tianyiliang/p/10330470.html


http://www.niftyadmin.cn/n/911023.html

相关文章

反省:低调做人,高调做事!

此段摘录: 高调做事。低调做人,并不是什么事情都退在后面,自己的利益被别人剥夺强占也不发任何声音,自己的人格被别人侮辱也不反抗,这不是低调,这是懦弱。低调做人,是不要太招摇&#xf…

深度学习分类类别不平衡_Jason Brownlee专栏| 分类不平衡的随机过采样和欠采样-不平衡分类系列教程(12)...

作者:Jason Brownlee编译:Florence Wong – AICUG本文系AICUG翻译原创,如需转载请联系(微信号:834436689)以获得授权不平衡的数据集是在类别分布中存在严重偏差的数据集,例如少数类比多数类是1:100或1&…

HTTP协议概述

HTTP简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。 HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文…

归并排序(C#实现)

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。归并排序是建立在归并操作上的一种有效的排序算法。该算法…

多线程跑调度_轻松实现Python中的多进程与多线程

还没关注?快动动手指!今天我们来聊聊Python里面的多进程与多线程编程模式。01 多线程工作在开始讲今天的正文之前,先给大家介绍一个概念「多线程工作」,这个概念可能有的人听过,也可能有的人平常工作中就是这么做的。我…

Ubuntu学习

Ubuntu学习——第一篇 一、 Ubuntu简介 Ubuntu(乌班图)是一个基于Debian的以桌面应用为主的Linux操作系统,据说其名称来自非洲南部祖鲁语或科萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非…

linux内核学习之四:进程切换简述

linux内核学习之四:进程切换简述 在讲述专业知识前,先讲讲我学习linux内核使用的入门书籍:《深入理解linux内核》第三版(英文原版叫《Understanding the Linux Kernel》),不过这本书不一定对每个人都适合&a…

hivesql修改字段类型_sqlserver修改表结构

增加字段: alter table 表名 add 新增字段名 字段类型 默认值...alter table [stu] add [jj] int default 0删除字段: ALTER TABLE 表名 DROP COLUMN 字段名;alter table [stu] drop column [jj]如果字段设置了默认值,会报错“由于一个或多个对象访问此列&#xff0…