实现多线程爬取数据并保存到mongodb
多线程爬取二手房网页并将数据保存到mongodb的代码:
import pymongo
import threading
import time from lxml import etree
import requests
from queue import Queue index_url='https://m.lianjia.com/gz/ershoufang/pg{}/'
detail_url='https://m.lianjia.com{}' # 设置爬取主页的页数
INDEX_PAGE_NUM= # 定义一个类 # 0定义主页url队列、主页html队列、详情页url队列、html队列、内容队列
# 1获取首页url并解析详情页url
# 2获取详情页的内容
# 3保存内容
# 4设置多线程调用方法 # 设置mongodb
client = pymongo.MongoClient('localhost')
# 设置数据库名
db = client['ershoufang']
# 指定集合名
index = 'index_info'
detail = 'detail_info' class lianJia():
def __init__(self):
self.index_url_queue=Queue() self.html_index_queue=Queue() self.index_content_queue=Queue()
self.detail_content_queue = Queue() # 获取主页的url和html内容并解析出index页内容和详情页url
def get_index(self):
for i in range(INDEX_PAGE_NUM):
# print(index_url.format(i+))
url=index_url.format(i+)
self.index_url_queue.put(url)
# index=requests.get(index_url.format(i+)).content.decode()
# self.html_index_queue.put(index)
# 获取主页html
def get_index_html(self):
while True:
url=self.index_url_queue.get()
index = requests.get(url).content.decode()
self.html_index_queue.put(index)
self.index_url_queue.task_done()
def parse_index(self):
while True:
# 获取队列里得内容
html1=self.html_index_queue.get()
xml=etree.HTML(html1)
pingjie_list=xml.xpath('''//ul[@class='lists']/li[position()>1]''')
# 将 pingjie_list拼接在xpath前,少写xpath语句
index_content_list=[]
for pj in pingjie_list:
index_infor={}
# #判空炒作,如果为空则显示none if len(index_infor['title']) > else None
index_infor['title']=pj.xpath('''./div/div[@class='item_list']/div[1]/text()''') index_infor['title']=index_infor['title'][] if len(index_infor['title']) > else None
index_infor['detail_url'] = pj.xpath('''./a/@href''')[]
index_infor['index_detail']=pj.xpath('''./div/div[2]/div[2]/text()''')
index_infor['index_detail']=index_infor['index_detail'][] if len(index_infor['index_detail'])> else None
index_infor['total_price']=pj.xpath('''./div/div[2]/div[position()>2]/span[1]/em/text()''')
index_infor['total_price']= index_infor['total_price'][] if len( index_infor['total_price'])> else None
index_infor['average_price']=pj.xpath('''./div/div[@class='item_list']/div[3]/span[2]/text()''')
index_infor['average_price']=index_infor['average_price'][]if len(index_infor['average_price'])> else None
index_content_list.append(index_infor)
# 队列保存时不能在循环里 否之回保存很多个队列
# self.index_content_queue.put(index_content_list)
# 把content_list放进content_queue里面 self.index_content_queue.put(index_content_list)
# print(index_content_list) # 每从队列中获取一个数,队列则减少一个数,所以此代码必须写
self.html_index_queue.task_done() # 获取详情页内容
def get_detail(self):
pass # 保存内容
def save_content(self):
while True:
index_conten_list=self.index_content_queue.get() for i in index_conten_list:
# print(i['title'])
if i['title']==None or i['total_price']==None or i['average_price']==None:
print('该数据为空,不进行保存') else:
db['index_info'].insert(i)
# db['detailDta'].insert(detail_datas)
print('保存数据成功')
self.index_content_queue.task_done() # 主线程:分配各种子线程去执行class里得每一个函数
# 使用队列的方式得设置多线程进行调用函数,才能让程序执行速度更快
def run(self):
# 设置线程列表
thread_list=[]
# start_time=time.time()
# .url_list
# threading.Thread不需要传参数,参数都是从队列里面取得
# for i in range():
t_index_u=threading.Thread(target=self.get_index)
thread_list.append(t_index_u) # .遍历,发送请求,获取响应
for i in range():
t_index_html=threading.Thread(target=self.get_index_html)
thread_list.append(t_index_html) # .提取数据
for i in range():
t_parse_index=threading.Thread(target=self.parse_index)
thread_list.append(t_parse_index) # .保存数据
t_save=threading.Thread(target=self.save_content)
thread_list.append(t_save)
# 循环开启各子线程
for t in thread_list:
# 表示主线程结束,子线程(设置为true无限循环)也跟着结束(用主线程控制子线程)
t.setDaemon(True)
# 启动线程
t.start()
for q in [self.index_url_queue,self.html_index_queue,self.index_content_queue]:
# 让主线程等待阻塞,等待队列的任务完成(即队列为空时 )之后再进行主线程
q.join()
# end_time=time.time()
# print('总耗时%.2f秒'%(end_time-start_time)) if __name__=='__main__':
sk = time.clock()
func=lianJia()
func.run()
ek = time.clock()
print('程序总耗时:',ek-sk)
多线程爬取糗事百科:
# coding=utf-
import requests
from lxml import etree
import threading
from queue import Queue # https://docs.python.org/3/library/queue.html#module-queue
# 队列使用方法简介
# q.qsize() 返回队列的大小
# q.empty() 如果队列为空,返回True,反之False
# q.full() 如果队列满了,返回True,反之False
# q.full 与 maxsize 大小对应
# q.get([block[, timeout]]) 获取队列,timeout等待时间
# q.get_nowait() 相当q.get(False)
# q.put(item) 写入队列,timeout等待时间
# q.put_nowait(item) 相当q.put(item, False)
# q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
# q.join() 实际上意味着等到队列为空,再执行别的操作 class QiubaiSpdier:
def __init__(self):
self.url_temp = "https://www.qiushibaike.com/8hr/page/{}/"
self.headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"}
self.url_queue = Queue()
self.html_queue = Queue()
self.content_queue = Queue()
def get_url_list(self):
# return [self.url_temp.format(i) for i in range(,)]
for i in range(,):
# 把13个索引页面的Url放进url_queue队列里
self.url_queue.put(self.url_temp.format(i)) def parse_url(self):
while True:
# get方法和task_done搭配使用
# 在put是队列+,get和task_done一起使用时队列才会-
url = self.url_queue.get()
print(url)
response = requests.get(url,headers=self.headers)
# 然后把索引页的响应页面放进html_queue队列里
self.html_queue.put(response.content.decode())
self.url_queue.task_done() def get_content_list(self): #提取数据
while True:
# 先从索引页响应页面html_queue队列里面取出索引页面
html_str = self.html_queue.get() html = etree.HTML(html_str)
div_list = html.xpath("//div[@id='content-left']/div") #分组
content_list = []
for div in div_list:
item= {}
item["content"] = div.xpath(".//div[@class='content']/span/text()")
item["content"] = [i.replace("\n","") for i in item["content"]]
item["author_gender"] = div.xpath(".//div[contains(@class,'articleGender')]/@class")
item["author_gender"] = item["author_gender"][].split(" ")[-].replace("Icon","") if len(item["author_gender"])> else None
item["auhtor_age"] = div.xpath(".//div[contains(@class,'articleGender')]/text()")
item["auhtor_age"] = item["auhtor_age"][] if len(item["auhtor_age"])> else None
item["content_img"] = div.xpath(".//div[@class='thumb']/a/img/@src")
item["content_img"] = "https:"+item["content_img"][] if len(item["content_img"])> else None
item["author_img"] = div.xpath(".//div[@class='author clearfix']//img/@src")
item["author_img"] = "https:"+item["author_img"][] if len(item["author_img"])> else None
item["stats_vote"] = div.xpath(".//span[@class='stats-vote']/i/text()")
item["stats_vote"] = item["stats_vote"][] if len(item["stats_vote"])> else None
content_list.append(item)
# 把content_list放进content_queue里面
self.content_queue.put(content_list)
self.html_queue.task_done() def save_content_list(self): #保存
while True:
content_list = self.content_queue.get()
for i in content_list:
print(i)
pass
self.content_queue.task_done() def run(self): #实现主要逻辑
thread_list = []
#.url_list
# threading.Thread不需要传参数,参数都是从队列里面取得
t_url = threading.Thread(target=self.get_url_list)
thread_list.append(t_url)
#.遍历,发送请求,获取响应
for i in range(): # 添加20个线程
t_parse = threading.Thread(target=self.parse_url)
thread_list.append(t_parse)
#.提取数据
for i in range(): # 添加2个线程
t_html = threading.Thread(target=self.get_content_list)
thread_list.append(t_html)
#.保存
t_save = threading.Thread(target=self.save_content_list)
thread_list.append(t_save)
for t in thread_list:
t.setDaemon(True) #把子线程设置为守护线程,该线程不重要,主线程结束,子线程结束(子线程是while true不会自己结束)
t.start() for q in [self.url_queue,self.html_queue,self.content_queue]:
q.join() #让主线程等待阻塞,等待队列的任务完成(即队列为空时 )之后再进行主线程 print("主线程结束") if __name__ == '__main__':
qiubai = QiubaiSpdier()
qiubai.run() # 所没有tast_done方法,程序最终会卡着不动,无法终止 # 线程的设计注意:耗时的操作要分配一些线程
实现多线程爬取数据并保存到mongodb的更多相关文章
- scrapy爬取海量数据并保存在MongoDB和MySQL数据库中
前言 一般我们都会将数据爬取下来保存在临时文件或者控制台直接输出,但对于超大规模数据的快速读写,高并发场景的访问,用数据库管理无疑是不二之选.首先简单描述一下MySQL和MongoDB的区别:MySQ ...
- sumafan:python爬虫多线程爬取数据小练习(附答案)
抓取 https://www.cnbeta.com/ 首页中新闻内容页网址, 抓取内容例子: https://hot.cnbeta.com/articles/game/825125 将抓取下来的内容页 ...
- 吴裕雄--天生自然python数据清洗与数据可视化:MYSQL、MongoDB数据库连接与查询、爬取天猫连衣裙数据保存到MongoDB
本博文使用的数据库是MySQL和MongoDB数据库.安装MySQL可以参照我的这篇博文:https://www.cnblogs.com/tszr/p/12112777.html 其中操作Mysql使 ...
- 吴裕雄--天生自然PYTHON爬虫:安装配置MongoDBy和爬取天气数据并清洗保存到MongoDB中
1.下载MongoDB 官网下载:https://www.mongodb.com/download-center#community 上面这张图选择第二个按钮 上面这张图直接Next 把bin路径添加 ...
- python多线程爬取斗图啦数据
python多线程爬取斗图啦网的表情数据 使用到的技术点 requests请求库 re 正则表达式 pyquery解析库,python实现的jquery threading 线程 queue 队列 ' ...
- Python爬虫入门教程 11-100 行行网电子书多线程爬取
行行网电子书多线程爬取-写在前面 最近想找几本电子书看看,就翻啊翻,然后呢,找到了一个 叫做 周读的网站 ,网站特别好,简单清爽,书籍很多,而且打开都是百度网盘可以直接下载,更新速度也还可以,于是乎, ...
- 借助Chrome和插件爬取数据
工具 Chrome浏览器 TamperMonkey ReRes Chrome浏览器 chrome浏览器是目前最受欢迎的浏览器,没有之一,它兼容大部分的w3c标准和ecma标准,对于前端工程师在开发过程 ...
- 使用selenium 多线程爬取爱奇艺电影信息
使用selenium 多线程爬取爱奇艺电影信息 转载请注明出处. 爬取目标:每个电影的评分.名称.时长.主演.和类型 爬取思路: 源文件:(有注释) from selenium import webd ...
- Python爬虫入门教程 14-100 All IT eBooks多线程爬取
All IT eBooks多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...
随机推荐
- CF1107
我哭了......什么鬼题我怎么都不会...果然教育场是教我做人的... 打的虚拟赛,286名...太菜了.EF都是可做题我都没写出来...G题大水题我居然没看... B:设g(i) = i的各位数字 ...
- Java 多个文件压缩下载
有时候会有多个附件一起下载的需求,这个时候最好就是打包下载了 首先下面这段代码是正常的单个下载 public void Download(@RequestParam("file_path&q ...
- luogu2643 聪聪可可
题目链接 题意 其实转化之后的题意就是求出树上有多少条路径长度是3的倍数.求答案的时候只要将这个数字除以总路径数量就行了. 思路 考虑点分治.对于当前子树,分别求出出树中每个点到根的路径长度对\(3\ ...
- gei 操作
git --version 查看版本号 进入项目文件 上传账号的用户名git config --global user.name "牛星宇" 上传账号的邮箱git config - ...
- 【洛谷P1226 【模板】快速幂||取余运算】
题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整数b,p,k. 输出格式: 输出“b^p mod k=s” s为运算结果 作为初 ...
- Filter(过滤器)
一.Filter过滤器(重要) Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作. 1.Filter快速入门 1.1.步骤: 1. 创建一个类实现Filter接口 2. 重写接口中方 ...
- template specifiers not specified in declaration of ‘template<class Key> class hash’
尝试写显示特化样例的时候,写了如下代码 #include <iostream> #include <cstddef> using namespace std; #define ...
- ElasticSearch6.5.0 【字段类型】
字符串类型 text 适合全文索引,有分析的过程 keyword 适合结构化的数据,比如地址.电话号码... 数字 long [带符号64位整数]范围:-263 ~ 263-1 integer ...
- Luogu P3346 [ZJOI2015]诸神眷顾的幻想乡 广义SAM 后缀自动机
题目链接 \(Click\) \(Here\) 真的是好题啊-不过在说做法之前先强调几个自己总是掉的坑点. 更新节点永远记不住往上跳\(p = fa[p]\) 新建节点永远记不住\(len[y] = ...
- (选择不相交区间)今年暑假不AC hdu2037
今年暑假不AC Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...