scrapy爬取某视频网站的部分视频信息

此次爬取的信息有:
1、视频名称
2、在线观看人数
3、弹幕内容
4、弹幕发送时间
5、弹幕在视频中的位置
6、点赞
7、收藏
8、投币数
在这里插入图片描述
在这里插入图片描述
由于b站的很多信息是动态加载的。所以部分信息,需要自己抓包,进入对应的网址抽取信息。例如在线观看视频人数,投币数,收藏数等等。
我的思路
首先拿到这个小项目时,分析出 要获取的数据如上。观察,不同信息对应的url。首先,我们应先在B站首页,获取出 要爬取视频的 名字,url地址。但此时存在一个问题:
在这里插入图片描述
若直接发送请求获取响应,只能的到8个视频的url和名字,其实这一栏共有24个视频信息,但这个是轮播图,不能一次性得到。起先,我试图通过抓包,希望能够得到接口地址,得到所有信息。但事与愿违,经过使用开发者工具及分析页面源码,我发现这个网页 用的vue的响应式,就是监听左右翻,然后把对应页数里的数据改到html上的href的里面 不是xhr请求。翻页更新是通过js改的html的数据。与是乎,我想到了用selenium来进行 翻页操作。并用
webdriver.Chrome().page_source来获取当前网页源码,来获得翻页后的视频信息。
上代码:

#通过selenium 间隔0.1秒点击3次 右翻页 获取 视频的名称 地址
        video_names = []
        video_urls = []
        chrome = webdriver.Chrome()
        url = 'https://www.bilibili.com/'
        chrome.get(url)
        for i in range(3):
            response = chrome.page_source
            e = etree.HTML(response)
            video_names += e.xpath('//div[@class="info"]/p[@class="title"]/text()')
            video_urls += e.xpath('//div[@class="recommend-box"]//a/@href')
            chrome.find_element_by_xpath('//i[@class="bilifont bili-icon_caozuo_xiangyou"]').click()    #点击翻页
            time.sleep(0.1)

此时,得到了 两个列表,一个是视频名,视频url。各有24个元素,对应24个视频。
接下来我们要 进入具体某个视频 得到其他信息。
经过对网页的分析,其过程我不再赘述。发现了储存点赞 投币 收藏 信息的网址 格式为:
aid

url = 'https://api.bilibili.com/x/web-interface/archive/stat?aid=' 

在这里插入图片描述
数据形式以json形式展现
弹幕是存放在一个xml文件地址里的
cid

  xml_url='http://comment.bilibili.com/{}.xml'.format(cids[i])

在这里插入图片描述
举个栗子

<d p="122.59100,1,25,16777215,1580443864,0,6080b8b9,27945436399534080">还有个地图和求生之路里完全一样……那个桥洞</d>

这其中,122.59100指的是 弹幕在视频出现的时间戳,27945436399534080指的是弹幕发送时的时间戳。分别需要转化为x分x秒,x月x日x时x秒。具体代码:

# # #----------------------------------------------------------------弹幕内容 时间--------------------------------------------------------------------------
            # 合成弹幕xml文件地址
            xml_url='http://comment.bilibili.com/{}.xml'.format(cids[i])
            response = requests.get(url=xml_url)
            response.encoding = 'utf-8_sig'
            # print(response.text)
            Barrage_html = response.text
            soup = BS(Barrage_html, 'lxml')
            all_d = soup.select('d')
            for d in all_d:
                # 把d标签中P的各个属性分离开
                Barrage_list = d['p'].split(',')
                # d.get_text()是弹幕内容
                Barrage_list.append(d.get_text())
                #删去xml解析信息的列表里,不要的元素
                for i in range(3):
                    del Barrage_list[1]
                for j in range(3):
                    del Barrage_list[2]
                #将弹幕在视频出现的时间戳,转化并替换为 分 秒
                total_time = time.strftime("%M:%S", time.gmtime(float(Barrage_list[0])))
                del Barrage_list[0]
                Barrage_list.insert(0, total_time)
                #将时间戳转化为北京时间,并替换
                timeNum = int(Barrage_list[1])
                timeArray = time.localtime(timeNum)
                otherStyleTime = time.strftime("%m-%d %H:%M", timeArray)
                del Barrage_list[1]
                Barrage_list.insert(1, otherStyleTime)
                #d弹幕在视频的时间
                video_time = Barrage_list[0]
                #发送弹幕时间
                Barrage_time = Barrage_list[1]
                #弹幕内容
                Barrage_content = Barrage_list[2]

在线人数信息的获取,需要aid
wss://broadcast.chat.bilibili.com:7823/sub发送请求建立连接。

            def connect(plz):
                url = "wss://broadcast.chat.bilibili.com:7823/sub"
                normal = base64.b64decode('AAAAIQASAAEAAAACAAAACQAAW29iamVjdCBPYmplY3Rd')
                ws = websocket.create_connection(url, timeout=10)
                ws.send(bytes(plz))
                get = ws.recv()
                # print(get)
                ws.send(bytes(normal))
                get = ws.recv()
                # print(get)
                if get.find(b'online') != -1:
                    # online = get_online(get)
                    online = get_online(get)
                    return online
                else:
                    print("None")
            def get_online_from_av(av):
                send = make_send(av)
                online = connect(send)
                return online
            audience_online = get_online_from_av(avid)

最后将得到 信息返回, 写入数据库。
在这里插入图片描述
共计24351行。
其他小的问题,利用好在这里插入图片描述
都没问题,善于使用搜索引擎,省时又省力。
在这里插入图片描述
Github也是一个不错的好地方。

发布了19 篇原创文章 · 获赞 3 · 访问量 3461

猜你喜欢

转载自blog.csdn.net/qq_43544005/article/details/104209895