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 ...
随机推荐
- FastDFS 分布式文件系统详解
什么是文件系统 文件系统是操作系统用于在磁盘或分区上组织文件的方法和数据结构.磁盘空间是什么样的我们并不清楚,但文件系统可以给我们呈现一个非常清晰的表象,我们可以创建.删除.修改和复制这些文件,而实现 ...
- 数论(8):min_25 筛(扩展埃氏筛)
min_25 筛介绍 我们考虑这样一个问题. \[ans=\sum_{i = 1}^nf(i)\\ \] 其中 \(1 \le n \le 10^{10}\) 其中 \(f(i)\) 是一个奇怪的函数 ...
- spring-boot-route(五)整合Swagger生成接口文档
目前,大多数公司都采用了前后端分离的开发模式,为了解决前后端人员的沟通问题,后端人员在开发接口的时候会选择使用swagger2来生成对应的接口文档,swagger2提供了强大的页面调试功能,这样可以有 ...
- 版本控制系统之基于httpd搭建私有git仓库
在上一篇博客中,我们主要聊到了git的基本工作原理和一些常用的git命令的使用:回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13787701.html:今天我 ...
- 对ACE和ATL积分
下载source code - 39.66 KB 介绍 这篇文章展示了一种结合ACE和ATL的方法.它不打算作为功能演示,而是作为一个小型的"入门"解决方案,展示实现此目标的可行方 ...
- [KMP]字符串匹配算法
算法介绍: KMP是一种用来处理字符串匹配问题的算法,给你两个字符串A.B,让你回答B是否为A的子串,或者A中有多少子串等于B. 这题最暴力的做法是:枚举A中与B相等的子串的左端点,再判断是否与B相等 ...
- Word+Excel 问题及解决
[Word] 快捷操作 (1)每个字后面都有换行符的处理办法: 替换:∧p -> 空格 (2)隐藏Word文档中的换行符: word选项 -> 显示 -> 段落标记 [Excel]
- css做模糊处理
-webkit-filter: blur(9px); filter: blur(9px);
- GDB将所有线程堆栈输出到文件
在调试多线程程序时,经常需要查看线程堆栈信息,如果线程数目过多,每次查看一个线程堆栈,繁琐耗时.下面介绍一种一次性将所有线程堆栈输出到文件的方法. 首先,将gdb attach到调试线程 gdb -p ...
- centos 7.0 更改启动环境/启动进入图形界面/命令行模式
当前我桌面模式 systemctl set-default multi-user.target ln -sf /lib/systemd/system/multi-user.target /etc/sy ...