用Python爬取B站我关注的人关注的人关注的人
发布日期:2022-03-18 18:19:14
浏览次数:8
分类:技术文章
本文共 5216 字,大约阅读时间需要 17 分钟。
此文首发于我的个人博客:
声明
- 代码、教程均为本人原创,且仅限于学习交流,请勿用于任何商业用途!
我突发奇想,想用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': 'zh-CN,zh;q=0.9', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'DNT': '1', 'Host': 'api.bilibili.com', 'Pragma': 'no-cache', 'Referer': ref_url, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \ AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36' } while 1: i += 1 if i >= 6: break url = "https://api.bilibili.com/x/relation/followings?vmid=" + \ str(startid)+"&pn="+str(i) + \ "&ps=20&order=desc&jsonp=jsonp&callback=__jp5" try: r = requests.get(url, headers=head, timeout=10).text r2 = eval(r[6:-1].replace('null', 'None')) list1 = r2['data']['list'] if list1 == []: break else: for user1 in list1: result.append( [user1["mid"], user1["uname"], user1["sign"]]) except Exception as e: print(e) if result != []: save(result, startid)
在这段代码里,我使用了requests库来获取网页,其中有10行代码用于修改requests的header,防止爬虫被封。
接着写一个保存数据到数据库的函数:def save(result=[], master=0): # 将数据保存至本地 global conn, user if result == [] or master == 0: print("save error!") return command1 = "insert into user \ (mid,name,sign) values (?,?,?);" command2 = "insert into relation\ (master,following)values(?,?)" for row in result: try: temp = (master, row[0]) if row[0] not in user: user.append(row[0]) conn.execute(command1, row) conn.execute(command2, temp) else: conn.execute(command2, temp) except Exception as e: print(e) print("insert error!") conn.rollback() conn.commit() result = []
最后写main函数:
if __name__ == "__main__": create() cycle = 0 recordids = 0 time0 = time.time() while 1: cycle += 1 if recordids == 0: users = [startid] else: users = user[recordids:len(user)] for i in users: recordids += 1 func(i) time1 = time.time() print("\r已爬取{0}个用户,正在第{1}层 ,总花费时间:{2:.2f}s".format( recordids, cycle, time1-time0), end="")
main函数在运行时会提示当前花费的时间和已经爬取的用户。
我用user这个全局变量来存储所有已经爬取过的用户的mid号。 完整的代码在实际操作
我调试完程序后,已我自己作为开始的起点,花费了接近一天的时间,爬取了10万用户。
然后我想单单爬取用户的关注,然后存在数据库中是对数据是一种浪费,我打算利用我拥有的数据。进阶操作
我打算利用已经爬取到本地的数据进行词云的生成,来看一下这10万用户中共同的关注的哪些UP主出现的次数最多。
代码的思路主要是从数据库中获取用户的名字,重复的次数越多说明越多的用户关注,然后我使用fate的一张图片作为 词云的mask图片,最后生成词云图片。 代码如下:import matplotlib.pyplot as pltfrom wordcloud import WordCloud, ImageColorGeneratorfrom scipy.misc import imreadimport sqlite3conn = sqlite3.connect('data.db')user = { }for i in conn.execute("select mid,name from user order by id").fetchall(): user[i[0]] = i[1]wordlist = []for i in conn.execute("select following from relation order by id").fetchall(): if i[0] in user: wordlist.append(user[i[0]])wl_space_split = " ".join(wordlist)mask_png = imread("fate.jpeg")my_wordcloud = WordCloud( font_path=r"C:\Windows\Fonts\simhei.ttf",# 词云自带的字体不支持中文,在windows环境下使用黑体中文 background_color="white", # 背景颜色 max_words=500, # 词云显示的最大词数 max_font_size=100, # 字体最大值 random_state=42, mask=mask_png, width=1000, height=860, margin=2,).generate(wl_space_split)image_colors = ImageColorGenerator(mask_png)plt.figure()plt.imshow(my_wordcloud.recolor(color_func=image_colors))plt.axis("off")plt.figure()plt.imshow(mask_png, cmap=plt.cm.gray)plt.axis("off")plt.show()my_wordcloud.to_file("wordcloud.png")
词云生成的完整代码在
最后生成的图片为 可以看出蕾丝,暴走漫画,木鱼水心,阅后即瞎,papi酱等B站大UP主都是热门关注。GitHub项目地址:https://github.com/zhang0peter/bilibili-following-spider
转载地址:https://zhang0peter.blog.csdn.net/article/details/83419262 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关注你微信了!
[***.104.42.241]2024年04月07日 20时32分55秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
带团队很简单,管理就是十六字!(管理者必看)
2019-04-26
写作技巧~100段作文排比句(61-80段),考试一定用得上,赶紧收藏!
2019-04-26
判别式模型和生成式模型
2019-04-26
SVM和LR的适用情况,SVM中核函数的作用。
2019-04-26
以下机器学习中,在数据预处理时,不需要考虑归一化处理的是
2019-04-26
在统计模式识分类问题中,当先验概率未知时,可以使用N-P判决和最小最大损失准则
2019-04-26
聚类的定义和2个基本问题
2019-04-26
聚类算法的种类介绍
2019-04-26
隐马模型(HMM)
2019-04-26
转载CSDN博客步骤
2019-04-26
向量与矩阵的范数(比较1-范数、2-范数、无穷范数、p-范数、L0范数 和 L1范数等)
2019-04-26
对偶问题和原问题的关系
2019-04-26
线性分类器的三种最优准则
2019-04-26
常用激活函数总结
2019-04-26
支持向量机(SVM)
2019-04-26
常用来划分测试集和训练集的划分方法
2019-04-26
Python 中__new__()和__init__()的区别
2019-04-26
平面点坐标旋转公式
2019-04-26
二叉树的问题汇总
2019-04-26
排序算法的时间复杂度汇总
2019-04-26