!!版权审核原因,主函数中网站链接需自己写。
1.模拟浏览器和用户发送请求,获取网页结构。
模拟发送请求可以使用urilib或requests,这里使用的是urllib
打包request请求:
urllib.request.request(url,请求头信息)
这里请求头信息包含的内容越详细越不易识破,信息详情可以借助chrom的F12中的network看
其中的useragent尤其重要,多写几个轮着调比较保险。
提交请求并读取信息:
urllib.read(),返回一个长字符串,包含url所对应html的所有内容
# 1.爬取网页
def getData(baseURL):
dataList = []
html = askURL(baseURL)
# 2.逐一解析数据
soup = BeautifulSoup(html, 'html.parser')
# 获取热门视频总体所在item
num = 0
# 查找符合标准的字符串,形成列表
'''
bs中的find_all可以通过limit属性来进行获取数据数量
'''
for item in soup.find_all("li", class_="rank-item"):
data = [] # 保存一个视频的所有信息
# 这里循环出来item是一个列表,需要转换成字符串,才能用正则匹配
item = str(item)
# 视频链接获取
'''
~通过bs将html解析后,通过正则库re的findall方法进行更精确匹配获取信息
~findall----通过指定的正则规则findLink对item字符串进行从左至右扫描,字符串列表或元组方式返回所有匹配成功的
~[0]---第一个元素就是要查找的链接所以是
'''
# 综合排名
addToData(data,item,findRank,0)
# print(data)
# 视频链接和up主主页链接
addToData(data,item,findLinks,0)
# 视频名
addToData(data,item,findName,0)
# print("name:" + data)
# up主名?
addToData(data,item,findUP,0)
# print("up:" + data)
# up主主页链接?
addToData(data, item, findLinks, 1)
# 播放量
addToData(data, item, findPlay, 0)
# print("play:" + data)
# 评论量
data = addToData(data, item, findLike, 0)
# 总集合中添加单个视频信息
dataList.append(data)
# print(dataList)
return dataList
# 得到指定一个url的网页内容
2. 逐一解析网络结构获取数据
这里用beautifulSoup和正则进行对传回来字符串的解析。
通过bs的find_all将html解析找到大体位置后,通过正则库re的findall方法进行更精确匹配获取信息
注意两个方法写法,bs的下划线不能漏
分析html
def askURL(url):
# 发送请求时模拟浏览器头部信息
userAgents = [
"Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14",
"Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02",
"Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00",
"Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
]
# 头部信息越多,伪装越好
headers = {
# user-agent其实是浏览器的版本信息
"user-agent": random.choice(userAgents),
"refer":"https://www.bilibili.com/v/popular/rank/all",
# cookies是用户的信息(非常重要,没有会被反扒)
"cookie":"buvid3=B96D89C6-A64A-4550-87A8-7A4AF77A606934771infoc; LIVE_BUVID=AUTO5516250967869049; i-wanna-go-back=-1; CURRENT_BLACKGAP=0; nostalgia_conf=-1; hit-dyn-v2=1; blackside_state=0; _uuid=3FC227AA-ECC3-D16B-3D94-771052FD108E2294486infoc; buvid_fp_plain=undefined; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1658305863; b_nut=100; rpdid=0z9ZwfQlHX|xIEC0rbK|32U|3w1OYn3W; buvid4=89EAC22C-12C9-CA0E-FDB7-253E5771540B63287-022020517-snDbkYGXgCXCbu%2F3PP%2Blpg%3D%3D; b_ut=5; header_theme_version=CLOSE; fingerprint=bab537a19eecb00e1e84472a58633a28; CURRENT_FNVAL=4048; CURRENT_PID=21055df0-cd24-11ed-8f3a-e180d10b7496; hit-new-style-dyn=1; FEED_LIVE_VERSION=V8; buvid_fp=bab537a19eecb00e1e84472a58633a28; sid=6zrwc359; bp_video_offset_19207104=785000681956180000; b_lsid=2574C312_18788927E7E; innersign=0; home_feed_column=4; PVID=5; CURRENT_QUALITY=64"
}
# 用户代理,表示告诉b站服务器,我们是什么类型的机器、浏览器
request = urllib.request.Request(url,headers=headers)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
# print(html)
except urllib.error.URLErroe as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
正则规则
# 综合排名
findRank = re.compile(r'<li class="rank-item" data-id=".*" data-rank="(\d*)">')
# 视频链接和up主主页链接
findLinks = re.compile(r'<a href="(.*?)" target="_blank">')
# 视频名
findName = re.compile(r'<a class="title" href=".*?" target="_blank">(.*)</a>')
# up主名称
findUP = re.compile(r'<span class="data-box up-name"><img alt="up" src=".*?"/>(.*?)</span>',re.S)
# 播放量
findPlay = re.compile(r'<span class="data-box"><img alt="play" src=".*?"/>(.*?)</span>',re.S)
# 评论量
findLike = re.compile(r'<span class="data-box"><img alt="like" src=".*?"/>(.*?)</span>', re.S)
3. 保存数据
可以将数据保存为一个表格文件,也可以使用sqlite数据库进行保存。
这里采用将其保存成一个表格文件。
# 3.保存数据
def saveData(datalist,savepath):
workbook = xlwt.Workbook(encoding="utf-8",style_compression=0) #创建workbook对象
worksheet = workbook.add_sheet('工作表名称',cell_overwrite_ok=True)#创建工作表,cell属性表示后来者覆盖之前内容
col = ("综合排名","视频链接","视频名","up主","up主页","播放量","评论量")
for i in range(0,7):
# 写第1行表头
worksheet.write(0,i,col[i])
for i in range(0,100):
print("第%d条:"%i)
data = datalist[i]
for j in range(0,7):
# 写第2行第1列,开始写内容
worksheet.write(i+1,j,data[j])
workbook.save(savepath)
小优化
在解析网页结构时,因解析部分代码重复挺多了,就封装了函数addToData
# 封装添加数据到data数组的函数
def addToData(data,item,method,index):
i = re.findall(method,item)[index]
data.append(i)
return data
用到的库
from bs4 import BeautifulSoup
#正则表达式,进行文字匹配
import re
# 指定url获取网页数据
import urllib.request,urllib.error
# 进行excel操作
import xlwt
# 进行sql数据库操作
import sqlite3
# 引入random,每次请求随机拿到一个useragent
import random
主函数
def main():
baseURL = "网站链接"
dataList = getData(baseURL)
# 将项目保存在当前目录下并命名
savepath = "表格文件名.xls"
saveData(dataList,savepath)
if __name__ == "__main__" :
main()```