天天看點

python爬蟲之多線程爬取--小米應用商店

多線程爬蟲

應用場景

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))