爬取B站UP主的部分信息
爬取B站UP主信息
爬取网页,一般的做法是先直接向目标页面发起请求,然后返回,查看返回页面是否与目标页面相同,如果不同,则证明这个页面是动态加载页面,需要另寻它法。
所以,我向B站发起了请求:https://space.bilibili.com/105511477
然而,返回的页面完全没有我需要的信息,这说明B站使用了异步加载技术,于是我逐个分析请求url,在https://api.bilibili.com/x/space/acc/info?mid=105511477&;jsonp=jsonp这个请求的响应中发现了id号, 姓名,性别, 生日,等级等数据,但是找不到关注数,粉丝数。继续分析,在https://api.bilibili.com/x/relation/stat?vmid=105511477&;jsonp=jsonp&callback=__jp3响应中找到关注数,粉丝数等数据。但是我嫌麻烦,直接在网上找到了将这2个url合并的url:https://api.bilibili.com/x/web-interface/card?mid=105511477&;jsonp=jsonp&article=true
直接发起请求,得到json数据,然后解析json数据就行了。由于B站数据太多,我有编写了进度保存与加载,防止重复爬取。但是爬取速度是比较慢的,改进的建议:多线程和分布式爬取。
由于数据不全,我没有做后续分析。
代码:
# -*- coding: utf-8 -*-
import requests
import json
import time
# 爬取B站up主的信息,包括:id号,姓名,性别,粉丝数,关注数,等级
# 由于B站数据太多,这里不能全部爬取,建议改进:多线程, 分布式
# 包含爬取数据进度保存,可以随时爬取
def get_html(url): # 向网站发送请求,代码格式固定
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0'}
cookie = {'Cookie': "fts=1504349387; buvid3=1C1CB246-90F7-4641-994C-875348FCC9DA31841infoc; LIVE_BUVID=923027b89ab5074df00ddeb74bd1bc4c; LIVE_PLAYER_TYPE=1; LIVE_BUVID__ckMd5=213686949aed5aa3; sid=jszx4g3e; stardustvideo=1; CURRENT_FNVAL=16; rpdid=kmwpioxopmdospssmioww; CURRENT_QUALITY=32; bp_t_offset_105511477=225519300968954321; finger=888236dc; im_notify_type_105511477=0; UM_distinctid=169200905bf184-0820062ee695d58-4c312f7f-100200-169200905c039c; DedeUserID=105511477; DedeUserID__ckMd5=e312e81cda67c220; SESSDATA=f560bc58%2C1553994772%2C44a40231; bili_jct=90910cb604d93fccf748794b4007ba13; bsource=seo_baidu; _dfcaptcha=d2c62b90ce5116dd8e1dd97aec364e73"}
print(cookie)
r = requests.get(url=url, headers=headers, cookies=cookie)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.content.decode()
def get_information(url): # 得到页面信息
html = get_html(url) # 得到json
value = json.loads(html) # 加载json
flag = True # flag,判断是否有这个页面
mid = value.get("data").get("card").get("mid") # json得到mid号
name = value.get("data").get("card").get("name")
sex = value.get("data").get("card").get("sex")
fans = value.get("data").get("card").get("fans")
attention = value.get("data").get("card").get("attention")
level = value.get("data").get("card").get("level_info").get("current_level")
if mid == "": # mid号为空,则没有这个用户
flag = False
return flag, mid, name, sex, fans, attention, level # 返回信息
with open("test.txt", "a+", encoding="utf-8") as f, open("save.txt", "r+") as f1:
start = int(f1.readline().strip().split("_")[-1]) # 加载保存的进度
if start == 0:
f.write("mid\tname\tsex\tfans\tattention\tlevel\n") # 如果没有进度,则写出题头
for i in range(start, 100000000):
mid = i + 1
# 生成url
url = "https://api.bilibili.com/x/web-interface/card?mid=%d&jsonp=jsonp&article=true" % mid
flag, mid, name, sex, fans, attention, level = get_information(url) # 得到数据
if flag:
# 写出数据
f.write(str(mid) + "\t" + name + "\t" + sex + "\t" + str(fans) + "\t" +
str(attention) + "\t" + str(level) + "\n")
if i % 100 == 0: # 每100轮保存进度
f1.write("_" + mid)
f.flush()
f1.flush()
print(i)
time.sleep(0.1) # 每次爬取后休息0.1秒
Twitter
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email