爬虫连接mongodb、多线程多进程的使用
一、连接mongodb
1、 设置数据库 client=pymongo.MongoClient(‘localhost’)
2、 db=client[‘lagou’]设置连接的数据库名称
POSITION_NAME=’’ 、PAGE_SUM 、PAGE_SIZE 等为你设置的变量名称。
3、DATA_NAME=’dataposition’ # # 指定数据库的名字
4、设置保存在mongo数据库中的数据:
def save_to_mongo(data):
if db[DATA_NAME].update({'positionId': data['positionId']}, {'$set': data}, True):
print('Saved to Mongo', data['positionId'])
else:
print('Saved to Mongo Failed', data['positionId'])
这是以positionId为唯一标识,如果数据库里面已经存在有positionId,说明数据已经爬过了,不再更新。
二、多进程设置和使用:
1、导入多进程:from multiprocessing import Pool
导入时间 import time
2、start_time = time.time()
pool = Pool() # pool()参数:进程个数:默认的是电脑cpu的核的个数,如果要指定进程个数,这个进程个数要小于等于cpu的核数
# 第一个参数是一个函数体,不需要加括号,也不需指定参数。。
# 第二个参数是一个列表,列表中的每个参数都会传给那个函数体
pool.map(to_mongo_pool,[i for i in range(PAGE_SUM)])
# close它只是把进程池关闭
pool.close()
# join起到一个阻塞的作用,主进程要等待子进程运行完,才能接着往下运行
pool.join()
end_time = time.time()
print("总耗费时间%.2f秒" % (end_time - start_time))
to_mongo_pool:这个函数要设计好,就一个参数就够了,然后把它的参数放在列表里面,通过map高阶函数一次传给to_mongo_pool
多线程的使用:
多线程要配合队列使用:
# coding=utf-8
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 Lianjia:
def __init__(self):
self.url_temp = url = "https://gz.lianjia.com/ershoufang/pg{}/"
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(1,14)]
for i in range(1, 14):
# 把13个索引页面的Url放进url_queue队列里
self.url_queue.put(self.url_temp.format(i))
定义运行函数
def run(self): # 实现主要逻辑
thread_list = []
# 1.url_list
# threading.Thread不需要传参数,参数都是从队列里面取得
t_url = threading.Thread(target=self.get_url_list)
thread_list.append(t_url)
# 2.遍历,发送请求,获取响应
for i in range(20): # 添加20个线程
t_parse = threading.Thread(target=self.parse_url)
thread_list.append(t_parse)
# 3.提取数据
for i in range(2): # 添加2个线程
t_html = threading.Thread(target=self.get_content_list)
thread_list.append(t_html)
# 4.保存
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("主线程结束")
代码如下:
# 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 Lianjia:
def __init__(self):
self.url_temp = url = "https://gz.lianjia.com/ershoufang/pg{}/"
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('//li[@class="clear LOGCLICKDATA"]') # 分组
content_list = []
for div in div_list:
item = {}
item['title'] = div.xpath('.//div[@class="title"]/a/text()')
item['href'] = div.xpath('.//div[@class="title"]/a/@href')
item['totalPrice'] = div.xpath('.//div[@class="totalPrice"]/span/text()')
item['houseInfo'] = div.xpath('.//div[@class="houseInfo"]/text()')
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 =Lianjia()
qiubai.run() # 所没有tast_done方法,程序最终会卡着不动,无法终止
爬虫连接mongodb、多线程多进程的使用的更多相关文章
- 爬虫链接mongodb 以及多线程多进程的操作
一.连接mongodb 1. 设置数据库 client=pymongo.MongoClient(‘localhost’) 2. db=client[‘lag ...
- 爬虫入门【8】Python连接MongoDB的用法简介
MongoDB的连接和数据存取 MongoDB是一种跨平台,面向文档的NoSQL数据库,提供高性能,高可用性并且易于扩展. 包含数据库,集合,文档等几个重要概念. 我们在这里不介绍MongoDB的特点 ...
- python爬虫入门八:多进程/多线程
什么是多线程/多进程 引用虫师的解释: 计算机程序只不过是磁盘中可执行的,二进制(或其它类型)的数据.它们只有在被读取到内存中,被操作系统调用的时候才开始它们的生命期. 进程(有时被称为重量级进程)是 ...
- Python有了asyncio和aiohttp在爬虫这类型IO任务中多线程/多进程还有存在的必要吗?
最近正在学习Python中的异步编程,看了一些博客后做了一些小测验:对比asyncio+aiohttp的爬虫和asyncio+aiohttp+concurrent.futures(线程池/进程池)在效 ...
- python爬虫之MongoDB测试环境安装
一. 下载 从http://www.mongodb.org/downloads地址中下载:mongodb-linux-x86_64-2.4.11.tar 二. 安装 1>设置mongoDB ...
- C++程序员面试题目总结(涉及C++基础、多线程多进程、网络编程、数据结构与算法)
说明:C++程序员面试题目总结(涉及C++基础知识.多线程多进程.TCP/IP网络编程.Linux操作.数据结构与算法) 内容来自作者看过的帖子或者看过的文章,个人整理自互联网,如有侵权,请联系作者 ...
- 使用mongo-java-driver-3.0.2连接MongoDB数据库
这里使用的mongodb的java驱动版本是:3.0.2,文件名mongo-java-driver-3.0.2.jar 博客本地下载下载网址(也可以下载其它版本):http://central.ma ...
- WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)
原文 WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口) WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验.如果希望做不同线程 ...
- Python多线程多进程那些事儿看这篇就够了~~
自己以前也写过多线程,发现都是零零碎碎,这篇写写详细点,填一下GIL和Python多线程多进程的坑~ 总结下GIL的坑和python多线程多进程分别应用场景(IO密集.计算密集)以及具体实现的代码模块 ...
随机推荐
- 通过python代码对域名ssl证书进行监控
根据公司要求,要求用zabbix对域名的ssl证书进行到期监控 直接上代码 #!/usr/bin/env python3 from urllib3.contrib import pyopenssl f ...
- SpringBootSecurity学习(06)网页版登录方法级别的权限
用户授权 前面讨论过,Web应用的安全管理,主要包括两个方面的内容,一个是用户身份的认证,即用户登录的设计,二是用户授权,即一个用户在一个应用系统中能够执行哪些操作的权限管理.前面介绍了登录,下面简单 ...
- Weblogic任意文件上传漏洞(CVE-2018-2894)复现
使用docker搭建漏洞测试环境 micr067@test:~/vulhub/weblogic/CVE-2018-2894$ sudo docker-compose build weblogic us ...
- SUSE Ceph 增加节点、减少节点、 删除OSD磁盘等操作 - Storage6
一.测试环境描述 之前我们已快速部署好一套Ceph集群(3节点),现要测试在现有集群中在线方式增加节点 如下表中可以看到增加节点node004具体配置 主机名 Public网络 管理网络 集群网络 说 ...
- 关于.NET HttpClient方式获取微信小程序码(二维码)
随着微信小程序的火热应用,市面上有关小程序开发的需求也多了起来.近来分析了一项生成有关生成微信小程序码的需求——要求扫码跳转到小程序指定页面(带参数):看了下小程序官方文档文档,结合网上的例子,未看到 ...
- JVM(三)初始化
字节码指令和符号引用.直接引用 1.主动引用和被动引用 主动引用:虚拟机规定只有满足四个情况的的情况下,才会进行主动引用. 被动引用:除过四种情况的引用是被动引用. 只有主动引用才会初始 ...
- 【solved】must have one register DataBase alias named `default`
beego在初始化MySQL数据库时报错处理 1.报错提示: ... [ORM]2019/10/11 08:42:52 register db Ping `default`, dial tcp 192 ...
- pycharm 2019/10 激活码 最新福利 (1)
MTW881U3Z5-eyJsaWNlbnNlSWQiOiJNVFc4ODFVM1o1IiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1lIjoiI ...
- Tomcat7.0.40注册到服务启动报错error Code 1 +connector attribute sslcertificateFile must be defined when using ssl with apr
Tomcat7.0.40 注册到服务启动遇到以下几个问题: 1.启动报错errorCode1 查看日志如下图: 解决办法: 这个是因为我的jdk版本问题,因为电脑是64位,安装的jdk是32位的所以会 ...
- RE-1 逆向分析基础
逆向分析基础 0x01-0x0C 本笔记使用汇编指令为x86架构下汇编指令,ARM架构汇编指令不做介绍 0x01. 关于RE 逆向工程(Reverse Engineering RE) 逆向分析方法: ...