多線程爬取小米商城
前言:想必大家對python的多線程還不是很瞭解吧,今天我們的學習任務就是怎麼使用多線程去爬取小米商城的App應用
1. 分析目標站點
目標URL : http://app.mi.com/category/15#page=0 小米商城
點擊 “遊戲-全部應用” 下方的下一頁後發現整個頁面只刷新了部分內容,這就說明整個網頁都是動態加載來的,以下總結了怎麼去判斷整個網頁是不是動態加載的。
總結:
- 鼠標往下滾動時加載了內容,但是整個頁面沒有重新加載
- 當點擊下一頁或者往下翻滾的時候只刷新了網頁中的部分內容,整個頁面也沒有重新加載
- 當在頁面中能找到的內容在網頁源代碼中找不到此內容時
小貼士:當碰到無法抓取的動態加載網頁時,推薦使用selenium,可以python的第三方庫中安裝,這個庫可以人爲的操作瀏覽器去做自己想要做的事情,當我們以瀏覽器去操作網頁時,我們也就不用考慮這個網頁是不是動態加載的了。
2. 分析加載的數據
a) 抓包。當確定網頁中的內容是動態異步加載時,我們第一個要做的抓包,右鍵檢查進入Network → XHR中,異步加載的數據一般都可以在這裏進行顯示
b) 分析url。觀察發送請求的url,發現只有page在變,而且第一頁中的page對應的值爲0,所以只需要改變page的值便可以獲取全部的內容了。
3.分析代碼
a) 創建請求url的隊列。今天我們的主要內容是怎麼去使用多線程爬取內容,所以我們第一步要做的就是怎麼去創建發送請求url的隊列。代碼如下
我們首先將要爬取的url加入到url _list這個隊列中去
class Xmshoop_spider(object):
def __init__(self):
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'}
self.url = 'http://app.mi.com/categotyAllListApi?page={}&categoryId=15&pageSize=30' # 需要爬取的url,通過改變page的值從而獲取所有需要發送請求的url
self.url_list = Queue() # 創建先進先出隊列
def send_request(self):
pass
def parse_json(self):
pass
def main(self):
for i in range(0,67): # for循環
self.url_list.put(self.url.format(i)) # 將要爬取的url通過put方法加入到隊列中
if __name__ == '__main__':
spider = Xmshoop_spider()
spider.main()
b) 發送請求獲取數據。通過隊列的get方法取出最先put進去的url,因爲我們創建的是先進先出隊列,所以我們get得到的就是第一個放進去的url。
取出第一個url併發送請求獲取數據
def send_request(self):
response = requests.get(self.url_list.get(),headers=self.headers).json() # 通過get方法取出第一個放進去的url,然後將獲取到的json數據轉爲python中的字典類型數據
print(response)
c)分析數據。獲取到數據後肯定就要提取出我們想要的數據,這裏我告訴大家兩種提取json數據的方法
- 將獲取的json數據轉爲python中的字典類型,然後去提取
- 使用jsonpath語法直接對json數據進行操作並提取數據
d) 多線程請求數據。
def main(self):
t_list = []
for i in range(0,67): # for循環
self.url_list.put(self.url.format(i)) # 將要爬取的url通過put方法加入到隊列中
for x in range(5):
t1 = Thread(target=self.send_request) # target的值函數名
t1.start() # 啓動線程
t_list.append(t1) # 將線程加入到列表中
for t in t_list:
t.join() # 讓主線程等待子線程結束
4. 完整代碼:
import requests
from threading import Thread
from queue import Queue
class Xmshoop_spider(object):
def __init__(self):
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'}
self.url = 'http://app.mi.com/categotyAllListApi?page={}&categoryId=15&pageSize=30' # 需要爬取的url,通過改變page的值從而獲取所有需要發送請求的url
self.url_list = Queue() # 創建先進先出隊列
self.count = 0
def send_request(self):
while not self.url_list.empty():
response = requests.get(self.url_list.get(),headers=self.headers).json() # 通過get方法取出第一個放進去的url,然後將獲取到的json數據轉爲python中的字典類型數據
self.parse_json(response)
def parse_json(self,res):
for data in res['data']:
name = data['displayName']
img_url = data['icon']
print(name,img_url)
self.count += 1
def main(self):
t_list = []
for i in range(0,67):
self.url_list.put(self.url.format(i)) # 將要爬取的url通過put方法加入到隊列中
for x in range(5): # for循環5次,總共創建了5個線程去爬取
t1 = Thread(target=self.send_request) # 創建線程
t1.start() # 啓動線程
t_list.append(t1)
for t in t_list:
t.join() # 主線程會一直阻塞等待子線程結束
if __name__ == '__main__':
spider = Xmshoop_spider()
spider.main()
print(spider.count) # 顯示總共爬取了多少個數據
a) 檢查結果。一頁30個應用信息,67頁正好2010條數據,對比開啓線程和不開啓線程爬取數據所花費的時間
- 開啓10個線程花費1s
- 不開啓線程花費了10s
結語:本章的多線程學習就到這裏結束了,有覺得小編寫的還不錯的評論加點贊,你們的支持是我最大的動力。