酷Go推荐 Html 解析利器-goquery

hausliu · 2021年04月18日 · 214 次阅读
本帖已被设为精华帖!

Html 解析利器-goquery

一、简介

什么是 goquery?

goquery 是由 Go 实现的基于 Go 的 net/html 包和 CSS 选择器库 cascadia 的 HTML 解析库。

由于net/html解析器需要UTF-8编码,goquery也同样需要,所以需要确保提供的html是UTF-8编码。

为什么用 goquery?

由于 net/html 解析器返回的是节点,而不是功能齐全的 DOM 树,所以在使用的过程中 goquery 可以提供更便利的操作。

二、快速上手

我们先对微博热搜进行一个简单的解析,打印当日的热搜排名标题以及热度。

package main

import (
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "log"
    "net/http"
)

type Data struct {
    number string
    title  string
    heat   string
}

func main() {
    // 爬取微博热搜网页
    res, err := http.Get("https://s.weibo.com/top/summary")
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()
    if res.StatusCode != 200 {
        log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
    }
    //将html生成goquery的Document
    dom, err := goquery.NewDocumentFromReader(res.Body)
    if err != nil {
        log.Fatalln(err)
    }
    var data []Data
    // 筛选class为td-01的元素
    dom.Find(".td-01").Each(func(i int, selection *goquery.Selection) {
        data = append(data, Data{number: selection.Text()})
    })
    // 筛选class为td-02的元素下的a元素
    dom.Find(".td-02>a").Each(func(i int, selection *goquery.Selection) {
        data[i].title = selection.Text()
    })
    // 筛选class为td-02的元素下的span元素
    dom.Find(".td-02>span").Each(func(i int, selection *goquery.Selection) {
        data[i].heat = selection.Text()
    })
    fmt.Println(data)
}


打印结果为:

[{ 网络安全有你有我 3026574} {1 任豪道歉 1635306} {2 刘鑫方称对江歌遇害不担责 1398449} {3 小米折叠屏开售 977369} {4 姜素拉产女 952863} {5 17元吃海底捞 718468} {6 那英 我只配给沈腾杨洋伴唱 634544} {7 日本船东要求埃及打一折 575670} {8 癌症早期几乎无症状 547113} {9 央行称要重视理工科教育 540756} {10 李宁回应天价鞋 540379} {11 任豪 外网 537050} {12 谢楠汪聪主持山河令演唱会 531075} {13 偶遇张小斐为李焕英扫墓 506813} {14 FBI
每10小时启动一项对中国的新调查 503616} {15 意大利海域遭水母入侵 495294} {16 山河令演唱会票价 486933} {17 刘以豪被娜扎亲出口红印 484077} {18 吴前 473968} {19 科学家成功捕获黑洞多波段指纹 468128} {20 宋佳袁咏仪发海报裁掉对方 462762} {21 郑州一中学通报女学生坠楼事件 453126} {22 72年前她身穿旗袍运送绝密情报 451299} {23 张雨绮李柄熹 娱乐圈姐弟恋甜宠文 414856} {24 多肉杨梅奶茶 397879} {25 创4总决赛绘画撑腰大赛 380987} {26 中
学小卖部承包3年拍出320万 347615} {27 北京沙尘暴 325600} {28 罗永浩再回应被强制执行 313570} {29 在营P2P网贷机构全部停业 311420} {30 多名教师殴打幼儿被园方辞退 294579} {31 我国连续4年多未发生暴恐案事件 285303} {32 蜘蛛侠3中文片名 282589} {33 娜扎护士装造型 278113} {34 王霜说在巴黎不被尊重 267191} {35 王佑硕鼻子 250443} {36 吴磊一镜到底哭戏 249606} {37 秦岭大熊猫上树折樱桃花 249071} {38 警方通报沈阳1死2伤持刀伤人案 248500
} {39 2020年中国群众安全感指数98.4% 246917} {40 你见过哪些海王操作 246148} {41 商务部回应日本处置福岛核废水 244992} {42 一组数据看平安中国 244345} {43 赵文瑄 243697} {44 内蒙古沙尘暴风沙夹杂雨雪 242044} {45 油价或迎年内首次搁浅 241157} {46 库里的进攻能力在NBA排第几 239944} {47 在家长群抢30个红包被拘 239808} {48 明白做老师不易的瞬间 207204} {49 张哲瀚OK周年刊封面 206645} {50 轻混血浓颜泰妆 }]

三、过滤器示例

基于 HTML Element 元素的选择器

使用 Element 名称作为选择器,如 dom.Find("div")。

dom.Find("div").Each(func (i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})

ID 选择器

以 # 加 id 值作为选择器

dom.Find("#id").Each(func (i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})

Class 选择器

以.加 class 值为选择器

dom.Find(".class").Each(func (i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})

由上面的示例可以看出,goquery 的选择器与 jQuery 的选择器用法无异,在这里就不继续赘述了,同学们可以自行探索。

四、常用节点属性值

Html() 获取该节点的 html

dom.Find("table").Each(func (i int, selection *goquery.Selection) {
fmt.Println(selection.Html())
})

Text() 获取该节点的文本值

dom.Find(".td-02>a").Each(func (i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})

Attr() 返回节点的属性值以及该属性是否存在的布尔值

dom.Find("#execution").Each(func (i int, selection *goquery.Selection) {
value[i], ok = selection.Attr("value")
})

Length() 返回该 Selection 的元素个数

dom.Find("td").Length()

闲言

这个库用起来非常容易上手,尤其是对 jQuery 熟悉的同学,极大地提升了开发效率。

之前都是用 Python 写爬虫,使用 BeautifulSoup 进行解析,十分方便。第一次用 go 的 net/html 尝试解析的时候,花了很多不必要的时间,直到后来发现了 goquery,才找回了用 BeautifulSoup 的感觉。

友情提示:爬虫有风险,请务必遵守法律法规。

参考文档:

欢迎加入我们 GOLANG 中国社区:https://gocn.vip/

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
astaxie 将本帖设为了精华贴 04月19日 15:16
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册