最近想爬下B站的弹幕和评论,发现网上找的教程基本无效。毕竟爬虫和反爬属于一尺高和一尺高的两侧。程序员兄弟们在网络两端的斗智斗勇也很精彩。当然,在爬虫这边,爬取网站数据的大致目的是比较明确的。比如我是冲着冰冰来的,废话不多说,开始吧!获取弹幕数据这里有一个说法。虽然网上的整体教程无效,但还是有一些步骤可以参考的。比如我们可以知道可以通过如下接口获取弹幕数据。https://comment.bilibili.com/xxxx.xml在浏览器中打开,可以看到如下:数据还是很干净的,那么接下来就是看如何获取xml地址了,即如何获取324768988ID;接下来我们搜索整个网页的源代码,可以发现如下情况;也就是说我们需要的ID可以在脚本中获取到,所以我们写一个函数来提取脚本中的内容。defgetHTML_content(self):#获取视频页面的内容response=requests.get(self.BVurl,headers=self.headers)html_str=response.content.decode()html=etree.HTML(html_str)result=etree.tostring(html)returnresultdefget_script_list(self,str):html=etree.HTML(str)script_list=html.xpath("//script/text()")returnscript_list得到所有脚本内容后,我们来分析又是我们需要的数据。script_list=self.get_script_list(html_content)#解析脚本数据,获取scriptinscript_list的cid信息:if'[{"cid":'inscript:find_script_text=scriptfinal_text=find_script_text.split('[{"cid":')[1].split(',"page":')[0]最后我们把整体代码封装成一个类,然后完成弹幕抓取的数据采集工作。spider=BiliSpider("BV16p4y187hc")spider.run()的结果如下:获取评论数据对于评论数据,可能比较复杂。需要分为主(main)评论和回复主评论的回复评论。我们使用浏览器工具抓取网页上的所有请求,然后搜索回复,可以得到如下结果:先看一下主请求,然后通过浏览器访问如下:也可以通过requests直接请求;通过观察可以知道,响应消息中的回复是主要的评论内容,我们也可以改变url中的next参数来翻页,然后请求不同的数据。这里注意rpid参数,在回复评论时会用到。我们再来看看回复评论。您也可以使用请求直接访问它。同时url中的root参数就是我们上面说的rpid参数。理清上面的关系后,我们就可以写代码了;defget_data(data):data_list=[]comment_data_list=data["data"]["replies"]foriincomment_data_list:data_list.append([i['rpid'],i['like'],i['member']['uname'],i['member']['level_info']['current_level'],i['content']['message']])returndata_listdefsave_data(data_type,data):如果不是os.path.exists(data_type+r'_data.csv'):withopen(data_type+r"_data.csv","a+",encoding='utf-8')asf:f.write("rpid,点赞数、用户数、评分、评论内容\n")foriindata:rpid=i[0]like_count=i[1]user=i[2].replace(',',',')level=i[3]content=i[4].replace(',',',')row='{},{},{},{},{}'.format(rpid,like_count,user,level,内容)f.write(row)f.write('\n')else:withopen(data_type+r"_data.csv","a+",encoding='utf-8')asf:foriindata:rpid=i[0]like_count=i[1]user=i[2].replace(',',',')level=i[3]content=i[4].replace(',',',')row='{},{},{},{},{}'.format(rpid,like_count,user,level,content)f.write(row)f.write('\n')fori在范围内(1000):url=“https://api.bilibili.com/x/v2/reply/main?jsnotallow=jsonp&next={}&type=1&oid=972516426&mode=3&plat=1&_=1632192192097”.format(str(i))print(url)d=requests.get(url)data=d.json()如果不是data['data']['replies']:breakm_data=get_data(data)save_data("main",m_data)对于m_data中的j:reply_url="https://api.bilibili.com/x/v2/reply/reply?jsnotallow=jsonp&pn=1&type=1&oid=972516426&ps=10&root={}&_=1632192668665".format(str(j[0]))print(reply_url)r=requests.get(reply_url)r_data=r.json()如果不是r_data['data']['replies']:breakreply_data=get_data(r_data)save_data("reply",reply_data)time.sleep(5)time.sleep(5)爬取过程中:这样,对于一个冰冰视频,我们已经完成了上千条评论的爬取;对于可视化,让我们做一些简单的可视化操作;首先我们看一下我们爬取到的数据的整体情况:因为数据中存在一些空值,我们来处理一下:df_new=df.dropna(axis=0,subset=["user"])你可以在下面画一张图,GO!使用pyecharts还是我们的首选,毕竟写评论popularity很容易.to_list()).add_yaxis("点赞数",df1["点赞数"].to_list(),color=Faker.rand_color()).set_global_opts(title_opts=opts.TitleOpts(title="评论人气Top20"),datazoom_opts=[opts.DataZoomOpts(),opts.DataZoomOpts(type_="inside")],).render_notebook())level分布pie_data=df_new.level.value_counts().sort_index(ascending=False)pie_data.tolist()c2=(Pie().add("",[list(z)forzinzip([str(i)for我在范围(6,1,-1)],pie_data.tolist())],radius=["40%","75%"],).set_global_opts(title_opts=opts.TitleOpts(title="水平分布"),legend_opts=opts.LegendOpts(orient="垂直",pos_top="15%",pos_left="2%"),).set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}")).render_notebook())评论词云defwordcloud(data,name,pic=None):comment=jieba.cut(str(data),cut_all=False)words=''.join(comment)img=Image.open(pic)img_array=np.array(img)wc=WordCloud(width=2000,height=1800,background_color='white',font_path=font,mask=img_array,stopwords=STOPWORDS,contour_width=3,contour_color='steelblue')wc.generate(words)wc.to_file(name+'.png')wordcloud(df_new["评论内容"],"Bingbing",'1.PNG')好了,今天的分享就到这里,喜欢冰冰的就点开看吧!
