1. 程式人生 > >多線程Beatiful Soup爬取鬥魚所有在線主播的信息

多線程Beatiful Soup爬取鬥魚所有在線主播的信息

category con 讀取 教程 stc https rom webkit date

  最近看了個爬蟲的教程,想著自己也常在鬥魚看直播,不如就拿它來練練手。於是就寫了個爬取鬥魚所有在線主播的信息,分別為類別、主播ID、房間標題、人氣值、房間地址。

  需要用到的工具python3下的bs4,requests,pymongo。我用的IDE是pycharm,感覺這個軟件實在太強大,有點離開它什麽都不會的感覺,數據庫Mongodb,結合pycharm工具可以直接在右側顯示數據。

#-*- coding:utf-8 -*-
from bs4 import BeautifulSoup
import requests, time ,datetime
import json
import
pymongo class douyu_host_info(): def __init__(self): self.date_time = datetime.datetime.now().strftime(%Y-%m-%d_%H-%M) self.host_url = https://www.douyu.com self.list_data = [] self.urls_list = [] self.headers = { User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
, } def get_url(self): #獲取所有類別的網站地址 urls = https://www.douyu.com/directory data = requests.get(urls) Soup = BeautifulSoup(data.text, lxml) list = Soup.select(.r-cont.column-cont dl dd ul li a) for i in list: urls = i.get(
href) self.urls_list.append(urls) print (self.urls_list) return self.urls_list def get_info(self, url): #查詢所需信息並寫調用寫入數據庫及本地磁盤的函數 time.sleep(1) #避免服務器承壓過大,每個網站爬取設置1s間隔 url = self.host_url + url print (Now start open {}.format(url)) get_data = requests.get(url, headers=self.headers) Soup = BeautifulSoup(get_data.text, lxml) names = Soup.select(.ellipsis.fl) nums = Soup.select(.dy-num.fr) titles = Soup.select(.mes h3) hrefs = Soup.select(#live-list-contentbox li a) #網站中帶directory時只是一個分類頁面沒有主播信息 if directory in url: pass #異常處理,有少數類別的HTML元素有差別,這裏就舍棄了 try: category = Soup.select(.listcustomize-topcon-msg h1)[0].get_text() except: category = 秩名類別 for name, num, href, title in zip(names, nums, hrefs, titles): data = { 類別: category, 主播: name.get_text(), 標題: title.get_text().split(\n)[-1].strip(), 鏈接: https://www.douyu.com + href.get(href), #把人氣指數轉換成以萬為單位的浮點型,方便後面計算查找 人氣指數: float(num.get_text()[:-1]) if in num.get_text() else float(num.get_text())/10000, } if data[人氣指數] > 2: print (data) self.w_to_local(data) self.w_to_db(data) def open_data(self, date_time): #需要用到時可以輸入指定時間點讀取本地保存的數據 with open(D:\douyu_host{}.csv.format(date_time), r) as r_data: r_data = json.load(r_data) for i in r_data: print (i) def w_to_local(self,data): #在將數據寫入數據庫的同時在本地磁盤保存一份 with open(D:\douyu_host{}.csv.format(self.date_time), a) as w_data: json.dump(data, w_data) def w_to_db(self, data): #將數據寫入一個以時間為後綴的數據庫表, data需要是字典格式 client = pymongo.MongoClient(localhost, 27017) walden = client[walden_{}.format(self.date_time)] sheet_tab = walden[sheet_tab] if data is not None: sheet_tab.insert_one(data) def check_from_db(self, date_time): #輸入時間從數據庫查詢相關人氣信息 client = pymongo.MongoClient(localhost, 27017) walden = client[walden_{}.format(date_time)] sheet_tab = walden[sheet_tab] for data in sheet_tab.find({人氣指數:{$gte:40}}): print (data)

  本來沒想用類來寫的,後來發現很多數據傳來傳去很亂,而且重要的數據存儲時間不好統一,於是就寫在一個類裏了。裏面很關鍵的一點,用select模塊選取元素路徑,如下圖。

技術分享圖片

  復制出來的是很長的一段路徑,可以慢慢觀察選取主要的關鍵字段就好了。

  然後新建一個py文件用來調用之前寫好的類,實例化後,用pool多線程運行,結果就出來了。

#-*- coding:utf-8 -*-
import time
from multiprocessing import Pool
from test0822 import douyu_host_info

douyu = douyu_host_info()


if __name__ == __main__:
    #多線程爬取數據
    urls_list = douyu.get_url()
    pool = Pool()
    pool.map(douyu.get_info, urls_list)

來個運行後的全景圖。

技術分享圖片

多線程Beatiful Soup爬取鬥魚所有在線主播的信息