用Python爬取斗魚網站的一個小案例


思路解析:

  1、我們需要明確爬取數據的目的:為了按熱度查看主播的在線觀看人數

  2、瀏覽網頁源代碼,查看我們需要的數據的定位標簽

        

 

 

  3、在代碼中發送一個http請求,獲取到網頁返回的html(需要注意的是,許多網頁都有反爬蟲機制,所以需要在請求中添加user-agent,偽裝成客戶端訪問)

  4、對獲取到的html進行分析,使用正則表達式提取我們需要的部分(需要注意的是要把主播名稱和觀看人數所在的塊整個提取,分別提取的話如果網頁設計不規律的話很難對應)

  5、將得到的單個主播的數據存儲在字典中,並把所有主播的數據存儲在list中

  6、如果抓取到的數據中包含空格換行等無用字符,還需要對數據進行精煉。

  7、對抓取到的數據從大到小進行排序(需要注意的是:我們抓取到的數據是字符串,並且單位可能是人或者萬人,所以要對觀看人數進行處理)

  8、將排好序的數據遍歷輸出。

由於斗魚網站的網頁是采用模板實現的,案例是抓取王者榮耀的主播的數據,想抓取別的類目的話,只需要修改url即可~

 

代碼實現:

'''
    爬取斗魚網站的王者榮耀分類主播的觀看人數和主播名字,並按熱度排名
'''
from urllib import request
from io import BytesIO
import gzip
import re


class Spider():
    url = 'https://www.douyu.com/g_wzry'

    # 根節點的字符串匹配正則表達式,匹配除了根節點中間的所有字符,非貪婪模式,找到第一個</div>就結束
    root_pattern = '<div class="DyListCover-info">([\s\S]*?)</div>'

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'}

    # 觀看人數匹配字符串
    number_pattern_str = '<span class="DyListCover-hot is-template">([\s\S]*?)</span>'
    # 觀看人數的字符串,刪除前面的icon部分
    number_pattern = '<svg><use xlink:href="#icon-hot_8a57f0b"></use></svg>'

    name_pattern_str = '<h2 class="DyListCover-user is-template">([\s\S]*?)</h2>'
    name_pattern = '<svg><use xlink:href="#icon-user_c95acf8"></use></svg>'

    # 抓取自定網頁內容並解碼
    def __fetch_content(self):
        # 發送一個http的請求,獲取返回的html代碼
        req = request.Request(Spider.url, headers=Spider.headers)
        htmls = request.urlopen(req).read()

        # 解碼
        buff = BytesIO(htmls)
        f = gzip.GzipFile(fileobj=buff)
        htmls = f.read().decode('utf-8')
        return htmls

    # 分析抓取內容,選取標簽時盡量選取閉合標簽,標簽成組的選擇好對應
    def __analysis(self, htmls):
        # 獲取到需要的全部數據
        root_html = re.findall(Spider.root_pattern, htmls)
        # 由於網頁中一個塊有兩個相同的class類,其中第一個主播介紹
        # 第二個才是需要的數據,所以選取奇數下標元素
        root_info_html = root_html[1::2]

        # 最后獲取到的數據列表
        anchors = []
        # 遍歷列表,提取用戶名和觀看人數
        for html in root_info_html:
            # 提取到的是帶icon的部分
            watch_num_str = re.findall(Spider.number_pattern_str, html)
            # 剔除icon部分
            watch_num = re.sub(Spider.number_pattern, '', watch_num_str[0])

            # 提取帶icon的name的部分
            name_str = re.findall(Spider.name_pattern_str, html)
            name = re.sub(Spider.name_pattern, '', name_str[0])

            # 將名字和觀看人數用字典存儲,最后再用列表存儲每個主播的數據
            anchor = {'name': name, 'number': watch_num}
            anchors.append(anchor)

        return anchors

    # 精煉函數
    # def __refine(self, anchors):
    #    lam = lambda anchor: {'name': anchor['name'][0], 'number': anchor['number'][0]}
    #    return map(lam, anchors)

    # 排序
    def __sort(self, anchors):
        anchors = sorted(anchors, key=self.__sort_key, reverse=True)
        return anchors

    # 排序規則
    def __sort_key(self, anchor):
        # 提取數字並計算
        r = re.findall('\d*', anchor['number'])
        number = float(r[0])
        if '' in anchor['number']:
            number *= 10000
        return number

    # 顯示數據
    def __show(self, anchors):
        # for anchor in anchors:
        #    print(anchor['name'], ':', anchor['number'])
        for rank in range(0, len(anchors)):
            print("Rank ", rank+1, ": ", anchors[rank]['name'], "    ", anchors[rank]['number'])

    # 入口方法
    def go(self):
        htmls = self.__fetch_content()
        anchors = self.__analysis(htmls)
        anchors = self.__sort(anchors)
        self.__show(anchors)


spider = Spider()
spider.go()

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM