go 语言爬虫库goQuery 的详细使用(知乎日报详情页解析示例)

本文主要是介绍go 语言爬虫库goQuery 的详细使用(知乎日报详情页解析示例),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇《uniapp小程序开发 | 从零实现一款影视类app 》实现了影视小程序的前端和后台接口,虽然包含了大多数小程序应有的知识,但基本还只是涉及网络接口和vue页面的设计。这里介绍下零一个有趣的练手项目,知乎日报。涉及详情页面的html解析,使用了golang的goquery三方库。

前言

知乎日报这个案例很经典,有比较完整的API,很值得模仿学习。 也很简单,唯一需要注意的是日报详情的设计,因为知乎日报的详情接口,竟返回的是html,这.....

上一篇《uniapp小程序开发 | 从零实现一款影视类app 》链接:uniapp小程序开发 | 从零实现一款影视类app (后台接口实现,go-zero微服务的使用)_uniapp开源影视app-CSDN博客

知乎日报API

启动界面图片

http://news-at.zhihu.com/api/4/start-image/{size}
参数说明
size图片尺寸,格式:宽*高。例如: 768*1024

获取刚进入应用时的显示封面,可以根据传递的尺寸参数来获取适配用户屏幕的封面。

获取最新日报

http://news-at.zhihu.com/api/4/news/latest

返回的数据用于日报的首页列表,首页的结构有上下部分,上部分是图片滑动模块,用于展示热门日报,下部分是首页日报列表,以上接口返回的数据有热门日报和首页日报

获取日报详细api

http://news-at.zhihu.com/api/4/news/{id}

或者直接解析详情页:

https://daily.zhihu.com/story/9773139
参数说明
id日报id

在点击日报列表也的日报项时,需要跳转到日报详情页展示日报的具体信息,这个接口用来获取日报的展示封面和具体内容。

历史日报

http://news.at.zhihu.com/api/4/news/before/{date}
参数说明
date年月日格式时间yyyyMMdd,例如:20150903、20161202

这个接口也是用与首页列表的日报展示,但是不同的是此接口需要传一个日期参数,如20150804格式。获取最新日报接口只能获取当天的日报列表,如果需要获取前天或者更久之前的日报,则需要这个接口单独获取。

日报额外信息

http://news-at.zhihu.com/api/4/story-extra/{id}

参数说明
id日报id

在日报详情页面中,不仅要展示日报的内容,好需要额外获取此日报的评论数目和推荐人数等额外信息。

日报长评

http://news-at.zhihu.com/api/4/story/{id}/long-comments

参数说明
id日报id

日报的评论页面展示长评用到的接口

日报短评

http://news-at.zhihu.com/api/4/story/{id}/short-comments

参数说明
id日报id

日报的评论页面展示段评用到的接口

主题日报栏目列表

http://news-at.zhihu.com/api/4/themes

主页的侧边栏显示有主题日报的列表,需要通过这个接口获取主题日报栏目列表

主题日报具体内容列表

http://news-at.zhihu.com/api/4/theme/{themeId}

参数说明
themeId主题日报栏目id

在主页侧栏点击主题日报进入主题日报的内容页,需要展示此主题日报下的日报列表。

goquery介绍

GoQuery是专为Go(Golang)语言设计的一个强大的HTML解析和查询库。它模仿了jQuery的API风格,使得在Go中处理HTML文档变得简单且直观。

GoQuery主要用于网页抓取(Web Scraping),能够通过CSS选择器来定位、遍历和操作HTML元素。你可以使用它来提取网页中的特定数据、修改DOM结构或进行其他与HTML文档相关的操作。

项目地址:GitHub - PuerkitoBio/goquery: A little like that j-thing, only in Go.

goquery使用

$ go get github.com/PuerkitoBio/goquery

简单示例

package mainimport ("fmt""log""github.com/PuerkitoBio/goquery"
)func main() {if err := run(); err != nil {log.Fatal(err)}
}func run() error {doc, err := goquery.NewDocument("http://example.com")if err != nil {return fmt.Errorf("failed to load document: %w", err)}doc.Find("a").Each(func(i int, s *goquery.Selection) {href, exists := s.Attr("href")if exists {fmt.Println(href)} else {fmt.Println(s.Text())}})return nil
}

知乎详情页解析

知乎日报详情页面:知乎日报 - 知乎 

 页面对应的html代码片段:

<html>
<body><p><strong>语言的疙瘩,就是思想上的疙瘩</strong></p><p>“靠嘴写作”的作家不少,王朔就是其一。去年他出了新书,受访时有个细节,说有段时间嗓子不舒服,便没写。乍一看挺蒙:如今写东西还得比吆喝了?</p>
<p>后来看了他的自序,才知道嗓子的用途。他是“拿口语写作的作者,检查文字也须拿口语来回溜,没磕啵儿,才觉得通顺”。</p><p>言下之意,<strong>朗读修改不只是勘误这么简单,本身就是创作方式。</strong>作家老舍将朗读文章比作拉胡琴定弦,声音不对马上调整,免得一音毁全曲。</p><blockquote>嘴里念,耳朵听,我们会立刻听出文字的毛病来:有的句子太长了,应当改短;有的句子念着绕嘴,必是音节或字眼安排得不对劲,要设法调换修正;有的句子意思好,可是念起来不嘹亮,不干脆,听着不起劲,这必是句子的结构还欠妥当,或某几个字不大现成,应当再加工。一个好句子念起来嘴舒服,耳朵舒服,心里也舒服。<br>——老舍</blockquote><p>叶圣陶说得更直接——<strong>“语言的任何疙瘩,也就是思想上的疙瘩。”</strong>我认为很对,句子写得弯弯绕,归根结底是没有想清楚重点,虽极力表达而不得要领,读之如堕云雾,这就不是改几个错别字那么简单了。</p><figure><img class="content-image" src="https://pic1.zhimg.com/v2-b74ec227f579df9b7e41fd42b02269ee_720w.jpg?source=8673f162" alt=""><figcaption>Photo by Thirdman</figcaption></figure><p><strong>行文优化三步走</strong></p><p>用好"朗读修改法"有很多角度和层次。从对象来说,可以自己读给自己听,自己读给别人听,或者别人读给自己听;从功能来看,能思考立意,检视材料,还能梳理逻辑……</p>
<p>不过,从效果上看,<strong>朗读还是最利于优化行文。</strong>汪曾祺曾说:"写小说就是写语言。"让朗读聚焦于语言自然更直接显著。由浅及深,我们可以通过“读”透三个层次来锤炼字句。</p><p><strong><strong>第一层:文病</strong></strong></p></body>
</html>

如何区分p标签和紧挨着的strong标签? 

区分<p>标签和紧挨着的<strong>标签,可以使用goquery的Each函数来逐个处理每个匹配的元素,并根据需要进行逻辑判断。以下是一个示例,演示如何区分和处理这两种标签:

package mainimport ("fmt""strings""github.com/PuerkitoBio/goquery"
)func main() {html := `<html><body><p><strong>语言的疙瘩,就是思想上的疙瘩</strong></p><p>“靠嘴写作”的作家不少,王朔就是其一。去年他出了新书,受访时有个细节,说有段时间嗓子不舒服,便没写。乍一看挺蒙:如今写东西还得比吆喝了?</p><p>后来看了他的自序,才知道嗓子的用途。他是“拿口语写作的作者,检查文字也须拿口语来回溜,没磕啵儿,才觉得通顺”。</p><p>言下之意,<strong>内容</strong></p></body></html>`doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))if err != nil {fmt.Println("Error loading HTML:", err)return}var prevTag stringdoc.Find("p, strong").Each(func(i int, s *goquery.Selection) {tagName := s.Get(0).Dataif tagName == "p" {prevTag = "p"fmt.Println("p tag:", s.Text())} else if tagName == "strong" && prevTag == "p" {fmt.Println("strong tag:", s.Text())}})
}

在上面的代码中,定义一个prevTag变量来跟踪前一个处理过的标签,然后在Each函数中根据标签类型执行不同的操作。当遍历到<p>标签时,打印出其文本内容并将prevTag设置为"p",然后当遍历到紧挨着的<strong>标签时,检查前一个处理过的标签类型,如果是<p>,则打印出<strong>标签的内容。

完整解析代码:

func (l *ZhiDetailLogic) ZhiDetail(req *types.ZhiDetailReq) (resp *types.ZhiDetailResp, err error) {// todo: add your logic here and delete this lineurl := "https://daily.zhihu.com/story/" + req.Idres, err_ := httpc.Do(l.ctx, http.MethodGet, url, nil)if err_ != nil {l.Error(err_)return nil, err_}defer res.Body.Close()// Load the HTML documentdoc, err := goquery.NewDocumentFromReader(res.Body)if err != nil {l.Error(err)}//var zhi types.CtItemvar responseData []types.CtItemtitle := doc.Find(".DailyHeader-title").Text()image, _ := doc.Find(".DailyHeader-image").Find("img").Attr("src")author := ""avatar := ""bio := ""doc.Find(".meta").Each(func(i int, s *goquery.Selection) {author = s.Find("span[class=author]").Text()l.Debugf("author:", author)bio = s.Find("span[class=bio]").Text()avatar, _ = s.Find("img[class=avatar]").Attr("src")})// 遍历.content下的所有子节点doc.Find(".content *").Each(func(i int, s *goquery.Selection) {var itm types.CtItem// 判断节点类型并相应处理tagName := s.Get(0).DataAtom.String()switch tagName {case "p":// 在p内部查找strong标签strong := s.Find("strong")if strong.Length() == 1 {itm.Types = "strong"itm.Value = s.Text()responseData = append(responseData, itm)} else {itm.Types = "p"itm.Value = s.Text()responseData = append(responseData, itm)}case "li":itm.Types = "li"itm.Value = s.Text()responseData = append(responseData, itm)case "figure":// 在figure内部查找img标签img := s.Find("img")if img.Length() > 0 {src, _ := img.Attr("src")itm.Types = "img"itm.Value = srcresponseData = append(responseData, itm)}}})resp = &types.ZhiDetailResp{Code:    0,Message: res.Status,Content: responseData,Title:   title,Author:  author,Bio:     bio,Avatar:  avatar,Image:   image,}return
}

其他资源

go 语言爬虫库goquery的具体使用_Golang_脚本之家

goquery: 快速高效的HTML解析库-CSDN博客

Golang学习日志 ━━ goQuery 的使用-CSDN博客

https://www.51cto.com/article/785226.html

Go语言colly框架的快速入门_Golang_脚本之家

https://news-at.zhihu.com/api/7/news/9773139

go-zero超强工具goctl的常用命令api,rpc,model及其构建的服务解析-CSDN博客

go-zero 缩短从需求到上线的距离

GitHub - cwuom/MusicHelper: 一个通过Python编写的QQ、网易云音乐无损音乐爬取工具

https://www.cnblogs.com/oopsguy/p/5968447.html

GitHub - oopsguy/wechat-miniprogram-examples: WeChat mini program examples. 微信小程序示例 

这篇关于go 语言爬虫库goQuery 的详细使用(知乎日报详情页解析示例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073789

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl