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

19|从正则表达式到CSS选择器:4种网页文本处理手段

你好,我是郑建勋。
在上一节课程中,我们了解了 Go Modules 依赖管理的使用方法和原理,这有助于我们在后期管理项目的复杂依赖。我之所以提前介绍依赖管理,是因为新项目一开始一般就会通过 go mod init 初始化当前项目的 module 名。
我们之前也看到了如何在 Go 中通过简单的函数调用获取网页中的数据。然而单单获取服务器返回的文本数据是远远不够的,信息和知识就隐藏在这些杂乱的数据之中。因此,我们需要有比较强的文本解析能力,将有用的信息提取出来。这节课,我们就来看看如何通过 Go 标准库、正则表达式、XPath 以及 CSS 选择器对复杂文本进行解析。
现在,让我们在任意位置新建一个文件:
> mkdir crawler
再新建一个入口文件:
> cd crawler
> touch main.go

初始化 Git 仓库

我先在 GitHub 上创建了一个 Git 仓库,名字叫 crawler。接着,我在本地新建了一个 README 文件,并建立了本地仓库和远程仓库之间的关联(你需要将下面的仓库地址替换为自己的):
echo "# crawler" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M 'main'
git remote add origin git@github.com:dreamerjackson/crawler.git
git push -u origin 'main'
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了使用Go语言对网页文本进行处理的四种方法:通过Go标准库、正则表达式、XPath以及CSS选择器。作者首先介绍了如何通过Go标准库获取网页中的数据,并展示了如何通过字符串处理函数来统计网页中链接的数量以及判断是否存在特定关键词。接着,作者讲解了使用正则表达式对复杂文本进行解析的方法,并提供了相应的代码示例。此外,作者还介绍了XPath和CSS选择器在网页文本处理中的应用,并给出了相应的代码演示。整体而言,本文通过实际代码示例生动地展示了四种不同的网页文本处理方法,为读者提供了丰富的技术参考和实践经验。 在文章中,还介绍了字符编码的处理方法,以及使用Go语言中的正则表达式标准库对文本进行复杂处理的技巧。此外,还对不同流派和标准的正则表达式进行了简要介绍,帮助读者更好地理解不同标准之间的差异。文章内容丰富,涵盖了多种技术细节,适合对网页文本处理感兴趣的读者阅读学习。 作者还通过实例介绍了XPath和CSS选择器在网页文本处理中的应用,展示了这两种方法相对于正则表达式的优势,使读者能够更好地理解和掌握这些技术。最后,作者提出了一道思考题,引发读者思考和讨论,为读者留下了一个思考和学习的空间。 总的来说,本文内容丰富,涵盖了多种技术细节,通过实例代码和技术讲解,生动地展示了网页文本处理的多种方法,适合对该领域感兴趣的读者学习参考。

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

全部留言(13)

  • 最新
  • 精选
  • 0mfg
    澎湃新闻首页应该是改版了,原来的例子抓不到内容,按照老师的思路抓到现在推荐卡片里的新闻标题,交作业了 package main import ( "bufio" "fmt" "io/ioutil" "net/http" "regexp" "golang.org/x/net/html/charset" "golang.org/x/text/encoding" "golang.org/x/text/encoding/unicode" "golang.org/x/text/transform" ) var headerRe = regexp.MustCompile(`<div class="small_cardcontent__BTALp"[\s\S]*?<h2>([\s\S]*?)</h2>`) func main() { url := "https://www.thepaper.cn/" pageBytes, err:= Fetch(url) if err!= nil { fmt.Printf("read content failed %v", err) return } matches := headerRe.FindAllSubmatch(pageBytes, -1) for _, m := range matches { fmt.Println("fetch card news:", string(m[1])) } } func Fetch(url string) ([]byte, error) { resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { fmt.Printf("Error status code: %v", resp.StatusCode) } bodyReader := bufio.NewReader(resp.Body) e := DerterminEncoding(bodyReader) //utf-8 utf8Reader := transform.NewReader(bodyReader, e.NewDecoder()) return ioutil.ReadAll(utf8Reader) } func DerterminEncoding(r *bufio.Reader) encoding.Encoding { bytes, err := r.Peek(1024) if err != nil { fmt.Printf("fetch error: %v", err) return unicode.UTF8 } e, _, _ := charset.DetermineEncoding(bytes, "") return e } 运行结果,fetch card news: 长二丁火箭70次发射发发成功,将171颗卫星送入预定轨道 fetch card news: 日本主帅森保一道歉:对不起支持我们的球迷,全力备战西班牙 fetch card news: 豪宅数万“天价电费”何来?台湾地区电价调涨背后的能源困局 fetch card news: 因白俄罗斯外长马克伊去世,俄外长推迟访问白俄罗斯

    作者回复: good

    2022-11-27归属地:北京
    3
    5
  • 徐海浪
    grep -oP 'order_id=\d+'|grep -oP '\d+'

    作者回复: Good

    2022-11-22归属地:北京
    4
  • 0mfg
    思考题,mac上通过grep -oE 'order_id=\d+' | grep -oE '\d+' 可以提取orderid

    作者回复: good

    2022-11-27归属地:北京
    2
  • 哈哈哈哈哈
    项目代码放哪里了?之前留的找不着了

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

    2022-11-26归属地:北京
    3
    2
  • 0mfg
    勘误, fmt.Println("fetch url error:%v", err) 应该为fmt.Printf("fetch url err:%v\n", err)吧

    作者回复: 是的,后面不用fmt.Println了,用log

    2022-11-27归属地:北京
    1
  • 烟消云散
    目前,Linux 和 Mac 在原生集成 GUN 套件。应该是GNU吧

    作者回复: 是的

    2022-11-22归属地:上海
    1
  • lesserror
    老师,澎湃新闻的首页改版了,代码需要调整了。不然运行后没结果。

    作者回复: 哈哈,没啥的,交的是方法

    2022-11-28归属地:北京
  • 问下最后这单个 return 含义是啥。 if err != nil { fmt.Println("fetch url error:%v", err) return }

    作者回复: 指的是函数立即返回

    2022-11-25归属地:北京
  • 0mfg
    勘误,“下面这段使用 bytes 标准库的代码和上面使用 strings 库的代码在功能上是等价的”,该处实例代码应该是这样吧 numLinks := bytes.Count(body, []byte("<a")) fmt.Printf("homepage has %d links", numLinks) exist := bytes.Contains(body, []byte("疫情")) fmt.Println(exist)
    2022-11-27归属地:北京
    1
    2
  • Geek_d09597
    更新之后的: 正则:var headerRe = regexp.MustCompile(`<div class="small_cardcontent__BTALp"[\s\S]*?<h2>([\s\S]*?)</h2>`) Xpath: nodes := htmlquery.Find(doc, `//div[@class="small_cardcontent__BTALp"]//h2`) CSS选择器: doc.Find("div.small_cardcontent__BTALp h2")
    2022-12-17归属地:广东
    1
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部