Go语言网络爬虫下载器接口

Go语言网络爬虫下载器接口,第1张

概述与 ModuleInternal 接口一样,下载器接口 Downloader 也内嵌了 Module 接口,它额外声明了一个 Download 方法。有了 ModuleInternal 接口及其实现类型,实现下载器时只需关注它的特色功能,其他的都 与 ModuleInternal 接口一样,下载器接口 Downloader 也内嵌了 Module 接口,它额外声明了一个 Download 方法。有了 ModuleInternal 接口及其实现类型,实现下载器时只需关注它的特色功能,其他的都交给内嵌的 stub.ModuleInternal 就可以了。

下载器的实现类型名为 myDownloader,其声明如下:
//下载器的实现类型type myDownloader struet {    //组件基础实例    stub.ModuleInternal    //下载用的http客户端    httpClIEnt http.ClIEnt}
可以看到,我匿名地嵌入了一个 stub.ModuleInternal 类型的字段,这种只有类型而没有名称的字段称为匿名字段。如此一来,myDownloader 类型的方法集合中就包含了 stub.ModuleInternal 类型的所有方法。因而,*myDownloader 类型已经实现了 Module 接口。

另一个 http.ClIEnt 类型的字段用于对目标服务器发送 http 请求并接收响应。http.ClIEnt 类型是做 http 客户端程序的必选,它开箱即用,同时又很开放,有很多可定制的地方。

myDownloader 类型的这两个字段的值都需要使用方直接或间接提供。关于第一个字段的值,可以很容易通过 stub.NewModuleInternal 函数生成。而第二个字段的值,可以直接通过复合字面量 http.ClIEnt{} 生成。

不过,我强烈建议你对它进行一些定制,如果你想让下载器跑得更快的话。后面讲网络爬虫程序示例的时候,我们会给出一些建议。

代码包 gopcp.v2/chapter6/webcrawler/module/local/downloader 中存放了所有与下载 器实现有关的代码,大家可以从我的网盘中下载相关代码包(链接:https://pan.baidu.com/s/1yzWHnK1t2jLDIcTPFMLPCA 提取码:slm5)。为了方便使用方创建下载器的实例,可以在其中编写了一个名为 New 的函数:
//用于创建一个下载器实例func New(    mID module.MID,clIEnt *http.ClIEnt,scoreCalculator module.Calculatescore) (module.Downloader,error) {    moduleBase,err := stub.NewModuleInternal(mID,scoreCalculator)    if err != nil {        return nil,err    }    if clIEnt == nil {        return nil,genParameterError( "nil http clIEnt")    }    return &myDownloader{        ModuleInternal: moduleBase,httpClIEnt:    *clIEnt,},nil}
上述代码中,stub.NewModuleInternal 函数需要组件 ID 和组件评分计算器来生成组件内部基础类型的值,那我就让 New 函数的参数声明列表包含它们。对这两个参数的校验 由 stub.NewModuleInternal 函数全权负责。

注意,这里还隐藏着一个 Go语言的命名惯例。由于下载器的实现代码独占一个代码包,所以可以让这个函数的名称足够简单,只有一个单词 New。这不同于前面提到的函数 NewPool 和 NewMultipleReader,这两个函数所创建的实例的含义无法由其所在代码包的名称 buffer 和 reader 表达。

另外,虽然函数 NewBuffer 所创建的实例的含义可以由其所在的代码包 buffer 表达,但是该包中用于创建实例的函数不止它一个。如果把它们的名称简化为 New,恐怕会造成表达上的不清晰。而 downloader 包中唯一用于创建实例的函数 New,可以让你马上明白它就是用于创建下载器实例的,并不需要过多解释。这就是命名方面的惯用法,也是一种技巧。

下面来看下载器的 Download 方法的实现:
func (downloader *myDownloader) Download(req *module.Request) (*module.Response,error) {    downloader.ModuleInternal.IncrHandlingNumber()    defer downloader.ModuleInternal.DecrHandlingNumber()    downloader.ModuleInternal.IncrCalledCount()    if req == nil {        return nil,genParameterError("nil request")    }    httpReq := req.httpReq()    if httpReq == nil {        return nil,genParameterError("nil http request")    }    downloader.ModuleInternal.IncrAcceptedCount()    logger.Infof("Do the request (URL: %s,depth: %d)... \n",httpReq.URL,req.Depth()) httpResp,err := downloader.httpClIEnt.Do(httpReq)    if err != nil {        return nil,err    }    downloader.ModuleInternal.IncrCompletedCount()    return module.NewResponse(httpResp,req.Depth()),nil}
这个方法的功能实现起来很简单,不过要注意对那 4 个组件计数的 *** 作。在方法的开始处,要递增实时处理数,并利用 defer 语句保证方法执行结束时递减这个计数。同时,还要递增调用计数。

在所有参数检查都通过后,要递增接受计数以表明该方法接受了这次调用。一旦目标服务器发回了 http 响应并且未发生错误,就可以递增成功完成计数 To 这代表当前组件实例又有效地为使用者提供了一次服务。 总结

以上是内存溢出为你收集整理的Go语言网络爬虫下载器接口全部内容,希望文章能够帮你解决Go语言网络爬虫下载器接口所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1271641.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存