爬取过大众点评的朋友应该会遇到这样的问题,在网页中看起来正常的文字,在其源代码中变成了下面这样:
究其原因,是因为大众点评在内容上设置的特别的反爬机制,与某些网站替换底层字体文件不同,大众点评使用随机替换的SVG图片来替换对应位置的汉字内容,使得我们使用常规的手段无法获取其网页中完整的文字内容,经过观察我发现,所有可以被SVG图像替换的文字都保存在下图所示的地址中:
打开该页面后可以发现其包含了所有可以被SVG替换的文字:
在查阅了他人针对该问题提出的相关文章后,获悉他们使用的方法是先找到源代码中SVG图像对应的<span>标签,其属性class与下图红框中所示第一个以及第二个px值存在一一映射关系,且该关系全量保存在旁边对应的css中:
右键该链接,选择open in new tab,在跳转的新页面中便隐藏了全量的class属性与两个对应的px之间的映射关系:
按照前人的经验,这两个px通过一个公式与之前的SVG界面中所有汉字的行列位置构建起一一对应关系,但他们的做法是自己去手动猜测规则,建立公式从而破解从class属性到SVG文字行列位置的一一映射关系,但这样的方式显然已经被大众点评后台人员知晓,于是乎,更变态的是,他们这套映射规则几乎每天都会发生一次更新,至少我在写这篇文章的前一天遇到的情况,与今天所遭遇的情况完全不同,这就使得前人总结的那套靠脑力去猜测的方法吃力不讨好,于是我摒弃了去猜测规则,而是选择去学习规则,即利用机器学习算法来解决这个看起来较为棘手的问题;
二、基于决策树分类器的破解方法
这里我选择使用较为经典的CART分类树来训练算法,从而实现对其映射规则的学习,在训练算法前,我们需要收集适量的样本数据来构造带标签的训练集,从而支撑之后的有监督学习过程;
2.1 收集训练数据
通过观察,我发现大众点评的页面中被SVG替换的文字并不确定,即每一次刷新页面,都可能有新的文字被替换成SVG,旧的SVG图像被还原为文字,借助这个机制,我们可以通过对某一确定的页面多次刷新,每次用正则提取评论内容标签下,所有符合单个汉字格式条件和<span></span>格式条件的片段,用下面的正则就可以实现:
'(<span>)|([\u4e00-\u9fa5]{1})'
每次将符合上述任一条件的一个片段按照其在整段文字中出现的顺序拼接起来,构造位置一一对应的编码列表和文字列表,并在重复的页面刷新过程中,通过识别从SVG图像恢复成普通文字的现象,得到汉字与其class编码的一一对应关系,再将这些已证实对应关系的汉字-编码作为我们构造训练集的基础,自变量为通过该文字编码在CSS页面中索引到的两个px值(用正则即可轻松实现),因变量为该文字在SVG页面中对应的行列位置,因为每行的文字数量不太一致,所以这里需要写一个简单的算法从SVG页面源代码中抽取每个汉字的行列位置并保存起来,以上步骤我的代码实现如下,这里为了跳过模拟登陆,我选择了在本地Chrome浏览器登录自己的大众点评账号并保持登录,再利用selenium来挂载本地浏览器配置文件,从而达到自动登录的目的: