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)
# 本來需要十幾分鐘的爬蟲,利用併發只需要一分鐘就可以爬取完成,十分迅速
 

以上就是整個併發的爬取方法,利用這個方法學到它的原理即可,不要生搬硬套,知道它是怎麼工作的,以後遇到這樣的也就迎刃而解!

另外,線程數也不是越多越好,根據自己的計算機性能進行設定!

謝謝關注!

需要獲取數據,又不懂爬蟲的可以私信!


分享到:


相關文章: