溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)

發(fā)布時間:2021-11-23 11:46:55 來源:億速云 閱讀:413 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要講解了“怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)”吧!

尋找彈幕信息

愛奇藝的彈幕數(shù)據(jù)已通過.z形式的壓縮文件存在,先通過以下步驟找到彈幕url, tvid列表,再獲取壓縮文件。利用工具對獲取的壓縮文件進(jìn)行解壓,處理,存儲及分析。

怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)

絕對,實行多頁爬取,需要分析url規(guī)律,利用url規(guī)律循環(huán)請求并獲取所需內(nèi)容。

此彈幕文件url地址為
https://cmts.iqiyi.com/bullet/93/00/6024766870349300_300_1.z
其中tvid = 6024766870349300

url普適形式為
url ='https:
//cmts.iqiyi.com/bullet/{ }/{}/{   }_300_{}.z '其中第一個與第二個花括號內(nèi)容是tvid后3、4位,,后1、2位。第三個花括號為tvid。第四個花括號為子文件序號,其不是一個無窮大的數(shù),會根據(jù)不同的電視劇有不同的最大數(shù)。

怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)

輸入網(wǎng)址可獲取彈幕內(nèi)容的壓縮文件文件。

利用解壓/壓縮包zlib對下載下來的壓縮文件進(jìn)行解壓查看。

import zlib
from bs4 import BeautifulSoup
with open(r"C:\Users\HP\Downloads\6024766870349300_300_10.z", 'rb') as fin:
    content = fin.read()
btArr = bytearray(content)
xml=zlib.decompress(btArr).decode('utf-8')
bs = BeautifulSoup(xml,"xml")
bs

輸出

怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)

因此tvid只要獲得就能輕松獲取該電視劇的彈幕文件數(shù)據(jù)。

import zlib
from bs4 import BeautifulSoup
import pandas as pd
import requests
def get_data(tv_name,tv_id):
    """
    獲取每集的tvid
    :param tv_name: 集數(shù),第1集、第2集...
    :param tv_id: 每集的tvid
    :return: DataFrame, 最終的數(shù)據(jù)
    """
    base_url = 'https://cmts.iqiyi.com/bullet/{}/{}/{}_300_{}.z'
    # 新建一個只有表頭的DataFrame
    head_data = pd.DataFrame(columns=['uid','contentsId','contents','likeCount'])
    for i in range(1,20):
        url = base_url.format(tv_id[-4:-2],tv_id[-2:],tv_id,i)
        print(url)
        res = requests.get(url)
        if res.status_code == 200:
            btArr = bytearray(res.content) 
            xml=zlib.decompress(btArr).decode('utf-8') # 解壓壓縮文件
            bs = BeautifulSoup(xml,"xml") # BeautifulSoup網(wǎng)頁解析
            data = pd.DataFrame(columns=['uid','contentsId','contents','likeCount'])
            data['uid'] = [i.text for i in bs.findAll('uid')]
            data['contentsId'] = [i.text for i in bs.findAll('contentId')]
            data['contents'] = [i.text for i in bs.findAll('content')]
            data['likeCount'] = [i.text for i in bs.findAll('likeCount')]
        else:
            break
        head_data = pd.concat([head_data,data],ignore_index = True)
    head_data['tv_name']= tv_name
    return head_data

獲取tvid

上文已通過tvid獲取到了彈幕文件數(shù)據(jù),那么如何獲取tvid又變成了一個問題。莫急,我們繼續(xù)分析。直接Ctrl + F搜索tvid

因此可以直接從返回結(jié)果中通過正則表達(dá)式獲取tvid。

from requests_html import HTMLSession, UserAgent
from bs4 import BeautifulSoup
import re
def get_tvid(url):
    """
    獲取每集的tvid
    :param url: 請求網(wǎng)址
    :return: str, 每集的tvid
    """
    session = HTMLSession()   #創(chuàng)建HTML會話對象
    user_agent = UserAgent().random  #創(chuàng)建隨機(jī)請求頭
    header = {"User-Agent": user_agent}
    res = session.get(url, headers=header)
    res.encoding='utf-8'
    bs = BeautifulSoup(res.text,"html.parser")
    pattern =re.compile(".*?tvid.*?(\d{16}).*?") # 定義正則表達(dá)式
    text_list = bs.find_all(text=pattern) # 通過正則表達(dá)式獲取內(nèi)容
    for t in range(len(text_list)):
        res_list = pattern.findall(text_list[t])
        if not res_list:
            pass
        else:
            tvid = res_list[0]
    return tvid

由此問題tvid。來每一集都有一個tvid,有多少集電視劇就可以獲取多少個tvid。那么問題又來了:獲取tvid時,是通過url發(fā)送請求,從返回結(jié)果中獲取。而每一集的url又該如何獲取呢。

獲取每集url

通過元素選擇工具定位到集數(shù)選擇信息。通過硒模擬瀏覽器獲取動態(tài)加載信息。

怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)

有小伙伴會說,可以直接直接從返回內(nèi)容中獲取此href網(wǎng)址啊,你可以自己動手嘗試下。

云朵君嘗試后得到的結(jié)果是href="javascript:void(0);",因此解決這一問題的方法之一是運用硒模擬瀏覽器獲取js動態(tài)加載信息。

def get_javascript0_links(url, class_name, class_name_father, sleep_time=0.02):
    """
    Selenium模擬用戶點擊爬取url
    :param url: 目標(biāo)頁面
    :param class_name: 模擬點擊的類
    :param class_name_father: 模擬點擊的類,此類為class_name的父類
    :param sleep_time: 留給頁面后退的時間
    :return: list, 點擊class為class_name進(jìn)去的超鏈接
    """

    def wait(locator, timeout=15):
        """等到元素加載完成"""
        WebDriverWait(driver, timeout).until(EC.presence_of_element_located(locator))

    options = Options()
#     options.add_argument("--headless")  # 無界面,若你需要查看界面內(nèi)容,可以將此行注釋掉
    driver = webdriver.Chrome(options=options)
    driver.get(url)

    locator = (By.CLASS_NAME, class_name)
    wait(locator)
    element = driver.find_elements_by_class_name(class_name_father)
    elements = driver.find_elements_by_class_name(class_name)
    link = []
    linkNum = len(elements)
    for j in range(len(element)):
        wait(locator)
        driver.execute_script("arguments[0].click();", element[j]) # 模擬用戶點擊
        for i in range(linkNum):
            print(i)
            wait(locator)
            elements = driver.find_elements_by_class_name(class_name) # 再次獲取元素,預(yù)防StaleElementReferenceException
            driver.execute_script("arguments[0].click();", elements[i]) # 模擬用戶點擊
            time.sleep(sleep_time)
            link.append(driver.current_url)
            time.sleep(sleep_time)
            driver.back()
    driver.quit()
    return link

if __name__ == "__main__":
    url = "https://www.iqiyi.com/v_1meaw5kgh4s.html"
    class_name = "qy-episode-num"
    link = get_javascript0_links(url, class_name, class_name_father="tab-bar")
    for i, _link in enumerate(link):
        print(i, _link)

主函數(shù)

接下來通過主函數(shù)將所有步驟串起。

def main(sleep_second=0.02):
    url = "https://www.iqiyi.com/v_1meaw5kgh4s.html"
    class_name = "select-item"
    class_name_father = "bar-li"
    links = get_javascript0_links(url, class_name, class_name_father)
    head_data = pd.DataFrame(columns=['tv_name','uid','contentsId','contents','likeCount'])
    for num, link in enumerate(links):
        tv_name = f"第{num+1}集"
        tv_id = get_tvid(url=link)
        data = get_data(tv_name,tv_id)
        head_data = pd.concat([head_data,data],ignore_index = True)
        time.sleep(sleep_second)
    return head_data

獲取到的數(shù)據(jù)結(jié)果如下:

>>> data = main()
>>> data.info()
"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 246716 entries, 0 to 246715
Data columns (total 5 columns):
 #   Column      Non-Null Count   Dtype 
---  ------      --------------   ----- 
 0   tv_name     246716 non-null  object
 1   uid         246716 non-null  object
 2   contentsId  246716 non-null  object
 3   contents    246716 non-null  object
 4   likeCount   246716 non-null  object
dtypes: object(5)
memory usage: 9.4+ MB
"""
>>> data.sample(10)

詞云圖

  • 先分詞

運用中文分詞庫jieba分詞,并去除撤銷詞。

def get_cut_words(content_series):
    """
    :param content_series: 需要分詞的內(nèi)容
    :return: list, 點擊class為class_name進(jìn)去的超鏈接
    """
    # 讀入停用詞表
    import jieba 
    stop_words = [] 
    with open("stop_words.txt", 'r', encoding='utf-8') as f:
        lines = f.readlines()
        for line in lines:
            stop_words.append(line.strip())
    # 添加關(guān)鍵詞
    my_words = ['倪妮', '劉詩詩', '鎖鎖', '蔣三歲', '陳道明']      
    for i in my_words:
        jieba.add_word(i) 
    # 自定義停用詞
    my_stop_words = ['哈哈哈','哈哈哈哈', '真的']    
    stop_words.extend(my_stop_words)               
    # 分詞
    word_num = jieba.lcut(content_series.str.cat(sep='。'), cut_all=False)
    word_num_selected = [i for i in word_num if i not in stop_words and len(i)>=2] # 條件篩選
    
    return word_num_selected
  • 后畫圖

運用升級版詞云圖庫stylecloud可視化彈幕結(jié)果。

import stylecloud
from IPython.display import Image 
text1 = get_cut_words(content_series=data.contents)
stylecloud.gen_stylecloud(text=' '.join(text1), collocations=False,
                          font_path=r'?C:\Windows\Fonts\msyh.ttc',
                          icon_name='fas fa-rocket',size=400,
                          output_name='流金歲月-詞云.png')
Image(filename='流金歲月-詞云.png')

感謝各位的閱讀,以上就是“怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對怎么用Python獲取愛奇藝電視劇彈幕數(shù)據(jù)這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI