乐趣区

关于python:Python爬取赘婿弹幕

前言

在近期的工作代码中我遇到了一些小问题,导致了我的更新慢了不少。明天我就想把我在之前遇到的问题分享给大家,并通过一篇实战内容来教会大家,心愿各位小伙伴当前遇到相似问题的时候,能够想起我的文章,并解决问题。

明天我要分享的常识是对于 xml 文件的解析。

什么是 XML

XML 指可拓展标记语言,规范通用标记语言的子集,是一种用于标记电子文件使其具备结构性的标记语言。XML 被设计用来传输和存储数据。XML 是一套定义语义的标记规定,这些标记将文档的许多部件并对这些部件加以标识。他也是元标记语言,即定义了用于定义其余畛域无关的、语义的、结构化的标记语言的句法语言

Python 对 XML 的解析

常见的 XML 接口次要有两种 DOM 和 SAX,这两种接口解决 XML 的形式不同,当然应用的场景也不雷同。

  • SAX(simple API for XML)

Python 规范库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析 XML 的过程中触发一个个事件并调用用户定义的回调函数来解决 XML 文件。

  • DOM(Document Object Model)

将 XML 数据在内存中解析成一个树,通过对树的操作,来操作 XML。

本次分享中应用的 XML 文件为 movies.xml,内容如下:

<collection shelf="New Arrivals">
<movie title="Enemy Behind">
   <type>War, Thriller</type>
   <format>DVD</format>
   <year>2003</year>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
   <type>Anime, Science Fiction</type>
   <format>DVD</format>
   <year>1989</year>
   <rating>R</rating>
   <stars>8</stars>
   <description>A schientific fiction</description>
</movie>
   <movie title="Trigun">
   <type>Anime, Action</type>
   <format>DVD</format>
   <episodes>4</episodes>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
   <type>Comedy</type>
   <format>VHS</format>
   <rating>PG</rating>
   <stars>2</stars>
   <description>Viewable boredom</description>
</movie>
</collection>

就目前来说,咱们比拟罕用的解析形式是应用 DOM 模块进行解析。

Python 解析 XML 示例

from xml.dom.minidom import parse
import xml.dom.minidom


# 应用 minidom 解析器关上 XML 文档
DOMTree = xml.dom.minidom.parse('movies.xml')   # 返回 Document 对象
collection = DOMTree.documentElement    # 获取元素操作对象
# print(collection)
if collection.hasAttribute('shelf'):
    print('Root element : %s' % collection.getAttribute('shelf'))


# 在汇合中获取所有的电影
movies = collection.getElementsByTagName('movie')   # 返回所有的 movie 标签,并保留在列表中
# print(movies)
for movie in movies:
    print('*******movie******')
    if movie.hasAttribute('title'):
        print('Title: %s' % movie.getAttribute('title'))
    type = movie.getElementsByTagName('type')[0]
    print('Type: %s' % type.childNodes[0].data) # 获取标签元素的内容
    format = movie.getElementsByTagName('format')[0]
    print('format: %s' % format.childNodes[0].data)
    rating = movie.getElementsByTagName('rating')[0]
    print('rating: %s' % rating.childNodes[0].data)
    description = movie.getElementsByTagName('description')[0]
    print('description: %s' % description.childNodes[0].data)


爱奇艺弹幕

最近出了一篇新剧,叫做《赘婿》,想必大家都看到了吧。明天咱们的实战内容就是把观众发送的弹幕抓取下来,并将我在爬取过程中遇到的内容分享给大家。

剖析网页

一般来说,视屏的弹幕是不可能呈现在网页源码中的,那么初步判断是通过异步加载弹幕数据。

首先关上开发者工具 –> 点击 network–> 点击 XHR

image

找到相似上图所示的 URL,咱们只须要其中的:/54/00/7973227714515400。

爱奇艺的弹幕地址获取如下:

https://cmts.iqiyi.com/bullet/ 参数 1_300_参数 2.z

参数 1 是:/54/00/7973227714515400

参数 2 是:数字 1、2、3……

爱奇艺每 5 分钟就会加载一次弹幕,每一集下来大略是 46 分钟,因而弹幕的链接如下:

https://cmts.iqiyi.com/bullet/54/00/7973227714515400_300_1.z
https://cmts.iqiyi.com/bullet/54/00/7973227714515400_300_2.z
https://cmts.iqiyi.com/bullet/54/00/7973227714515400_300_3.z
.
.
.
https://cmts.iqiyi.com/bullet/54/00/7973227714515400_300_10.z

数据解码

当你把下面的 URL 复制到浏览器中,你会发现间接下载一个以.z 为后缀的压缩包,windows 不能间接关上,只能先通过 Python 对压缩包进行解码。

在这里我先对 zlib 这个库做简略的解释,zlib 用于压缩和解压缩数据流。

因而,咱们能够对下载下来的数据包进行解压缩。

首先,须要以二进制的形式读取数据包,再进行解压缩。

就拿我刚刚下载下来的压缩包为例子吧。

具体代码如下所示:

import zlib


with open('7973227714515400_300_1.z', 'rb') as f:
    data = f.read()

decode = zlib.decompress(bytearray(data), 15 + 32).decode('utf-8')
print(decode)

运行后果,如下所示:

image

不晓得你有没有发现这类数据很像是 XML,那咱们就无妨写多两行代码,将数据保留为 XML 文件。

具体代码,如下所示:

import zlib


with open('7973227714515400_300_1.z', 'rb') as f:
    data = f.read()

decode = zlib.decompress(bytearray(data), 15 + 32).decode('utf-8')
with open('zx-1.xml', 'w', encoding='utf-8') as f:
    f.write(decode)

失去的 XML 文件内容,如下所示:

image

看到运行运行后果之后是不是有点小惊喜呀,依据我下面所讲的内容就能够获取到咱们想要的数据了。

提取数据

具体代码,如下所示:

from xml.dom.minidom import parse
import xml.dom.minidom


DOMTree = xml.dom.minidom.parse('zx-1.xml')
collection = DOMTree.documentElement
entrys = collection.getElementsByTagName('entry')   
for entry in entrys:
    content = entry.getElementsByTagName('content')[0].childNodes[0].data
    print(content)

运行后果,如下所示:

image

当初对网页的剖析和数据的获取思路想必大家都明确了。

那当初咱们又须要回到刚刚的终点了,须要结构弹幕 URL,并向该 URL 发送申请,获取它的二进制数据,再进行解压缩并保留为 XML 文件,最初从该文件中提取弹幕数据。

结构 URL

具体代码,如下所示:

# 结构 URL
    def get_urls(self):
        urls = []
        for x in range(1, 11):
            url = f'https://cmts.iqiyi.com/bullet/54/00/7973227714515400_300_{x}.z'
            urls.append(url)
        return urls

保留 XML 文件

具体代码,如下所示:

# 保留 xml 文件
    def get_xml(self):
        urls = self.get_urls()
        count = 1
        for url in urls:
            content = requests.get(url, headers=self.headers).content
            decode = zlib.decompress(bytearray(content), 15 + 32).decode('utf-8')
            with open(f'../data/zx-{count}.xml', 'a', encoding='utf-8') as f:
                f.write(decode)
            count += 1

避坑:

1、首先咱们要获取的内容其实是一个压缩包,因而咱们的 headers 应该这样写:

self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36',
            'Accept-Encoding': 'gzip, deflate'
        }

避免出现如下谬误:

image

2、保留的 xml 文件不能以中文命名,还有一点就是最好增加一个 –,如下所示:

zx-0
zx-1
.
.
.
zx-9

避免出现如下谬误:

image

将 XML 文件都保留下来之后,临时正文掉爬虫代码,因为,接下来咱们须要对下面的文件进行数据提取了。

提取数据

 # 提取数据
    def parse_data(self):
        danmus = []
        
        for x in range(1, 11):
            DOMTree = xml.dom.minidom.parse(f'../data/zx-{x}.xml')
            collection = DOMTree.documentElement
            entrys = collection.getElementsByTagName('entry')
            for entry in entrys:
                danmu = entry.getElementsByTagName('content')[0].childNodes[0].data
                danmus.append(danmu)
        # print(danmus)
        df = pd.DataFrame({'弹幕': danmus})
        return df

在这里咱们刚好应用到了,刚刚学习的 XML 的解析形式。所以对于咱们来说,提取外面的弹幕对咱们来说基本上,没有什么问题。

保留数据

 # 保留数据
    def save_data(self):
        df = self.parse_data()
        df.to_csv('../data/danmu.csv', encoding='utf-8-sig', index=False)

评论内容词云

image

小伙伴们请留神,这个只是第一集,就有两千多条弹幕,由此能够看出,这部剧还是比拟火爆的。

最初

没有什么事件是能够欲速不达的,生存如此,学习亦是如此!

因而,哪里会有什么三天速成,七天速成的说法呢?

唯有保持,方能胜利!

退出移动版