人生苦短,我用python
碰到喜欢的人该怎么办?
🧑:楼主楼主,最近碰到一个喜欢的人,我该怎么办?
LZ:什么人啊?
🧑:一个up主。
LZ:当然是爬他鸭!(✿‿)
这次我们就来爬一爬up主的视频数据
第一步:导入对应的模块
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
import re
import pymongo
import time
import datetime as dt
import random
import pandas as pd
import warnings
warnings.filterwarnings('ignore')#忽略警告
print('导入成功!')
这里我们用的模块主要有:
requests —— 用于访问网页
BeautifulSoup —— 用于解析网页
selenium —— 测试网页的工具包,模拟人操作网页
re —— 通过正则表达式,提取内容
pymongo —— Python操作Mongo数据库的工具包
本文涉及的模块较多,后面写其他文章将补充其用法
第二步:获取页面的url
我们进入UP主的首页看看
我们要爬取的目标是视频的相关信息,这里我们选择投稿这个标签,这是我们会发现网址发生了变化,当切换翻页时,网页也发生了变化,而这个变化是有规律可循的。
第一页的网址://space.bilibili.com/82366241/video?tid=0&page=1&keyword=&order=pubdate”
第二页的网址://space.bilibili.com/82366241/video?tid=0&page=2&keyword=&order=pubdate”
......(自行修改网址)
这里可以写一个循环函数就可获取所有视频列表的网址。
def get_urls(n):
#【分页网页url采集】函数
#n:页数参数
lst = []
for i in range(n):
lst.append('https://space.bilibili.com/82366241/video?tid=0&page=%i&keyword=&order=pubdate' %(i+1))
return lst
urllst = get_urls(14)#这里up的视频投稿一共有14页
获取了所有的视频网页后我们就需要爬取每个投稿页面下视频对应的链接,再进一步去或者视频页面的一些信息。
这里requests + BeautifulSoup的方式没办法直接解析up主的页面,我们就用selenium去获取相关信息。
通过Chrome浏览器直接检查网页的元素(这里建议使用Chrome浏览器)
根据网页标签我们就可以直接定位我们要爬取的内容了。
lilst = []
brower = webdriver.Chrome()
for u in urllst:
brower.get(u)
time.sleep(1)#休息1秒等待网页缓冲
ul = brower.find_element_by_class_name('list-list')
lis = ul.find_elements_by_tag_name('a')
for li in lis:
lilst.append(li.get_attribute('href'))
lilst = list(set(lilst))#这里由于存在图片和文字标题两个链接,这里做一个去重的操作
这里我尝试过不运用睡眠1秒这个操作,但是有时因为网速不稳定可能会导致数据查找失败,所以这里做了一个休息1秒的设定。同时,这里去重还用了一个“小技巧”,因为在python里集合是不能用重复项的,所以这里将列表变为集合再变为列表来去除重复项。这样我们就获取了所有视频的网址信息了。接下来就可以爬数据了。o( ̄ ̄)ブ
第三步:解析网页获取数据
解析网页之前要做两项铺垫,要获取网页的User-Agent和Cookie,这里要登陆B站,然后打开刚刚采集的网址(这里只用一个网页讲解,后面用循环就可以操作就可以获取全部网页的)
当然这里检查的时候要重新刷新一下,否则看不到这些信息。
然后将cookie存成字典形式。
dic_c1 = {}
cookies1 = '''buvid3=03FCB17B-8E7D-46F0-8156-838D7D5A2B9940786infoc; LIVE_BUVID=AUTO4615631674934688; sid=cjdl8sqy; DedeUserID=15107370; DedeUserID__ckMd5=051111d6cb7f72d5; SESSDATA=19a2f18d%2C1565759681%2C31bec571; bili_jct=fa019ab71d9655efbcc14a1cb272c4ab; _uuid=5137E4C3-A530-CCC3-493F-5D34E4758B0B92699infoc; UM_distinctid=16bf40e1ab957c-0f454459c38526-e343166-1fa400-16bf40e1aba774; CNZZDATA2724999=cnzz_eid%3D1822973876-1563165600-https%253A%252F%252Fwww.bilibili.com%252F%26ntime%3D1563165600; bp_t_offset_15107370=276288717802840143; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1563167705,1563167765; Hm_lpvt_8a6e55dbd2870f0f5bc9194cddf32a02=1563167765; innermark=1; CURRENT_FNVAL=16; rpdid=|(umRu)YJJ~~0J'ulYJuY)|R|; stardustvideo=1'''
for i in cookies1.split('; '):
dic_c1[i.split('=')[0]] = i.split('=')[1]
尝试打开网址
开始解析网页,这个页面里我们主要获取3个信息(标题,UP主,上线的时间)还有个aid这是视频在B站唯一值,这个数据可以直接网址里利用正则获取(.../av53742321这串数字就是)。
ui = 'https://www.bilibili.com/video/av53742321'
r1 = requests.get(url = ui,headers = dic_h,cookies = dic_c1)
soup1 = BeautifulSoup(r1.text,'lxml')
title = soup1.h1['title']
time = re.search(r'(\d*-\d*-\d* \d*:\d*:\d*)',soup1.find('div',class_="video-data").text).group(1)
aid = re.search(r'av(\d*).*',ui).group(1)
up = soup1.find('div',class_="name").a.text
通过aid我们可以打开对应的(网址查看代码)获取视频的播放量,投币,点赞,收藏等数据。这个网址我们要重新获取cookie信息,这里我就不重复了。
r2 = requests.get(url = 'https://api.bilibili.com/x/web-interface/archive/stat?aid=53742321',
headers = d_h,cookies = d_c2)#修改“aid=”就可以获取对应视频信息了
soup2 = BeautifulSoup(r2.text,'lxml')
name = soup1.find('div',class_="info open").text
info = re.search(r'"view.*(\d*),"now_rank"',soup2.text).group().split(',')[:-2]
date = str(dt.date.today())
dic = {}
dic['标题'] = title
dic['介绍'] = name
dic['aid'] = aid
dic['上线时间'] = time
dic['up主'] = up
dic['采集时间'] = date
for i in info:
dic[i.split(':')[0].replace('"','')] = i.split(':')[1]
第四步:保存数据
如果电脑安装好了Mongo存数据就很简单了
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
db = myclient['看电影了没']
datatable = db['视频信息']
第五步:循环采集
把刚刚采集过程转换成函数,然后循环执行函数,就可以完成爬取up主的所有数据了。
def get_data(ui,d_h,d_c1,d_c2,table):
#【视频网页url采集】函数
#u:起始网址
#d_h:user-agent信息
#d_c1,d_c2:cookies信息(两个网址)
#table:要存入mongo的collection名称
r1 = requests.get(url = ui,headers = d_h,cookies = d_c1)
soup1 = BeautifulSoup(r1.text,'lxml')
title = soup1.h1['title']
time = re.search(r'(\d*-\d*-\d* \d*:\d*:\d*)',soup1.find('div',class_="video-data").text).group(1)
#long =
aid = re.search(r'av(\d*).*',ui).group(1)
up = soup1.find('div',class_="name").a.text
r2 = requests.get(url = 'https://api.bilibili.com/x/web-interface/archive/stat?aid=%s' %aid,
headers = d_h,cookies = d_c2)
soup2 = BeautifulSoup(r2.text,'lxml')
name = soup1.find('div',class_="info open").text
info = re.search(r'"view.*(\d*),"now_rank"',soup2.text).group().split(',')[:-2]
date = str(dt.date.today())
dic = {}
dic['标题'] = title
dic['介绍'] = name
dic['aid'] = aid
dic['上线时间'] = time
dic['up主'] = up
dic['采集时间'] = date
for i in info:
dic[i.split(':')[0].replace('"','')] = i.split(':')[1]
table.insert_one(dic)
return len(dic)
进行循环采集
errorlst = []
datalst = []
for ui in lilst:
try:
datalst.append(get_data(ui,dic_h,dic_c1,dic_c2,datatable))
print('数据采集成功,总共采集%i条数据' % len(datalst))
except:
errorlst.append(ui)
print('数据采集失败,数据网址为:',ui)
#time.sleep(random.randint(1,3))
最后我们用Robo 3T查看一下采集的数据🤩
楼主去拥抱up主了,下次见🤞
ps:点击查看全部代码