某魚直播資料全站爬取

海和他的風發表於2020-04-05

前言

本次爬取使用了代理IP,爬取全站為1個小時,當然也可以不用代理proxy,但是要設定爬取速度 time.sleep(5) 先附上完整程式碼,下面有詳解

import csv
from fake_useragent import UserAgent
import json

from lxml import etree

import requests

# 代理伺服器
proxyHost = "http-dyn.abuyun.com"
proxyPort = "9020"

# 代理隧道驗證資訊
proxyUser = "HM89Z6WLA4F6N05D"
proxyPass = "C8CF37D06DBED9DB"

proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
    "host": proxyHost,
    "port": proxyPort,
    "user": proxyUser,
    "pass": proxyPass,
}

proxies = {
    "http": proxyMeta,
    "https": proxyMeta,
}


headers = {"User-Agent": '{}'.format(UserAgent().random),
           "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
           "Accept-Language": "en-us",
           "Connection": "keep-alive",
           "Accept-Charset": "GB2312,utf-8;q=0.7,*;q=0.7"}


#-------- 獲取 遊戲名稱 和 url ------------#
directory_url = 'https://www.douyu.com/directory'

Web = requests.get(directory_url, headers=headers, proxies=proxies).text

dom = etree.HTML(Web)

Game_urls_list = []
Game_names_list = []
for i in range(3, 13):
    Game_names = dom.xpath('//*[@id="allCate"]/section/div[{}]/ul/li/a/strong/text()'.format(i))
    Game_urls = dom.xpath('//*[@id="allCate"]/section/div[{}]/ul/li/a/@href'.format(i))

#--------------遊戲名和遊戲url放入新的列表,並分割遊戲url(後面會用到)----------#
    for Gn in Game_names:
        Game_names_list.append(Gn)
    for Gu in Game_urls:
        G_url = Gu.split('_')[1]
        Game_urls_list.append(G_url)

#----------把名字和url存入字典------------#
All_game = dict(zip(Game_names_list, Game_urls_list))


#----------依次取出字典的 key 迴圈----------#
for G_name in All_game.keys():
    print("===========正在爬取========", G_name)
    count = 1  # 因為不同遊戲分割槽,爬取頁數不一樣,用count計數做一個靈活的爬取辦法

    for page in range(1, 350):   #觀察得一個遊戲最多不會超過350頁
        # time.sleep(5)
        base_api = 'https://m.douyu.com/api/room/list?page={}&type={}'.format(page, All_game['{}'.format(G_name)])
        try:
            response = requests.get(base_api, headers=headers, proxies=proxies, timeout=30, verify=False).text

        except IOError:
            pass

        RoomList = json.loads(response).get('data').get('list')

        if len(RoomList) > 1:
        # 本頁api有資料,count+1
            count += 1
            path = '/home/liuyang/Spider/Scrapy_Project/BS_Spider/Douyu/Info_Douyu2020-04-05-14:00.csv'

            for room in RoomList:
                GameName = G_name
                RoomId = room.get('rid')
                RoomName = room.get('roomName')
                BlogName = room.get('nickname')
                HotSpots = room.get('hn')

                with open(path, "a+", encoding='utf-8-sig') as f:
                    writer = csv.writer(f, dialect="excel")
                    csv_write = csv.writer(f)
                    csv_data = [G_name, RoomId, RoomName, BlogName, HotSpots]
                    csv_write.writerow(csv_data)
                    f.close()
                    print(G_name, RoomId, RoomName, BlogName, HotSpots)
        else:
            count -= 10
	    # 本頁沒有資料,count減去10, 
	    # 因為前面只要有資料 count就會 +1,如果page=1 那麼 count=2 ,page=2 則count=3......
	    # 一旦有一頁(最後一頁)沒有資料,那麼count -10 ,滿足conut<page 則 break,就說明這個遊戲所有頁數全部爬取完了,開始爬取下一個遊戲
        print(count, page)

        if count < page:
        # 因為有的遊戲只有 10多頁 而有的遊戲有350多頁,所以沒必要對一個10多頁遊戲的api重複請求350次
            break
		
複製程式碼

如果需要IP代理的話推薦阿布雲,可以按小時計算 1h 1塊錢,畢竟家境貧寒,代理IP可以看看一看這片文章zhuanlan.zhihu.com/p/36207770

詳解:

我們是先把各個遊戲的名稱url爬取下來並存入字典,然後再依次取出字典進入各個遊戲分割槽對所有直播間進行爬取 先從鬥魚的分類地址獲取所有遊戲:www.douyu.com/directory

directory_url = 'https://www.douyu.com/directory'
複製程式碼

獲取url和名稱

獲取一個遊戲所有直播資料: 先從鬥魚的分類地址:www.douyu.com/directory,中點開一個遊戲,就LOL了

api介面都是一樣的
點進去後,不用進入直播間,我們直接從api介面獲取資料,比如LOL第1頁的API連結就是:m.douyu.com/api/room/li…
LOL的api
API 頁面是這樣的
這就是我們想要的資料了!
Over!

Gei it !
最後歡迎訪問我的個人部落格:wangwanghub.com

鄭重宣告:本專案及所有相關文章,僅用於經驗技術交流,禁止將相關技術應用到不正當途徑,因為濫用技術產生的風險與本人無關。

相關文章