Python爬虫练习(多线程,进程,协程抓取网页)
详情点我跳转
关注公众号“轻松学编程”了解更多。
一、多线程抓取网页
流程:a.设置种子url b.获取区域列表 c.循环区域列表 d.创建线程获取页面数据
e、启动线程
import csv
import threading
import time
import requests
import lxml
from lxml import etree
import json
# 递归锁
rlock = threading.RLock()
# 设置请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
def getAreaList(url):
'''
获取区域列表
:param url:
:return: dict {"cityName":"cityUrl"}
'''
# 获取响应
response = requests.get(url,headers=headers).text
# 创建xml树形结构对象
mytree = lxml.etree.HTML(response)
# 分区
areaList = mytree.xpath('//div[@data-role="ershoufang"]/div/a')
#分区字典
areaDict = {}
for area in areaList:
#区域名
areaName = area.xpath('./text()')[0]
areaUrl = "https://gz.lianjia.com"+area.xpath('./@href')[0]
areaDict[areaName] = areaUrl
# print(areaName,areaUrl)
return areaDict
def getPageTotal(url):
'''
获取分区页数
:param url: utl
:return: int 总页数
'''
response = requests.get(url,headers=headers).text
mytree = lxml.etree.HTML(response)
# 获取总页数
pageTotal = mytree.xpath('//div[@class="page-box house-lst-page-box"]/@page-data')[0]
pageTotal = int(json.loads(pageTotal)["totalPage"])
# print(pageTotal)
return pageTotal
def getHouseInfo(area,url):
'''
获取房子信息
:param area:区域
:param url: url
:return:
'''
pageTotal = getPageTotal(url)
for page in range(1,pageTotal+1):
newurl = url+"pg%d/"%page
# print(newurl)
response = requests.get(newurl,headers=headers).text
mytree = lxml.etree.HTML(response)
houseList = mytree.xpath('//li[@class="clear"]')
print(houseList)
for house in houseList:
# 房子标题
houseTitle = house.xpath('.//div[@class="title"]/a/text()')[0]
# 房子url
houseUrl = house.xpath('.//div[@class="title"]/a/@href')[0]
# 房子地址
houseAddr = house.xpath('.//div[@class="houseInfo"]//text()')
houseAddr = ''.join(houseAddr)
# 位置信息
positionInfo = house.xpath('.//div[@class="positionInfo"]//text()')
positionInfo = ''.join(positionInfo)
# 总价
priceInfo = house.xpath('.//div[@class="totalPrice"]/span/text()')[0] + '万'
# 平方价
unitPrice = house.xpath('.//div[@class="unitPrice"]/span/text()')[0]
print(houseTitle,houseUrl,houseAddr,positionInfo,priceInfo,unitPrice)
# 保存成csv文件
with rlock:
with open('./data/'+area+'.csv','a+',encoding='utf-8',errors='ignore') as f:
writer = csv.writer(f)
writer.writerow([houseTitle,houseUrl,houseAddr,positionInfo,priceInfo,unitPrice])
if __name__ == '__main__':
#设置种子url
cityUrl = "https://gz.lianjia.com/ershoufang/"
# 获取区域列表
areaDict = getAreaList(cityUrl)
threadList = []
time.clock()
for areaName,areaUrl in areaDict.items():
# 创建线程
t = threading.Thread(target=getHouseInfo,args=(areaName,areaUrl))
t.start()
threadList.append(t)
# 保证线程正常结束
for t in threadList:
t.join()
print(time.clock())
二、协程抓取网页
import csv
import threading
import time
import requests
import lxml
from lxml import etree
import json
import gevent
from gevent import monkey
# 非阻塞型
gevent.monkey.patch_all()
# 递归锁
rlock = threading.RLock()
# 设置请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
def getAreaList(url):
'''
获取区域列表
:param url:
:return: dict {"cityName":"cityUrl"}
'''
# 获取响应
response = requests.get(url,headers=headers).text
# 创建xml树形结构对象
mytree = lxml.etree.HTML(response)
# 分区
areaList = mytree.xpath('//div[@data-role="ershoufang"]/div/a')
#分区字典
areaDict = {}
for area in areaList:
#区域名
areaName = area.xpath('./text()')[0]
areaUrl = "https://gz.lianjia.com"+area.xpath('./@href')[0]
areaDict[areaName] = areaUrl
# print(areaName,areaUrl)
return areaDict
def getPageTotal(url):
'''
获取分区页数
:param url: utl
:return: int 总页数
'''
response = requests.get(url,headers=headers).text
mytree = lxml.etree.HTML(response)
# 获取总页数
pageTotal = mytree.xpath('//div[@class="page-box house-lst-page-box"]/@page-data')[0]
pageTotal = int(json.loads(pageTotal)["totalPage"])
# print(pageTotal)
return pageTotal
def getHouseInfo(area,url):
'''
获取房子信息
:param area:区域
:param url: url
:return:
'''
pageTotal = getPageTotal(url)
for page in range(1,pageTotal+1):
newurl = url+"pg%d/"%page
# print(newurl)
response = requests.get(newurl,headers=headers).text
mytree = lxml.etree.HTML(response)
houseList = mytree.xpath('//li[@class="clear"]')
print(houseList)
for house in houseList:
# 房子标题
houseTitle = house.xpath('.//div[@class="title"]/a/text()')[0]
# 房子url
houseUrl = house.xpath('.//div[@class="title"]/a/@href')[0]
# 房子地址
houseAddr = house.xpath('.//div[@class="houseInfo"]//text()')
houseAddr = ''.join(houseAddr)
# 位置信息
positionInfo = house.xpath('.//div[@class="positionInfo"]//text()')
positionInfo = ''.join(positionInfo)
# 总价
priceInfo = house.xpath('.//div[@class="totalPrice"]/span/text()')[0] + '万'
# 平方价
unitPrice = house.xpath('.//div[@class="unitPrice"]/span/text()')[0]
print(houseTitle,houseUrl,houseAddr,positionInfo,priceInfo,unitPrice)
# 保存成csv文件
with rlock:
with open('./data/'+area+'.csv','a+',encoding='utf-8',errors='ignore') as f:
writer = csv.writer(f)
writer.writerow([houseTitle,houseUrl,houseAddr,positionInfo,priceInfo,unitPrice])
if __name__ == '__main__':
#设置种子url
cityUrl = "https://gz.lianjia.com/ershoufang/"
# 获取区域列表
areaDict = getAreaList(cityUrl)
geventList = []
time.clock()
for areaName,areaUrl in areaDict.items():
# 创建协程
g = gevent.spawn(getHouseInfo,areaName,areaUrl)
geventList.append(g)
# 保证协程正常结束
gevent.joinall(geventList)
print(time.clock())
三、协程与进程结合抓取网页
import csv
import threading
import time
import requests
import lxml
from lxml import etree
import json
import multiprocessing
import gevent
from gevent import monkey
# 非阻塞型
gevent.monkey.patch_all()
# 递归锁
rlock = threading.RLock()
# 设置请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
def getAreaList(url):
'''
获取区域列表
:param url:
:return: dict {"cityName":"cityUrl"}
'''
# 获取响应
response = requests.get(url,headers=headers).text
# 创建xml树形结构对象
mytree = lxml.etree.HTML(response)
# 分区
areaList = mytree.xpath('//div[@data-role="ershoufang"]/div/a')
#分区字典
areaDict = {}
for area in areaList:
#区域名
areaName = area.xpath('./text()')[0]
areaUrl = "https://gz.lianjia.com"+area.xpath('./@href')[0]
areaDict[areaName] = areaUrl
# print(areaName,areaUrl)
return areaDict
def getPageTotal(url):
'''
获取分区页数
:param url: utl
:return: int 总页数
'''
response = requests.get(url,headers=headers).text
mytree = lxml.etree.HTML(response)
# 获取总页数
pageTotal = mytree.xpath('//div[@class="page-box house-lst-page-box"]/@page-data')[0]
pageTotal = int(json.loads(pageTotal)["totalPage"])
# print(pageTotal)
return pageTotal
def getHouseInfo(area,url):
'''
获取房子信息
:param area:区域
:param url: url
:return:
'''
def houesInfo(area,url,pageTotal):
for page in range(1,pageTotal+1):
newurl = url+"pg%d/"%page
# print(newurl)
response = requests.get(newurl,headers=headers).text
mytree = lxml.etree.HTML(response)
houseList = mytree.xpath('//li[@class="clear"]')
print(houseList)
for house in houseList:
# 房子标题
houseTitle = house.xpath('.//div[@class="title"]/a/text()')[0]
# 房子url
houseUrl = house.xpath('.//div[@class="title"]/a/@href')[0]
# 房子地址
houseAddr = house.xpath('.//div[@class="houseInfo"]//text()')
houseAddr = ''.join(houseAddr)
# 位置信息
positionInfo = house.xpath('.//div[@class="positionInfo"]//text()')
positionInfo = ''.join(positionInfo)
# 总价
priceInfo = house.xpath('.//div[@class="totalPrice"]/span/text()')[0] + '万'
# 平方价
unitPrice = house.xpath('.//div[@class="unitPrice"]/span/text()')[0]
print(houseTitle,houseUrl,houseAddr,positionInfo,priceInfo,unitPrice)
# 保存成csv文件
with rlock:
with open('./data/'+area+'.csv','a+',encoding='utf-8',errors='ignore') as f:
writer = csv.writer(f)
writer.writerow([houseTitle,houseUrl,houseAddr,positionInfo,priceInfo,unitPrice])
# 获取总页数
pageTotal = getPageTotal(url)
# 创建协程
g = gevent.spawn(houesInfo, area, url, pageTotal)
# 保证协程正常结束
gevent.joinall([g])
if __name__ == '__main__':
#设置种子url
cityUrl = "https://gz.lianjia.com/ershoufang/"
# 获取区域列表
areaDict = getAreaList(cityUrl)
processList = []
time.clock()
for areaName,areaUrl in areaDict.items():
# 创建进程
p = multiprocessing.Process(target=getHouseInfo,args=(areaName,areaUrl))
p.start()
processList.append(p)
# 保证进程正常结束
for p in processList:
p.join()
print(time.clock())
后记
【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。
也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!
公众号


关注我,我们一起成长~~
Python爬虫练习(多线程,进程,协程抓取网页)的更多相关文章
- python单线程,多线程和协程速度对比
在某些应用场景下,想要提高python的并发能力,可以使用多线程,或者协程.比如网络爬虫,数据库操作等一些IO密集型的操作.下面对比python单线程,多线程和协程在网络爬虫场景下的速度. 一,单线程 ...
- Python爬虫工程师必学——App数据抓取实战 ✌✌
Python爬虫工程师必学——App数据抓取实战 (一个人学习或许会很枯燥,但是寻找更多志同道合的朋友一起,学习将会变得更加有意义✌✌) 爬虫分为几大方向,WEB网页数据抓取.APP数据抓取.软件系统 ...
- Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺
更新 其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经 ...
- Python爬虫工程师必学APP数据抓取实战✍✍✍
Python爬虫工程师必学APP数据抓取实战 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大 ...
- Python爬虫工程师必学——App数据抓取实战
Python爬虫工程师必学 App数据抓取实战 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大 ...
- 也说性能测试,顺便说python的多进程+多线程、协程
最近需要一个web系统进行接口性能测试,这里顺便说一下性能测试的步骤吧,大概如下 一.分析接口频率 根据系统的复杂程度,接口的数量有多有少,应该优先对那些频率高,数据库操作频繁的接口进行性能测试,所以 ...
- python 多进程,多线程,协程
在我们实际编码中,会遇到一些并行的任务,因为单个任务无法最大限度的使用计算机资源.使用并行任务,可以提高代码效率,最大限度的发挥计算机的性能.python实现并行任务可以有多进程,多线程,协程等方式. ...
- Python并发编程——多线程与协程
Pythpn并发编程--多线程与协程 目录 Pythpn并发编程--多线程与协程 1. 进程与线程 1.1 概念上 1.2 多进程与多线程--同时执行多个任务 2. 并发和并行 3. Python多线 ...
- Python多进程、多线程、协程
转载:https://www.cnblogs.com/huangguifeng/p/7632799.html 首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是C ...
随机推荐
- 【extern】【static】
C语言根据变量的生存周期来划分,可以分为静态存储方式和动态存储方式. 静态存储方式:是指在程序运行期间分配固定的存储空间的方式.静态存储区中存放了在整个程序执行过程中都存在的变量,如全局变量. 动态存 ...
- Python练习题 033:Project Euler 005:最小公倍数
本题来自 Project Euler 第5题:https://projecteuler.net/problem=5 # Project Euler: Problem 5: Smallest multi ...
- DIV垂直滚动效果源码
<div id="demo" style="width: 300; overflow: hidden; line-height:24px; height: 100p ...
- Spring Boot 第六弹,拦截器如何配置,看这儿~
持续原创输出,点击上方蓝字关注我吧 目录 前言 Spring Boot 版本 什么是拦截器? 如何自定义一个拦截器? 如何使其在Spring Boot中生效? 举个栗子 思路 根据什么判断这个接口已经 ...
- arduino中SCoop库的简单应用案例
转载:https://www.csdn.net/gather_27/MtTaggzsMDExMS1ibG9n.html arduino中SCoop库的简单应用案例首先这篇文章来在视频https://v ...
- 用< 100行代码向EPUB或Web服务器添加视频回放
下载source - 32.3 KB 下载latest version from GituHub 介绍 在我 在关于CodeProject的前一篇文章中,我展示了一个简单的EPUB查看器 Androi ...
- [学习笔记] Tarjan算法求强连通分量
今天,我们要探讨的就是--Tarjan算法. Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题. 首 ...
- OpenStack最新版本--Victoria发布亮点与初体验
前言 `OpenStack`是一个云操作系统,可控制整个数据中心内的大型计算,存储和网络资源池,所有资源均通过具有通用身份验证机制的`API`进行管理和配置. 还提供了一个仪表板,可让管理员进行控制, ...
- ASP.Net Core3.1 生成二维码填坑
ASP.Net Core3.1 使用QrCode生成二维码 部署到Linux报错 The type initializer for 'System.DrawingCore.GDIPlus' threw ...
- JSON,数组根据字段多次分组
我们在前端开发过程中,遇到json对象,有时会需要多次分组.比如说,先按照是业务分组,然后再按照产品线分组,然后通过table或其他方式展示或操作 var obj1=[ { "demp&qu ...