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

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

本文将分别使用 Python ,Golang 以及 GraphQuery 来解析某网站的 素材详情页面 ,这个页面的特色是具有清晰的数据结构,但是DOM结构不够规范,无法通过单独的选择器定位页面元素,对页面的解析造成了一些曲折。通过这个页面的解析过程,深入浅出的了解爬虫的解析思想与这些语言之间的异同。

一、前言

在前言中,为了防止在后面的章节产生不必要的困扰,我们将会首先了解一些基本的编程理念。

1. 语义化的DOM结构

这里我们讲的语义化的DOM结构,不仅仅包括 语义化的html标签,也包括了语义化的选择器,在前端开发中应该注意的是,所有的动态文本都应该有单独的 html 标签包裹,并最好赋予其语义化的 class 属性或 id 属性,这在版本功能的迭代中,对前端和后端的开发都是大有裨益的,比如下面的HTML代码:

<div> <p>编号:32490230</p> <p>模式:RGB</p> <p>体积:16.659 MB</p> <p>分辨率:72dpi</p> </div>

这就是不够语义化的前端代码,32504070,RGB,16.659 MB,72dpi这些值都是动态属性, 会跟随编号的改变而改变,在规范的开发中,应该将这些 动态变化的属性,分别用 <span> 这类行内标签包裹起来,并赋予其一定的语义化选择器,在上面的HTML结构中大致可以推测出这是后端直接使用 foreach 渲染出的页面,这是不符合前后端分离的思想的,如果有一天他们决定使用 jsonp 或 Ajax 渲染这些属性, 由前端进行渲染,工作量无疑会上一个层次。语义化的DOM结构更倾向于下面这样:

<p> 模式:<span>RGB</span> </p>

也可以将 property-mode 直接作为 span 的 class 属性,这样这些属性无论是后端渲染,还是前端动态渲染都减轻了产品迭代产生的负担。

2. 稳定的解析代码

在 语义化的DOM结构 之后,我们来谈谈稳定的解析代码, 对于下面的DOM结构:

<div> <p>编号:32490230</p> <p>模式:RGB</p> <p>体积:16.659 MB</p> <p>分辨率:72dpi</p> </div>

如果我们想要提取 模式 信息,当然可以采取下面的步骤:

选取 class 属性中包含 main-right 的 div

选取这个 div 中第二个 p 元素,取出其包含的文本

删除文本中的 模式:, 得到模式为 RGB

虽然成功获取到了想要的结果,但是这样的解析方法,我们认为它是 不稳定的,这个不稳定是指 在其祖先元素、兄弟元素等自身以外的元素节点发生一定程度的结构改变时,导致解析错误或失败 的情况, 比如如果有一天在 模式 所在的节点之前增加了一个 尺寸 的属性:

<div> <p>编号:32490230</p> <p>尺寸:4724×6299像素</p> <p>模式:RGB</p> <p>体积:16.659 MB</p> <p>分辨率:72dpi</p> </div>

那么我们之前的解析将会发生错误(什么?你觉得不可能发生这样的变动?请对比 Page1 和 Page2)。
那我们应该如何写出更稳定的解析代码呢,对于上面的DOM结构,我们可以有下面几种思路:
思路一: 遍历 class 属性为 main-rightStage的 p 节点,依次判断节点的文本是否以 模式 开头, 如果是, 取出其 : 后的内容,缺点是逻辑太多,不易维护且降低了代码可读性。
思路二: 使用正则表达式 模式:([A-Z]+) 进行匹配,缺点是使用不当可能造成效率问题。
思路三: 使用 CSS选择器中的 contains 方法,比如 .main-rightStage:contains(模式), 就可以选取文本中包含 模式,且 class 属性中包含 main-rightStage 的节点了。但缺点是不同语言和不同库对这种语法的支持程度各有不同,缺乏兼容性。
使用哪种方法,仁者见仁智者见智,不同的解析思路带来的解析的 稳定性、代码的 复杂程度、运行效率 和 兼容性 都是不同的, 开发者需要从各种因素中进行权衡, 来写出最优秀的解析代码。

二、进行页面的解析

在进行页面数据的抽取之前,首先要做的是明确我们需要哪些数据、页面上提供了哪些数据,然后设计出我们需要的数据结构。首先打开 待解析页面, 由于其最上方的 浏览量、收藏量、下载量等数据是动态加载的, 在我们的演示中暂时不需要,而这个页面右边的 尺寸、模式 等数据,通过上面 Page1 和 Page2 的对比,可以得知这些属性是不一定存在的,因此将它们一起归到 metainfo 中。因此我们需要获得的数据如下图所示:

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

由此我们可以很快设计出我们的数据结构:

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

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

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