Go 进阶 · 分布式爬虫实战
郑建勋
Go 语言技术专家,《Go 语言底层原理剖析》作者
15839 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 58 讲
Go 进阶 · 分布式爬虫实战
15
15
1.0x
00:00/00:00
登录|注册

21|采集引擎:实战接口抽象与模拟浏览器访问

你好,我是郑建勋。
我们知道,接口是实现功能模块化、构建复杂程序强有力的手段。在上一节课,我介绍了接口的最佳实践和原理。这一节课,让我们在爬虫程序中实战接口,对采集引擎完成接口抽象。

接口抽象

第 19 讲,我们已经将爬取网站信息的代码封装为了 fetch 函数,完成了第一轮的功能抽象。但是随着爬取的网站越来越复杂,加上服务器本身的反爬机制等原因,我们需要用到不同的爬取技术。例如后面会讲到的模拟浏览器访问、代理访问等。要想比较容易地切换不同的爬取方法,用模块化的方式对功能进行组合、测试,我们可以很容易地想到可以对爬取网站数据的代码模块进行接口抽象。

实战接口

具体的做法,我们首先要创建一个新的文件夹,将 package 命名为 collect,把它作为我们的采取引擎。之后所有和爬取相关的代码都会放在这个目录下。
mkdir collect
touch collect/collect.go
接着我们要定义一个 Fetcher 接口,内部有一个方法签名 Get,参数为网站的 URL。后面我们还将对函数的方法签名进行改变,也会添加其他方法签名,比如用于控制超时的 Context 参数等。不过要知道的是,在 Go 语言中,对接口的变更是非常轻量的,我们不用提前费劲去设计。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了爬虫程序中接口抽象和模拟浏览器访问的技术要点。作者首先强调了接口抽象的重要性,并通过示例代码展示了如何使用接口来实现基本爬取的逻辑。随后,详细介绍了模拟浏览器访问的必要性,以及如何通过设置HTTP请求头和使用浏览器驱动协议来实现模拟浏览器的能力。文章通过实际代码演示了如何创建Fetcher接口、实现基本爬取逻辑以及模拟浏览器访问的过程,为读者提供了清晰的技术指导。此外,还介绍了Chrome DevTools协议的使用方法,以及空接口在API设计中的作用。总的来说,本文内容丰富,对于想要深入了解爬虫程序设计的读者具有一定的参考价值。文章还提到了空接口与反射的关系,以及接口的陷阱,为读者呈现了更加全面的技术视角。通过本文的阅读,读者可以获得关于爬虫程序设计和接口抽象的深入理解,同时也能够对反射和接口的使用中可能遇到的问题有所警示。文章以实例和案例为主线,结合代码演示,使得技术内容更加生动易懂。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 进阶 · 分布式爬虫实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(18)

  • 最新
  • 精选
  • 哈哈哈哈哈
    麻烦发个全部代码链接。小白,一段一段代码看着不是很懂

    作者回复: https://github.com/dreamerjackson/crawler,注意看文中指明的tag分支

    2022-11-27归属地:北京
    2
    4
  • Realm
    "第一类错误是,当接口中存储的是值,但是结构体是指针时,接口动态调用无法编译通过。" 接口中存储的是值,结构体是指针,这句能展开说说吗?不是特别明白。

    作者回复: “接口中存储的是值”指的是接口中存储的已经并不是原始数据的引用了,如下代码会报错 type adder interface { Add() } type M struct{} func (m *M) Add() { } func main() { var m adder = M{} m.Add() } # command-line-arguments ./1_print.go:21:6: cannot use M{} (type M) as type adder in assignment: M does not implement adder (Add method has pointer receiver)

    2022-11-29归属地:北京
    4
    1
  • shuff1e
    老哥,更新速度能不能快些?

    作者回复: try my best~

    2022-11-28归属地:北京
    1
  • 叶绘落
    文中有一段代码 func findExecPath() string ... 看起来与文章内容毫无关联,不知道为何贴上来。

    作者回复: 这里是解释chromedp库默认查找当前系统指定路径下指定的谷歌应用程序,这个函数findExecPath就是实现该功能的

    2022-12-16归属地:广东
    2
  • 吹口哨yu
    为啥 BaseFetch 的 Get 写成 func (BaseFetch) Get(...), 而不写成 func (b *BaseFetch) Get(...) ?

    作者回复: 结构体比较简单的时候就还无所谓,比较复杂的结构体是建议用指针的

    2022-12-03归属地:北京
  • Calabash
    代码在哪里

    作者回复: https://github.com/dreamerjackson/crawler,注意看文中指明的tag分支

    2022-11-28归属地:北京
  • 哈哈哈哈哈
    utf8Reader := transform.NewReader(bodyReader, e.NewDecoder()),”transform.NewReader“这是从哪冒出来的。本人刚学,原文中不方便贴出全部代码,麻烦贴个链接我慢慢看。

    作者回复: https://github.com/dreamerjackson/crawler,注意看文中指明的tag分支

    2022-11-27归属地:北京
    3
  • 范飞扬
    tag是多少?

    作者回复: 可以直接看最新的main分支

    2022-11-27归属地:北京
  • 使用 chromedp 必须要单独安装 Chrome 浏览器吗?内部能不能直接集成?在服务器上是不能直接安装的

    作者回复: 在容器里面集成无头的谷歌浏览器就好了,是很小的

    2022-11-26归属地:北京
    2
  • 0mfg
    敲一遍跑一遍基本学会反射了,createQuery进本人调试可正常运行版本 package main import ( "fmt" "reflect" ) type Student struct { Name string Age int } type Trade struct { tradeId int Price int } func createQuery(q interface{}) string { var query string if reflect.TypeOf(q).Kind() == reflect.Struct { //如果q是结构体 t := reflect.TypeOf(q).Name() query = fmt.Sprintf("insert into %s values(", t) //拼接出insert into student values( v := reflect.ValueOf(q) for i := 0; i < v.NumField(); i++ { switch v.Field(i).Kind() { case reflect.Int: if i == 0 { query = fmt.Sprintf("%s%d", query, v.Field(i).Int()) //拼接出insert into student values(20 } else { query = fmt.Sprintf("%s, %d", query, v.Field(i).Int()) //拼接出insert into student values(jonson, 20) } case reflect.String: if i == 0 { query = fmt.Sprintf("%s%s", query, v.Field(i).String()) //拼接出insert into student values(jonson } else { query = fmt.Sprintf("%s, %s", query, v.Field(i).String()) //拼接出insert into student values(20, jonson } } } query = fmt.Sprintf("%s)", query) fmt.Println(query) } return query } func main() { createQuery(Student{Name: "jonson", Age: 20}) createQuery(Trade{tradeId: 123, Price: 456}) }
    2022-11-28归属地:北京
    2
收起评论
显示
设置
留言
18
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部