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

Colly之外的另一个Go爬虫框架——Goribot

时间:2023-03-26 15:00:07 Python

gocolly是一个用go实现的网络爬虫框架。目前在github上有3400+星数,在爬虫程序go版本中排名第一。gocolly快速优雅,以回调函数的形式提供了一套接口,可以实现任何类型的爬虫。goribotgithub.com/zhshch2002/goribot参考了colly的回调函数的设计,加入了类似Scrapy的Pipeline支持,支持添加各种扩展功能。获取Goribot:goget-ugithub.com/zhshch2002/goribot创建一个爬虫代码中导入:import"github.com/gocolly/colly"Goribot的主体是一个Spider对象,用于管理http请求,回调函数和各种插件扩展。s:=goribot.NewSpider()Goribot的基本运行单元是任务,即一个HTTP请求和一个需要为其执行的回调函数。s.AddTask(goribot.GetReq("https://github.com"),func(ctx*goribot.Context){fmt.Println(ctx.Resp.Text)},)传入的回调函数与在colly的概念是不同的。此功能仅针对此请求执行。这种设计类似于Scrapy。同时Goribot还可以像colly一样给Spider添加全局回调函数,即为每个请求添加OnReq、OnResp等函数。您可以参考提供的示例。//当蜘蛛执行s.Run()(s*Spider)时执行一次funcOnStart(fnfunc(s*Spider))//当所有线程结束后蜘蛛即将退出时调用一次func(s*Spider)OnFinish(fnfunc(s*Spider))//在向队列添加新任务之前执行func(s*Spider)OnAdd(fnfunc(ctx*Context,t*Task)*Task)//发出新的执行func(s*Spider)在Http请求之前。OnReq(fnfunc(ctx*Context,req*Request)*Request)//当有新的Http响应时执行,请求中携带的回调函数会在之后执行。func(s*Spider)OnResp(fnfunc(ctx*Context))//一个新的Item提交到队列后执行func(s*Spider)OnItem(fnfunc(iinterface{})interface{})//errororinthespiderExecutethefunc(s*Spider)OnError(fnfunc(ctx*Context,errerror))任务回调函数afterrecoveryafterpanic可以传入多个也可以不传入,因为Goribot也提供了全局回调函数类似colly。//无论是否传入回调函数,Goribot都会执行全局回调函数。如果任务简单,用likecolly就好了。s.AddTask(goribot.GetReq("https://github.com"))//为一个请求设置多个回调函数形成Pipelines.AddTask(goribot.GetReq("https://github.com"),func(ctx*goribot.Context){fmt.Println("firsthandler")},func(ctx*goribot.Context){fmt.Println("secondhandler")},)Goribot的区别Spider需要运行!Goribot的蜘蛛需要执行s.Run()才能开始执行。相对链接分析当我们从一个页面获取一个新链接时,在colly中这样写:c.OnHTML("a[href]",func(e*colly.HTMLElement){c.Visit(e.Request.AbsoluteURL(e.Attr("href")))})在Goribot中,回调函数提交的新任务会自动分析是否为相对链接并自动转换:s.OnHTML("a[href]",func(ctx*goribot.Context,sel*goquery.Selection){ctx.AddTask(goribot.GetReq(sel.AttrOr("href","")))})JSON处理Goribot提供了两种Json处理方式,在全局在回调内部:s.OnJSON("args",func(ctx*goribot.Context,jgjson.Result){fmt.Println("onjson",j.Str)})在任务回调内部:s.AddTask(goribot.GetReq("https://httpbin.org/").SetParam(map[string]string{"Goribottest":"helloworld",}),func(ctx*goribot.Context){fmt.Println(ctx.Resp.Json("args").Str)},)GoribotextensionGoribot的Spider对象只提供了基本的功能,比如robots.txt支持,请求速率限制和d其他功能由Goribotextension提供。因此,Goribot框架也保持了概念的统一性。即Spider只负责执行任务,其他功能通过扩展参数、添加回调函数实现。截至撰写本文时,Goribot的扩展如下:限制请求、速率、并发、白名单SaveItemsAsJSON|将抓取结果保存到JSON文件SaveItemsAsCSV|将抓取结果保存到CSV文件中Retry|失败时重试Robots.txt支持SpiderLogError|记录事故和错误SpiderLogPrint|打印蜘蛛运行状态RefererFiller|填充RefererSetDepthFirst|设置为深度优先策略ReqDeduplicate|请求去重RandomProxy|扩张。这是在紧急情况下记录爬虫状态和页面响应的扩展。我们在设计爬虫的时候,每时每刻只抓取少量页面,不会触发反爬,人眼也能观察到页面异常(如反爬、验证码)。但是爬虫大规模运行后,由于页面数量较多,不易观察,可以使用这个插件来记录异常状态。s:=goribot.NewSpider()s.Use(goribot.SpiderLogError(os.Stdout))//记录异常日志并输出到Stderr。在实际应用中,输出到文件就像激活一个扩展插件一样简单。接下来我们犯错:s.OnResp(func(ctx*goribot.Context){if!strings.Contains(ctx.Resp.Text,"sortedbytime"){ctx.AddItem(goribot.ErrorItem{Ctx:ctx,Msg:"禁止我B站IP~",})}ctx.AddTask(goribot.GetReq("https://www.bilibili.com/video/BV1tJ411V7eg"))ctx.AddTask(goribot.GetReq("httpshttps://www.bilibili.com/video/BV1tJ411V7eg"))ctx.AddTask(goribot.GetReq("https://www.bilibili.com/video/BV1tJ411V7eg"))ctx.AddTask(goribot.GetReq("https://www.bilibili.com/video/BV1tJ411V7eg"))})s.AddTask(goribot.GetReq("https://www.bilibili.com/video/BV1tJ411V7eg"))s.Run()如在上面的代码,爬虫启动后,会拼命访问B站的一个地址,用不了多久我们就会看到这样的东西:它记录了错误、评论、请求和响应的详细信息。我们可以在后面对这些日志进行分析,总结反爬虫的策略和特点,更加高效的完成爬虫操作。结语Goribot结构非常简单,同时也提供了丰富的文档。Goribot本身也实现了轻量级的分布式支持,这与Scrapy的分布式应用非常相似,用于构建更复杂的应用程序。