实现多线程爬取数据并保存到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多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...
随机推荐
- 【CH6801】棋盘覆盖
题目大意:给定一个 N*N 的棋盘,棋盘上有些位置不能防止任何东西,现用 1*2 的骨牌填充棋盘,问最多能铺多少块骨牌. 题解:由于骨牌只能覆盖相邻的两个格子,那么按照对角线进行划分的格子可以保证一定 ...
- (转)visual stdio 书签功能介绍
http://www.mycode.net.cn/tools/1615.html 使用 Visual Studio 开发过程中,你很容易遇到一种情况就是多个文件来回的切换,在每一块实现不同的业务,打开 ...
- 判断JDK安装成功的方法
JDK安装成功之后,主要是要写入环境变量
- Nginx概述及安装配置
1.概述 Nginx是一款开源的,高性能的Http和反向代理服务器,同时也是一个IMAP.POP3.SMTP代理服务器:Nginx可以作为一个HTTP服务器进行网站的发布处理,也可以作为反向代理进行负 ...
- python实现发送邮件
一 使用SMTP模块发送邮件 import smtplib from email.mime.text import MIMEText from email.header import Header m ...
- Ubuntu下添加Samba用户名与密码
参考: ubuntu下的Samba配置:使每个用户可以用自己的用户名和密码登录自己的home目录 增加samba用户提示Failed to add entry for user Ubuntu可以直接在 ...
- HDU - 5952 Counting Cliques(DFS)
A clique is a complete graph, in which there is an edge between every pair of the vertices. Given a ...
- mysql 5.7安装准备
在5.5之后的mysql安装中,需要使用cmake来指定安装参数,下面列出关于cmake的几个常用参数: CMAKE_INSTALL_PREFIX:指定MySQL程序的安装目录,默认/usr/loca ...
- Zabbix Web API Get方法整合
#!/usr/bin/python3 import requests,json,re,time,datetime url = 'http://xxx.com/api_jsonrpc.php' ...
- java io系列19之 CharArrayWriter(字符数组输出流)
本章,我们学习CharArrayWriter.学习时,我们先对CharArrayWriter有个大致了解,然后深入了解一下它的源码,最后通过示例来掌握它的用法. 转载请注明出处:http://www. ...