当前位置: 首页 > 后端技术 > Python

Golang爬虫快速入门-获取B站全站视频数据

时间:2023-03-25 22:03:37 Python

原文首发,持续更新于https://imagician.net/archives/92/。更多内容请看我的博客https://imagician.net/说到爬虫,总会想到Python。Python似乎是爬虫的唯一选择。爬虫只是完成访问页面和收集数据的任务,可以用任何语言编写。与Python实现速度快但体积庞大相比,Golang似乎是另一种更好的编写爬虫的选择。HTTP请求Golang语言的HTTP请求库不需要使用第三方库,标准库已经内置了足够好的支持:packagemainimport("fmt""net/http""io/ioutil")funcfetch(urlstring)string{fmt.Println("FetchUrl",url)//创建请求req,_:=http.NewRequest("GET",url,nil)//创建HTTP客户端client:=&http.Client{}//发出请求resp,err:=client.Do(req)iferr!=nil{fmt.Println("Httpgeterr:",err)return""}ifresp.StatusCode!=200{fmt.Println("Httpstatuscode:",resp.StatusCode)return""}//读取HTTP响应文本deferresp.Body.Close()body,err:=ioutil.ReadAll(resp.Body)iferr!=nil{fmt.Println("读取错误",err)return""}returnstring(body)}funcmain(){fmt.Println(fetch("https://github.com"))}使用官方HTTP包快速请求页面并获取返回的数据。就像Python有Scrapy库一样,爬虫框架可以大大简化HTTP请求、数据提取、收集的过程,同时提供更多的工具来帮助我们实现更复杂的功能。Golang爬虫框架——Goribothttps://github.com/zhshch2002/goribot是一个用Golang编写的轻量级爬虫框架,具有良好的扩展性和分布式支持能力。文档位于https://imagician.net/goribot/。获取Goribot:goget-ugithub.com/zhshch2002/goribot使用Goribot实现上面代码的功能看起来简单多了。packagemainimport("fmt""github.com/zhshch2002/goribot")funcmain(){s:=goribot.NewSpider()s.AddTask(goribot.GetReq("https://github.com"),func(ctx*goribot.Context){fmt.Println(ctx.Resp.Text)},)s.Run()}这样实现了一个单一的功能,即访问“https://github.com”并打印出来结果。这样的应用,用一个框架是不够的。那么让我们从一个更复杂的爬虫应用开始。使用Goribot爬取B站信息我们来搭建一个更复杂的爬虫应用,期望实现两个功能:自动沿链接发现新的视频链接,提取标题、封面图、作者和视频数据(播放、投币、收藏)等.)研究B站的页面首先我们研究B站的视频页面,以https://www.bilibili.com/video/BV1JE411P7hK?spm_id_from=333.851.b_62696c695f7265706f72745f6469676974616c.21为例。按F12打开调试界面,切换到Network标签。我们可以看到这个页面涉及到的所有请求和资源。在调试界面选择XHR选项,查看Ajax请求。您可以通过点击不同的请求,在右侧弹出的面板中查看具体内容。单击新面板中的预览以查看服务器响应的内容。然后,我给你一个任务,依次检查XHR下的所有请求,找出哪个最像服务器返回的点赞、收藏、播放数据。太好了,让我们看看你是否找到了这个?你已经成功实现了爬虫工程师的成就——从Ajax请求中寻找目标数据。然后我们切换到Header(标头)选项,看看这个请求对应的参数。最好找到这个response和videoId的关系。找到了视频ID-BV编号。我们已经解决了核心问题,获取了B站的视频数据。对于自动视频搜索,我们可以设置一个起始链接,然后搜索标签来扩展抓取。构建爬虫的完整代码在下文中。创建爬虫s:=goribot.NewSpider(//创建爬虫并注册扩展goribot.Limiter(true,&goribot.LimitRule{//添加限制器限制白名单域名和请求简写限制glob:"*.bilibili.com",//防止服务器压力过大被B站服务器屏蔽Rate:2,}),goribot.RefererFiller(),//自动填写Referer,见Goribot(https://imagician.net/goribot/)关于扩展部分goribot.RandomUserAgent(),//随机UAgoribot.SetDepthFirst(true),//使用深度优先策略,即沿着一个页面走,然后到子页面而不是同级页面)获取视频数据vargetVideoInfo=func(ctx*goribot.Context){res:=map[string]interface{}{"bvid":ctx.Resp.Json("data.bvid").String(),"title":ctx.Resp.Json("data.title").String(),"des":ctx.Resp.Json("data.des").String(),"pic":ctx.Resp.Json("data.pic").String(),//封面图"tname":ctx.Resp.Json("data.tname").String(),//c类名"owner":map[string]interface{}{//videoAuthor"name":ctx.Resp.Json("data.owner.name").String(),"mid":ctx.Resp.Json("data.owner.mid").String(),"face":ctx.Resp.Json("data.owner.face").String(),//头像},"ctime":ctx.Resp.Json("data.ctime").String(),//创建时间"pubdate":ctx.Resp.Json("data.pubdate").String(),//发布时间"stat":map[string]interface{}{//视频数据"view":ctx.Resp.Json("data.stat.view").Int(),"弹幕":ctx.Resp.Json("data.stat.danmaku").Int(),"回复":ctx.Resp.Json("data.stat.reply").Int(),"favorite":ctx.Resp.Json("data.stat.favorite").Int(),"coin":ctx.Resp.Json("data.stat.coin").Int(),"share":ctx.Resp.Json("data.stat.share").Int(),"like":ctx.Resp.Json("data.stat.like").Int(),"dislike":ctx.Resp.Json("data.stat.dislike").Int(),},}ctx.AddItem(res)//保存到蜘蛛的Item处理队列}这是一个函数,自动解析response中的Json数据,即刚才看到的Ajax结果在解析完数据后保存到蜘蛛的Item处理队列中。查找新视频varfindVideogoribot.CtxHandlerFunfindVideo=func(ctx*goribot.Context){u:=ctx.Req.URL.String()fmt.Println(u)ifstrings.HasPrefix(u,"https://www.bilibili.com/video/"){//判断是否为视频页面ifstrings.Contains(u,"?"){u=u[:strings.Index(u,"?")]}u=u[31:]//截取视频中的BV号fmt.Println(u)//创建任务从BV号获取具体数据,使用之前的策略ctx.AddTask(goribot.GetReq("https://api.bilibili.com/x/web-interface/view?bvid="+u",getVideoInfo)}ctx.Resp.Dom.Find("a[href]").Each(func(iint,sel*goquery.Selection){ifh,ok:=sel.Attr("href");ok{ctx.AddTask(goribot.GetReq(h),findVideo)//使用相同的策略处理子页面}})}CollectItemWe正在获取视频数据Ajax数据获取并保存到Item队列中。我们在这里处理这些项目,以避免通过读写文件和数据库来阻塞主爬行线程。s.OnItem(func(iinterface{})interface{}{fmt.Println(i)//我们暂时不做任何处理,直接打印出来returni})OnItem的具体使用可以参考到Goribot文档的相关内容。最后我们运行//seedtasks.AddTask(goribot.GetReq("https://www.bilibili.com/video/BV1at411a7RS"),findVideo)s.Run()完整代码如下packagemainimport("fmt""github.com/PuerkitoBio/goquery""github.com/zhshch2002/goribot""strings")funcmain(){s:=goribot.NewSpider(goribot.Limiter(true,&goribot.LimitRule{Glob:"*.bilibili.com",评分:2,}),goribot.RefererFiller(),goribot.RandomUserAgent(),goribot.SetDepthFirst(true),)vargetVideoInfo=func(ctx*goribot.Context){res:=map[string]interface{}{"bvid":ctx.Resp.Json("data.bvid").String(),"title":ctx.Resp.Json("data.title").String(),"des":CTX。Resp.Json("data.des").String(),"pic":ctx.Resp.Json("data.pic").String(),//封面图"tname":ctx.Resp.Json("data.tname").String(),//类别名称"owner":map[string]interface{}{//视频作者"name":ctx.Resp.Json("data.owner.name").String(),"mid":ctx.Resp.Json("data.owner.mid").String(),"face":ctx.Resp.Json("data.owner.face").String(),//头像},"ctime":ctx.Resp.Json("data.ctime").String(),//创建时间"pubdate":ctx.Resp.Json("data.pubdate").String(),//发布时间"stat":map[string]interface{}{//视频数据"view":ctx.Resp.Json("data.stat.view").Int(),"弹幕":ctx.Resp.Json("data.stat.danmaku").Int(),"回复":ctx.Resp.Json("data.stat.reply").Int(),"favorite":ctx.Resp.Json("data.stat.favorite").Int(),"coin":ctx.Resp.Json("data.stat.coin").Int(),"分享":ctx.Resp.Json("data.stat.share").Int(),"喜欢":ctx.Resp.Json("data.stat.like").Int(),"不喜欢":ctx.Resp.Json("data.stat.dislike").Int(),},}ctx.AddItem(res)}varfindVideogoribot.CtxHandlerFunfindVideo=func(ctx*goribot.Context){u:=ctx.Req.URL.String()fmt.Println(u)ifstrings.HasPrefix(u,"https://www.bilibili.com/video/"){ifstrings.Contains(u,"?"){u=u[:strings.Index(u,"?")]}u=u[31:]fmt.Println(u)ctx.AddTask(goribot.GetReq("https://api.bilibili.com/x/web-interface/view?bvid="+u),getVideoInfo)}ctx.Resp.Dom.Find("a[href]").Each(func(iint,sel*goquery.Selection){ifh,ok:=sel.Attr("href");ok{ctx.AddTask(goribot.GetReq(h),findVideo)}})}s.OnItem(func(iinterface{})interface{}{fmt.Println(i)returni})s.AddTask(goribot.GetReq("https://www.bilibili.com/video/BV1at411a7RS").SetHeader("cookie","_uuid=1B9F036F-8652-DCDD-D67E-54603D58A9B904750infoc;buvid3=5D62519D-8AB5-449B-A4CF-72D17C3DFB87155806infoc;sid=9h5nzg2a;LIVE_BUVID=AUTO7815811574205505;CURRENT_FNVAL=16;im_notify_type_403928979=0;rpdid=|(k|~uu|lu||0J'ul)ukk)~kY;_ga=GA1.2.533428114.1584175871;PVID=1;DedeUserID=403928979;DedeUserID__ckMd5=08363945687b3545;SESSDATA=b4f022fe%2C1601298276%2C1cf0c*41;bili_jct=2f00b7d205a97aa2ec1475f93bfcb1a3;bp_t_offset_403928979=375484225910036050"),findVideo)s.Run()}最后爬虫框架只是工具,重要Seetheproject_examplesanddocumentationtounderstandhowpeopleuseit.

最新推荐
猜你喜欢