多線程Beatiful Soup爬取鬥魚所有在線主播的信息
阿新 • • 發佈:2018-09-01
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 importpymongo 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爬取鬥魚所有在線主播的信息