python使用并发法爬取二手房数据,速度提升不止十倍

前言

本次爬虫使用的方法是多线程并发,加快了一般方法的速度,我们用的一般方法是requests+BeautifulSoup这两个库对网站进行请求、解析,再根据自身需求抓取数据。

但是这种方法比较慢,只有一个线程,再加上我们要进行IO操作,会更加降低速度,因此为了加速爬虫速度,这次我们根据实战详细了解一下多线程并发的方法,速度提升不止十倍,甚至二十倍六十倍上百倍!相信仔细看完这篇文章,您会对多线程并发有一个深刻的了解!

python使用并发法爬取二手房数据,速度提升不止十倍

整体过程讲解

爬取的网站:安居客最新二手房:
https://changchun.anjuke.com/sale/o5-p5/#filtersort

使用的第三方库:requests、BeautifulSoup、csv和concurrent.futures模块里面的ThreadPoolExecutor, wait, ALL_COMPLETED

这些库的具体使用会在下面的代码中提到,接下来看一下整个代码的过程以及详细分析,各种解释都在代码中解释的很详细,大家仔细查看!

"""
使用并发爬取一定要注意网站要验证等问题
不然影响爬虫进度
另外代理的话也要多一点
寿命不长没关系,很快就能爬取完
长期代理爬取速度太快需要谨慎
不然容易被马上查到
并发在一般同步爬取的基础上加入并发加速器,多线程进行爬取
"""
# 导入请求库requests用于向网站服务器发送请求
import requests
# 导入解析库,用于解析服务器返回的文件比如html文件
from bs4 import BeautifulSoup
# 导入时间库,用于模仿人类行为,防止被封ip
import time
# 导入加速器,用于开启多线程,加速整个爬取过程
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
# 导入csv库,用于将爬取到的数据写入表格,存在本地excel
import csv
# 开始时间,从程序开头计时,判断算法的运行优劣
t1 = time.time()
print('#' * 50)
# 加入代理,这里的代理是我购买的,已经更改不能使用,需要自己找代理
proxy = "zhaoshuang:[email protected]:28803"
proxies = {
 'http': 'http://' + proxy,
 'https': 'https://' + proxy
}
# 加入请求头,用于模仿用户在浏览器端操作
headers = {
 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}

# 定义解析函数,用于获取每个网页需要爬取的内容
def parser(url):
 # 对网站发送请求,获取返回值
 res = requests.get(url, headers=headers)
 # 对响应体res.text进行解析,解析方式为‘lxml’
 soup = BeautifulSoup(res.text, "lxml")
 # 用select函数抽取需要的内容,在网页中鼠标放在需要的内容上面,右键-检查-copy select
 # 以下是我在安居客上想要爬取的内容
 # 爬取二手房标题
 titles = soup.select("#houselist-mod-new > li > div.house-details > div.house-title > a") 
 # 爬取地址
 addresses = soup.select(
 "#houselist-mod-new > li > div.house-details > div:nth-child(3) > span.comm-address") 
 # 爬取每平方米的单价
 dprices = soup.select("#houselist-mod-new > li > div.pro-price > span.unit-price") 
 # 爬取二手房的总价
 tprices = soup.select("#houselist-mod-new > li > div.pro-price > span.price-det > strong") 
 # 爬取总面积
 areas = soup.select(
 "#houselist-mod-new > li > div.house-details > div:nth-child(2) > span:nth-child(3)") 
 # 爬取建造年份
 years = soup.select(
 '#houselist-mod-new > li > div.house-details > div:nth-child(2) > span:nth-child(7)') 
 # 爬取楼层数
 lous = soup.select("#houselist-mod-new > li > div.house-details > div:nth-child(2) > span:nth-child(5)") 
 # 爬取有多少个厅室
 tings = soup.select(
 '#houselist-mod-new > li > div.house-details > div:nth-child(2) > span:nth-child(1)') 
 # 爬取周边的交通情况
 traffics = soup.select('#houselist-mod-new > li > div.house-details > div.tags-bottom') 
 # 以下把爬取到的内容导出到csv文件中
 for title, address, dprice, tprice, area, year, lou, ting, traffic in zip(titles, addresses, dprices, tprices,
 areas, years, lous, tings, traffics):
 # 建立空列表,分配存储地址
 dprice = dprice.text, # 价格直接获取里面的文本就可以,两边是标签
 dprice = dprice[0].strip("元/m²")
 tprice = tprice.text, # 价格直接获取里面的文本就可以,两边是标签
 tprice = tprice[0]
 title = title.text.strip(), # 获得文本并去除掉文本两侧的不必要的字符,用strip()
 address = address.text.strip() # 同样地址也是去除两头不必要的字符串
 address = address.split('\xa0\xa0\n'),
 address = address[0][0] + address[0][1].strip(),
 area = area.text,
 area = area[0],
 year = year.text,
 lou = lou.text,
 ting = ting.text,
 traffic = traffic.text.strip('\n')
 data = [title[0], address[0], dprice, tprice, area[0], year[0], lou[0], ting[0], traffic] # 将以上数据放入列表中打印在命令框
 print(data)
 # 将爬取到的内容写入到csv文件中
 with open('二手房/最新8.7/华北东北/长春.csv', 'a', newline='',
 encoding='utf-8-sig') as csvfile:
 w1 = csv.writer(csvfile)
 w1.writerow(data)
 # 模仿人类行为,睡眠一秒
 time.sleep(1)
# 定义要爬取的网站,这里我一共要爬取50页,所以一共有50个网站url
urls = ['https://changchun.anjuke.com/sale/o5-p{}/#filtersort'.format(number) for number in range(1, 51)]
# 利用并发加速爬取,最大线程为50个,本文章中一共有50个网站,可以加入50个线程,一般来说,最好的线程数是电脑核心数*2+2个线程,这个时候爬取效率以及质量都很高
# 建立一个加速器对象,线程数每个网站都不同,太大网站接受不了会造成数据损失,这里我加入十个线程,因为我的电脑是4核心,这里创建一个10线程的加速器对象executor

executor = ThreadPoolExecutor(max_workers=10)
# submit()的参数: 第一个为函数, 之后为该函数的传入参数,允许有多个,这里给加速器对象提交一个任务
future_tasks = [executor.submit(parser, url) for url in urls]
# 等待所有的线程完成,才进入后续的执行
wait(future_tasks, return_when=ALL_COMPLETED)
# 计算总用时间
t2 = time.time() # 结束时间
print('并发方法,总共耗时:%s' % (t2 - t1))
print('#' * 50)
# 本来需要十几分钟的爬虫,利用并发只需要一分钟就可以爬取完成,十分迅速
 

以上就是整个并发的爬取方法,利用这个方法学到它的原理即可,不要生搬硬套,知道它是怎么工作的,以后遇到这样的也就迎刃而解!

另外,线程数也不是越多越好,根据自己的计算机性能进行设定!

谢谢关注!

需要获取数据,又不懂爬虫的可以私信!


分享到:


相關文章: