千家信息网

怎么用Python获取爱奇艺电视剧弹幕数据

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,这篇文章主要讲解了"怎么用Python获取爱奇艺电视剧弹幕数据",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么用Python获取爱奇艺电视剧弹幕数据
千家信息网最后更新 2025年02月03日怎么用Python获取爱奇艺电视剧弹幕数据

这篇文章主要讲解了"怎么用Python获取爱奇艺电视剧弹幕数据",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么用Python获取爱奇艺电视剧弹幕数据"吧!

寻找弹幕信息

爱奇艺的弹幕数据已通过.z形式的压缩文件存在,先通过以下步骤找到弹幕url, tvid列表,再获取压缩文件。利用工具对获取的压缩文件进行解压,处理,存储及分析。

绝对,实行多页爬取,需要分析url规律,利用url规律循环请求并获取所需内容。

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

url普适形式为
url ='https:
//cmts.iqiyi.com/bullet/{ }/{}/{ }_300_{}.z '其中第一个与第二个花括号内容是tvid后3、4位,,后1、2位。第三个花括号为tvid。第四个花括号为子文件序号,其不是一个无穷大的数,会根据不同的电视剧有不同的最大数。

输入网址可获取弹幕内容的压缩文件文件。

利用解压/压缩包zlib对下载下来的压缩文件进行解压查看。

import zlibfrom bs4 import BeautifulSoupwith 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

输出

因此tvid只要获得就能轻松获取该电视剧的弹幕文件数据。

import zlibfrom bs4 import BeautifulSoupimport pandas as pdimport requestsdef get_data(tv_name,tv_id):    """    获取每集的tvid    :param tv_name: 集数,第1集、第2集...    :param tv_id: 每集的tvid    :return: DataFrame, 最终的数据    """    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网页解析            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获取到了弹幕文件数据,那么如何获取tvid又变成了一个问题。莫急,我们继续分析。直接Ctrl + F搜索tvid

因此可以直接从返回结果中通过正则表达式获取tvid。

from requests_html import HTMLSession, UserAgentfrom bs4 import BeautifulSoupimport redef get_tvid(url):    """    获取每集的tvid    :param url: 请求网址    :return: str, 每集的tvid    """    session = HTMLSession()   #创建HTML会话对象    user_agent = UserAgent().random  #创建随机请求头    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}).*?") # 定义正则表达式    text_list = bs.find_all(text=pattern) # 通过正则表达式获取内容    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发送请求,从返回结果中获取。而每一集的url又该如何获取呢。

获取每集url

通过元素选择工具定位到集数选择信息。通过硒模拟浏览器获取动态加载信息。

有小伙伴会说,可以直接直接从返回内容中获取此href网址啊,你可以自己动手尝试下。

云朵君尝试后得到的结果是href="_javascript:void(0);",因此解决这一问题的方法之一是运用硒模拟浏览器获取js动态加载信息。

def get_javascript0_links(url, class_name, class_name_father, sleep_time=0.02):    """    Selenium模拟用户点击爬取url    :param url: 目标页面    :param class_name: 模拟点击的类    :param class_name_father: 模拟点击的类,此类为class_name的父类    :param sleep_time: 留给页面后退的时间    :return: list, 点击class为class_name进去的超链接    """    def wait(locator, timeout=15):        """等到元素加载完成"""        WebDriverWait(driver, timeout).until(EC.presence_of_element_located(locator))    options = Options()#     options.add_argument("--headless")  # 无界面,若你需要查看界面内容,可以将此行注释掉    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) # 再次获取元素,预防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 linkif __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)

主函数

接下来通过主函数将所有步骤串起。

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

获取到的数据结果如下:

>>> data = main()>>> data.info()"""RangeIndex: 246716 entries, 0 to 246715Data 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  objectdtypes: object(5)memory usage: 9.4+ MB""">>> data.sample(10)

词云图

  • 先分词

运用中文分词库jieba分词,并去除撤销词。

def get_cut_words(content_series):    """    :param content_series: 需要分词的内容    :return: list, 点击class为class_name进去的超链接    """    # 读入停用词表    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())    # 添加关键词    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可视化弹幕结果。

import stylecloudfrom 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获取爱奇艺电视剧弹幕数据"的内容了,经过本文的学习后,相信大家对怎么用Python获取爱奇艺电视剧弹幕数据这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0