多線程爬蟲
應用場景
1、多程序 :CPU密集程式
2、多線程 :爬蟲(網絡I/O)、本地磁盤I/O
- 隊列
# 導入子產品
from queue import Queue
# 使用
q = Queue()
q.put(url)
q.get() # 當隊列為空時,阻塞
q.empty() # 判斷隊列是否為空,True/False
- 線程子產品
# 導入子產品
from threading import Thread
# 使用流程
t = Thread(target=函數名) # 建立線程對象
t.start() # 建立并啟動線程
t.join() # 阻塞等待回收線程
# 建立多線程
t_list = []
for i in range(5):
t = Thread(target=函數名)
t_list.append(t)
t.start()
for i in t_list:
i.join()
小米應用商店抓取(多線程)
- 目标
1、網址 :百度搜 - 小米應用商店,進入官網
2、目标 :應用分類 - 聊天社交
應用名稱
應用連結
- 實作步驟
1、确認是否為動态加載
1、頁面局部重新整理
2、右鍵檢視網頁源代碼,搜尋關鍵字未搜到
# 此網站為動态加載網站,需要抓取網絡資料包分析
2、F12抓取網絡資料包
1、抓取傳回json資料的URL位址(Headers中的Request URL)
http://app.mi.com/categotyAllListApi?page={}&categoryId=2&pageSize=30
2、檢視并分析查詢參數(headers中的Query String Parameters)
page: 1
categoryId: 2
pageSize: 30
# 隻有page再變,0 1 2 3 ... ... ,這樣我們就可以通過控制page的直拼接多個傳回json資料的URL位址
- 代碼實作
import requests
from threading import Thread
from queue import Queue
import json
import time
class XiaomiSpider(object):
def __init__(self):
self.headers = {'User-Agent':'Mozilla/5.0'}
self.url = 'http://app.mi.com/categotyAllListApi?page={}&categoryId=2&pageSize=30'
# 定義隊列,用來存放URL位址
self.url_queue = Queue()
# URL入隊列
def url_in(self):
# 拼接多個URL位址,然後put()到隊列中
for i in range(67):
self.url.format((str(i)))
self.url_queue.put(self.url)
# 線程事件函數(請求,解析提取資料)
def get_page(self):
# 先get()URL位址,發請求
# json子產品做解析
# 循環從隊列中擷取url抓取資料
while True:
# 當隊列不為空時,擷取url位址
if not self.url_queue.empty():
url = self.url_queue.get()
html = requests.get(url,headers=self.headers).text
self.parse_page(html)
else:
break
# 解析函數
def parse_page(self,html):
app_json = json.loads(html)
for app in app_json['data']:
# 應用名稱
name = app['displayName']
# 應用連結
link = 'http://app.mi.com/details?id={}'.format(app['packageName'])
d = { '名稱' : name,'連結' : link }
print(d)
# 主函數
def main(self):
self.url_in()
# 存放所有線程的清單
t_list = []
for i in range(10):
t = Thread(target=self.get_page)
t.start()
t_list.append(t)
# 統一回收線程
for p in t_list:
p.join()
if __name__ == '__main__':
start = time.time()
spider = XiaomiSpider()
spider.main()
end = time.time()
print('執行時間:%.2f' % (end-start))