此文首发于我的个人博客:爬取B站我关注的人关注的人关注的人 — zhang0peter的个人博客
声明
- 代码、教程均为本人原创,且仅限于学习交流,请勿用于任何商业用途!
我突发奇想,想用Python爬取B站中我关注的人,我关注的人关注的人,我关注的人关注的人关注的人等。
准备阶段
写代码前先构思思路:既然我要爬取用户关注的用户,那我需要存储用户之间的关系,确定谁是主用户,谁是follower。
存储关系使用数据库最方便,也有利于后期的数据分析,我选择sqlite数据库,因为Python自带sqlite,sqlite在Python中使用起来也非常方便。
数据库中需要2个表,一个表存储用户的相互关注信息,另一个表存储用户的基本信息,在B站的用户体系中,一个用户的mid号是唯一的。
然后我还需要一个列表来存储所以已经爬取的用户,防止重复爬取,毕竟用户之间相互关注的现象也是存在的,列表中存用户的mid号就可以了。
最后我需要找到B站用户的关注列表的json接口,很快就找到了,地址是https://api.bilibili.com/x/relation/followings?vmid=2&pn=1&ps=20&order=desc&jsonp=jsonp&callback=__jp7
其中vimd=后的参数就是用户的mid号,pn=1指用户的关注的第一面用户,一面显示20个用户。因为B站的隐私设置,一个人只能爬取其他人的前5面关注,共100人。
开始写代码
先写建数据库的代码,数据库中放一个用户表,一个关系表:
def create():
# 创建数据库
global conn
conn = sqlite3.connect('data.db')
conn.execute("""
create table if not exists user(
id INTEGER PRIMARY KEY ,
mid int DEFAULT NULL,
name varchar DEFAULT NULL,
sign varchar DEFAULT NULL)""")
conn.execute("""
create table if not exists relation(
id INTEGER PRIMARY KEY ,
master int,
following int
)""")
conn.commit()
然后写爬取的核心代码:
def func(startid=0):
global user
if startid == 0:
return
i = 0
result = []
ref_url = "https://space.bilibili.com/"+str(startid)+"/#/fans/follow"
head = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language':