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

其中 size、volume、mode、resolution由于可能不存在,因此归入到了 metadata 下, images 是一个图片地址的数组,tags 是标签数组,在确定了要提取的数据结构,就可以开始进行解析。

使用Python进行页面的解析

Python库的数量非常庞大,有很多优秀的库可以帮助到我们,在使用Python进行页面的解析时,我们通常用到下面这些库:

提供 正则表达式 支持的 re 库

提供 CSS选择器 支持的 pyquery 和 beautifulsoup4

提供 Xpath 支持的 lxml 库

提供 JSON PATH 支持的 jsonpath_rw 库

这些库在 Python 3 下获得支持的,可以通过 pip install 进行安装。
由于 CSS选择器 的语法比 Xpath 语法要更加简洁,而在方法的调用上,pyquery 比 beautifulsoup4 要更加方便,因此在 2 和 3 之间我们选择了 pyquery。
下面我们会以 title 和 type 属性的获取作为例子进行讲解, 其他节点的获取是同理的。首先我们先使用 requests 库下载这个页面的源文件:

import requests from pyquery import PyQuery as pq response = requests.get("http://www.58pic.com/newpic/32504070.html") document = pq(response.content.decode('gb2312'))

下面使用Python进行的解析都将依次为前提进行。

1. 获取title节点

打开 待解析页面,在标题上右键, 点击 查看元素,可以看到它的DOM结构如下:

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

这时我们注意到, 我们想要提取出的标题文本 大侠海报金庸武侠水墨中国风黑白,并没有被html标签包裹,这是不符合我们上面提到的 的。同时,使用CSS选择器,也是无法直接选取到这个文本节点的(可以使用Xpath直接选取到,本文略)。对于这样的节点,我们可以有下面两种思路:
思路一: 先选取其父元素节点, 获取其 HTML 内容,使用正则表达式, 匹配在 </div> 和 <p 之间的文本。
思路二: 先选取其父元素节点,然后删除文本节点之外的其他节点,再直接通过获取父元素节点的文本,得到想要的标题文本。
我们采取思路二,写出下面的Python代码:

title_node = document.find(".detail-title") title_node.find("div").remove() title_node.find("p").remove() print(title_node.text())

输出结果与我们期望的相同, 为 大侠海报金庸武侠水墨中国风黑白。

2. 获取size节点

在 尺寸 上右键查看元素,可以看到下图所示的DOM结构:

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

我们发现这些节点不具有语义化的选择器,并且这些属性不一定都存在(详见Page1 和 Page2 的对比)。在 中我们也讲到了对于这种结构的文档可以采取的几种思路,这里我们采用正则解析的方法:

import re context = document.find(".mainRight-file").text() file_type_matches = re.compile("尺寸:(.*?像素)").findall(context) filetype = "" if len(file_type_matches) > 0: filetype = file_type_matches[0] print(filetype)

由于获取 size、volume、mode、resolution 这些属性,都可以采取类似的方法,因此我们可以归结出一个正则提取的函数:

def regex_get(text, expr): matches = re.compile(expr).findall(text) if len(matches) == 0: return "" return matches[0]

因此,在获取 size 节点时,我们的代码就可以精简为:

size = regex_get(context, r"尺寸:(.*?像素)") 3. 完整的Python代码

到这里,我们解析页面可能遇到的问题就已经解决了大半,整个Python代码如下:

import requests import re from pyquery import PyQuery as pq def regex_get(text, expr): matches = re.compile(expr).findall(text) if len(matches) == 0: return "" return matches[0] conseq = {} ## 下载文档 response = requests.get("http://www.58pic.com/newpic/32504070.html") document = pq(response.text) ## 获取文件标题 title_node = document.find(".detail-title") title_node.find("div").remove() title_node.find("p").remove() conseq["title"] = title_node.text() ## 获取素材类型 conseq["pictype"] = document.find(".pic-type").text() ## 获取文件格式 conseq["filetype"] = regex_get(document.find(".mainRight-file").text(), r"文件格式:([a-z]+)") ## 获取元数据 context = document.find(".main-right p").text() conseq['metainfo'] = { "size": regex_get(context, r"尺寸:(.*?像素)"), "volume": regex_get(context, r"体积:(.*? MB)"), "mode": regex_get(context, r"模式:([A-Z]+)"), "resolution": regex_get(context, r"分辨率:(\d+dpi)"), } ## 获取作者 conseq['author'] = document.find('.user-name').text() ## 获取图片 conseq['images'] = [] for node_image in document.find("#show-area-height img"): conseq['images'].append(pq(node_image).attr("src")) ## 获取tag conseq['tags'] = [] for node_image in document.find(".mainRight-tagBox .fl"): conseq['tags'].append(pq(node_image).text()) print(conseq) 使用Golang进行页面的解析

在 Golang 中解析 html 和 xml 文档, 常用到的库有以下几种:

提供 正则表达式 支持的 regexp 库

提供 CSS选择器 支持的 github.com/PuerkitoBio/goquery

提供 Xpath 支持的 gopkg.in/xmlpath.v2 库

提供 JSON PATH 支持的 github.com/tidwall/gjson 库

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

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