目录
2.2 任务2:根据URL获取其中一页json数据并通过vscode规整代码
2.3 任务3:通过python爬取这个5个json文本(每个页面20条记录,共100条)
爬虫文章不能出现被获取(spider)网站页面,审核的哥哥姐姐辛苦了!
1.爬虫介绍
一句话,假装浏览器向服务器发送请求获取大量数据,常见有get请求(直接回获取数据),post请求(发送表单来获取类似于注册登录等)
2.1任务1:找到返回后台数据的URL
下图为某站热门页面
某站主页->热门->综合热门 ,进入一条条的热门视频推荐页面
也就是在这个网址
或者
进入热门页面之后:
操作:F12 -> network -> XHR -> F5(一定要F5刷新一下) 【3】
首先,根据经验,热门视频列表是一直可以往下拉更新的,因此在html里面找到所有数据是不可能的,肯定是通过一个URL请求后台数据,每下拉到底自动从后台请求下一页数据再传到html最后渲染出来。
要找到请求后台数据这个URL可以往下多刷几页,就会看见规律,因此我们知道该页面是通过这个XHR类型的popular?ps={一次20个数据项}&pn{第几页}里面的url请求数据的。
参照下图Request URL
(注意我们编程时通过改变pn=数字来获取不同页数据)
同时我们也能通过请求方法method为GET验证本页面通过get请求服务器数据并返回
2.2 任务2:根据URL获取其中一页json数据并通过vscode规整代码
小小实践一下访问这个第一页pn=1的URL看得到什么
如果无法打开那就自己输入这个pn=1的url到搜索引擎去打开吧,可能这个连接是从csdn跳转出去的某站不给你访问。
这不正是我们要找的吗?看不清楚可以将这个网页所有内容复制粘贴到vscode文本,shift+alt+f 格式规整后,可以看出就是一个这个网页上是json文件(JSON 就是 Javascript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符串【1】)的形式(后续python爬取出来的text是str类型,还得通过json库将str转换成字典数据类型),后续可以通过python的字典与列表处理
2.3 任务3:通过python爬取这个5个json文本(每个页面20条记录,共100条)
(1) 导入所需库
import requests # 相当于浏览器发起请求 import json # 内置的库,不用下载 ,处理json数据的转换等操作 import csv #内置,处理csv文件按存取等操作
(2) 设置请求头——假装浏览器反反扒的第一步
找到这个请求头,里面的User-Agent是伪装最重要的,一般有了这个可以解决大部分反扒。
我们声明一个headers字典,将User-Agent及其值复制到里面。有的项目还用到Cookie
# 用自己的就可以了 headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.3" }
(3) 爬下第一页的20条热门数据json文本
i = 1 # i为for循环做准备 URL = f"https://api.bilibili.com/x/web-interface/popular?ps=20&pn={i}" response = requests.get(URL,headers = headers) # print(response.text) # response.text为str型的页面数据 dict_heat = json.loads(response.text) # 将str转换成json格式数据 print(dict_heat)
有内容打印就行,内容会随着热门的改变而不一样 。
规整代码后清晰明了
(4) 分析所需数据位置
关键!关键!关键!这里字典与列表、字典与字典疯狂套套套
(抱歉,下图是要找title不是tname,即最外层字典名["data"]["list"][0]["title"],懒得改图了)
再举一个例子,要得到第2个(则列表下标为1)热门tname,最外层字典名为dict_heat,则dict_heat["data"]["list"][1]["tname]
(5) 循环获取5页共100条热门数据 ——f字符串语句
# ps = 20 ,100 = 1*5 ''' 我们需要类型tname,标题名title、描述desc,up主name、观看量view、弹幕数danmaku、点赞like,收藏favorite,硬币数coin 我们用字典dict_coint的键值对形式存储一条热门的上面这几个数据,因此,将这几个数据提取出来存进字典 我们用列表list_top100存储每一条热门字典 ''' list_top100 = [] # i从1-5,分别对应五个URL,每次循环就相当于浏览器每下拉到底就更新一页的20条热门 for i in range(1,6): URL = f"https://api.bilibili.com/x/web-interface/popular?ps=20&pn={i}" response = requests.get(URL,headers = headers) #print(type(response.text)) dict_heat = json.loads(response.text) # print(dict_heat) # 处理字典获取类型tname,标题名title、描述desc,up主name、观看量view、弹幕数danmaku、点赞like,收藏favorite,硬币数coin # li从0-19,每一个dict_heat字典list有20个热门,每次循环就是每条热门 for li in range(20): dict_coint = {"tname":"","title":"","desc":"","owner":"","view":"","danmaku":"","like":"","favorite":"","coin":""} dict_coint["tname"] = dict_heat["data"]["list"][li]["tname"] dict_coint["title"] = dict_heat["data"]["list"][li]["title"] dict_coint["desc"] = dict_heat["data"]["list"][li]["desc"] dict_coint["owner"] = dict_heat["data"]["list"][li]["owner"]["name"] dict_coint["view"] = dict_heat["data"]["list"][li]["stat"]["view"] dict_coint["danmaku"] = dict_heat["data"]["list"][li]["stat"]["danmaku"] dict_coint["like"] = dict_heat["data"]["list"][li]["stat"]["like"] dict_coint["favorite"] = dict_heat["data"]["list"][li]["stat"]["favorite"] dict_coint["coin"] = dict_heat["data"]["list"][li]["stat"]["coin"] list_top100.append(dict_coint) print(list_top100)
2.4 任务4:存到本地csv表【2】
with open(r"bilibili_top100.csv","w",encoding='utf-8-sig',newline='' ) as f: csv_writer = csv.writer((f)) # 先写一行表头,我为了美观多加了一行序号 csv_writer.writerow(["序号","类型","标题","描述","up主","浏览量","弹幕数","点赞数","收藏数","投币数"]) # 还是注意多了序号 # dodo是每次列表list_top100返回的一个字典 for i, doto in enumerate(list_top100): csv_writer.writerow([i+1,doto["tname"],doto["title"],doto["desc"],doto["owner"],doto["view"],doto["danmaku"],doto["like"],doto["favorite"],doto["coin"]])
文件路径因为我是就在同级文件夹里
3.完整代码
import requests # 相当于浏览器发起请求 from bs4 import BeautifulSoup #本次没用到 import json # 内置的库,不用下载 ,处理json数据的转换等操作 import csv #内置,处理csv文件按存取等操作 # 请求该网址获取热门数据json url = "https://api.bilibili.com/x/web-interface/popular?ps=20&pn=" headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.3", #"Cookie":"buvid3=A2DE5D15-AB31-3498-3CBC-FAA2758718BC90917infoc; b_nut=1668129090; i-wanna-go-back=-1; _uuid=EE5768D2-C2C4-10AFE-102101-2108FF6310FB6791645infoc; nostalgia_conf=-1; LIVE_BUVID=AUTO2516681291427415; fingerprint=275df7b8b6dd68ec39d06535391183fd; buvid_fp_plain=undefined; PVID=1; b_ut=5; rpdid=0zbfAGvvia|1n8AfspM|1Ej|3w1OYp9G; CURRENT_BLACKGAP=0; is-2022-channel=1; CURRENT_FNVAL=4048; CURRENT_QUALITY=80; buvid_fp=275df7b8b6dd68ec39d06535391183fd; header_theme_version=CLOSE; CURRENT_PID=92db9e00-d55b-11ed-918b-ef0265900a07; FEED_LIVE_VERSION=V8; buvid4=DD914872-814A-E541-6411-AECE343B81A592381-022111109-QvnVcBMEUB9cj5ReWWq3ZPeCDe2iT%2F3aV%2FgOVu0WxxdlybTyg0qT7g%3D%3D; innersign=0; b_lsid=B53AC6D2_1881CE410C6; bsource=search_bing; home_feed_column=4; browser_resolution=1396-685; bp_video_offset_397001083=795738040063492200; SESSDATA=fc5e1f63%2C1699666280%2C63116%2A51; bili_jct=8b97f5de15f0e146666e1043c9311286; DedeUserID=397001083; DedeUserID__ckMd5=6986d46441593e09; sid=ftstla3y" #"Cookie":"buvid3=A2DE5D15-AB31-3498-3CBC-FAA2758718BC90917infoc; b_nut=1668129090; i-wanna-go-back=-1; _uuid=EE5768D2-C2C4-10AFE-102101-2108FF6310FB6791645infoc; nostalgia_conf=-1; LIVE_BUVID=AUTO2516681291427415; fingerprint=275df7b8b6dd68ec39d06535391183fd; buvid_fp_plain=undefined; PVID=1; b_ut=5; rpdid=0zbfAGvvia|1n8AfspM|1Ej|3w1OYp9G; CURRENT_BLACKGAP=0; is-2022-channel=1; CURRENT_FNVAL=4048; CURRENT_QUALITY=80; buvid_fp=275df7b8b6dd68ec39d06535391183fd; header_theme_version=CLOSE; CURRENT_PID=92db9e00-d55b-11ed-918b-ef0265900a07; FEED_LIVE_VERSION=V8; buvid4=DD914872-814A-E541-6411-AECE343B81A592381-022111109-QvnVcBMEUB9cj5ReWWq3ZPeCDe2iT%2F3aV%2FgOVu0WxxdlybTyg0qT7g%3D%3D; innersign=0; b_lsid=B53AC6D2_1881CE410C6; bsource=search_bing; home_feed_column=4; browser_resolution=1396-685; bp_video_offset_397001083=795738040063492200; sid=fnz9238s" } # ps = 20 ,100 = 1*5 list_top100 = [] for i in range(1,6): URL = f"https://api.bilibili.com/x/web-interface/popular?ps=20&pn={i}" response = requests.get(URL,headers = headers) #print(type(response.text)) #test code: 200 dict_heat = json.loads(response.text) # print(dict_heat) Sucess # 处理字典获取类型tname,标题名title、描述desc,up主name、观看量view、弹幕数danmaku、点赞like,收藏favorite,硬币数coin for li in range(20): dict_coint = {"tname":"","title":"","desc":"","owner":"","view":"","danmaku":"","like":"","favorite":"","coin":""} dict_coint["tname"] = dict_heat["data"]["list"][li]["tname"] dict_coint["title"] = dict_heat["data"]["list"][li]["title"] dict_coint["desc"] = dict_heat["data"]["list"][li]["desc"] dict_coint["owner"] = dict_heat["data"]["list"][li]["owner"]["name"] dict_coint["view"] = dict_heat["data"]["list"][li]["stat"]["view"] dict_coint["danmaku"] = dict_heat["data"]["list"][li]["stat"]["danmaku"] dict_coint["like"] = dict_heat["data"]["list"][li]["stat"]["like"] dict_coint["favorite"] = dict_heat["data"]["list"][li]["stat"]["favorite"] dict_coint["coin"] = dict_heat["data"]["list"][li]["stat"]["coin"] list_top100.append(dict_coint) print(list_top100) with open(r"bilibili_top100.csv","w",encoding='utf-8-sig',newline='' ) as f: csv_writer = csv.writer((f)) csv_writer.writerow(["序号","类型","标题","描述","up主","浏览量","弹幕数","点赞数","收藏数","投币数"]) for i, doto in enumerate(list_top100): csv_writer.writerow([i+1,doto["tname"],doto["title"],doto["desc"],doto["owner"],doto["view"],doto["danmaku"],doto["like"],doto["favorite"],doto["coin"]])
4.后话
通过获取json,我们还能看到封面url、视频连接等其他数据,
5.参考致谢
【1】csdn——JSON 本质就是字符串???( 刚学JSON时)