# 深入浅出爬虫之道: Python、Golang与GraphQuery的对比 (3)

这些库,你都可以通过 go get -u 来获取,由于在上面的Python解析中我们已经整理出了解析逻辑,在Golang中只需要复现即可,与 Python 不同的是,我们最好先为我们的数据结构定义一个 struct,像下面这样:

type Reuslt struct { Title string Pictype string Number string Type string Metadata struct { Size string Volume string Mode string Resolution string } Author string Images []string Tags []string }

同时,由于我们的 待解析页面 是非主流的 gbk 编码,所以在下载下来文档之后,需要手动将 utf-8 的编码转换为 gbk 的编码,这个过程虽然不在解析的范畴之内,但是也是必须要做的步骤之一, 我们使用了 github.com/axgle/mahonia 这个库进行编码的转换,并整理出了编码转换的函数 decoderConvert:

func decoderConvert(name string, body string) string { return mahonia.NewDecoder("gbk").ConvertString(body) }

因此, 最终的 golang 代码应该是下面这样的:

package main import ( "encoding/json" "log" "regexp" "strings" "github.com/axgle/mahonia" "github.com/parnurzeal/gorequest" "github.com/PuerkitoBio/goquery" ) type Reuslt struct { Title string Pictype string Number string Type string Metadata struct { Size string Volume string Mode string Resolution string } Author string Images []string Tags []string } func RegexGet(text string, expr string) string { regex, _ := regexp.Compile(expr) return regex.FindString(text) } func decoderConvert(name string, body string) string { return mahonia.NewDecoder("gbk").ConvertString(body) } func main() { //下载文档 request := gorequest.New() _, body, _ := request.Get("http://www.58pic.com/newpic/32504070.html").End() document, err := goquery.NewDocumentFromReader(strings.NewReader(decoderConvert("gbk", body))) if err != nil { panic(err) } conseq := &Reuslt{} //获取文件标题 titleNode := document.Find(".detail-title") titleNode.Find("div").Remove() titleNode.Find("p").Remove() conseq.Title = titleNode.Text() // 获取素材类型 conseq.Pictype = document.Find(".pic-type").Text() // 获取文件格式 conseq.Type = document.Find(".mainRight-file").Text() // 获取元数据 context := document.Find(".main-right p").Text() conseq.Metadata.Mode = RegexGet(context, `尺寸:(.*?)像素`) conseq.Metadata.Resolution = RegexGet(context, `体积:(.*? MB)`) conseq.Metadata.Size = RegexGet(context, `模式:([A-Z]+)`) conseq.Metadata.Volume = RegexGet(context, `分辨率:(\d+dpi)`) // 获取作者 conseq.Author = document.Find(".user-name").Text() // 获取图片 document.Find("#show-area-height img").Each(func(i int, element *goquery.Selection) { if attribute, exists := element.Attr("src"); exists && attribute != "" { conseq.Images = append(conseq.Images, attribute) } }) // 获取tag document.Find(".mainRight-tagBox .fl").Each(func(i int, element *goquery.Selection) { conseq.Tags = append(conseq.Tags, element.Text()) }) bytes, _ := json.Marshal(conseq) log.Println(string(bytes)) }

解析逻辑完全相同,代码量和复杂程度相较 python版 差不多,下面我们来看一下新出现的 GraphQuery 是如何做的。

使用GraphQuery进行解析

已知我们想要得到的数据结构如下:

{ title pictype number type metadata { size volume mode resolution } author images [] tags [] }

GraphQuery 的代码是下面这样的:

{ title `xpath("/html/body/div[4]/div[1]/div/div/div[1]/text()")` pictype `css(".pic-type")` number `css(".detailBtn-down");attr("data-id")` type `regex("文件格式:([a-z]+)")` metadata `css(".main-right p")` { size `regex("尺寸:(.*?)像素")` volume `regex("体积:(.*? MB)")` mode `regex("模式:([A-Z]+)")` resolution `regex("分辨率:(\d+dpi)")` } author `css(".user-name")` images `css("#show-area-height img")` [ src `attr("src")` ] tags `css(".mainRight-tagBox .fl")` [ tag `text()` ] }

通过对比可以看出, 它只是在我们设计的数据结构之中添加了一些由反引号包裹起来的函数。惊艳的是,它能完全还原我们上面在 Python 和 Golang 中的解析逻辑,而且从它的语法结构上,更能清晰的读出返回的数据结构。这段 GraphQuery 的执行结果如下:

{ "data": { "author": "Ice bear", "images": [ "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=http://www.likecs.com/repeat/true/crop/0x1024a0a0", "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=http://www.likecs.com/repeat/true/crop/0x1024a0a1024", "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=http://www.likecs.com/repeat/true/crop/0x1024a0a2048", "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=http://www.likecs.com/repeat/true/crop/0x1024a0a3072" ], "metadata": { "mode": "RGB", "resolution": "200dpi", "size": "4724×6299", "volume": "196.886 MB" }, "number": "32504070", "pictype": "原创", "tags": ["大侠", "海报", "黑白", "金庸", "水墨", "武侠", "中国风"], "title": "大侠海报金庸武侠水墨中国风黑白", "type": "psd" }, "error": "", "timecost": 10997800 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssfyw.html