1.使用goquery爬取初始静态HTML文件中的元素

在用golang编写爬虫的过程中,goquery提供了非常方便的对于静态html页面元素提前的接口.

比如这种直接出现在出现在静态hmtl文件中的元素,就可以直接爬取

goquery支持这种Xpath风格的查询,在找到对应的节点后可以直接获取其中的属性值.

但是很快我又发现了问题,就是在一个页面中他的想法在元素审查这个界面有10个,但是在静态html文件中只有2个,也就是说审查元素和我们http请求获得的源码不一致.

所谓查看网页源代码,就是别人服务器发送到浏览器的原封不动的代码。这是爬虫获得的代码.

你那些在源码中找不到的代码(元素),那是在浏览器执行js动态生成的,这些能在审查元素中看到.

通过审查元素就看到就是浏览器处理过的最终的html代码。

在这里可行的解决方案之一就是采集在浏览器中最终生成的元素,这时就需要借助我们的第二个工具--chromedp.


2. 使用chromedp获取网页执行动态js后的代码(即审查元素)

chromedp 本质上就是一个浏览器调度包,它与Selenium非常类似,但是使用起来更加方便,更易拓展,而且对golang更加友好

使用chromedp(当然,你必须安装了chrome浏览器),我们可以将需要浏览的网站的url传入,然后等待网页把全部的动态js执行完毕,生成最后的html文件,这时再获取其中的元素,便可以读取所有的元素.

chromedp的使用过程会大量牵涉到golang 中context包的应用, 想要深入理解的小伙伴可以去系统的学习一下这个包的使用.

代码中的Useragent可以在浏览器中输入chrome://version获取

随后依然使用goquery来读取这些你想要的元素,这里要注意把获得的html文件(原string类型)转化为 Reader类型.

至此,想法的爬取已经结束.


3. 拓展chromedp函数爬取想法下面的热评

获取了所有的想法之后,接下来需要获取的就是想法下面的热评了.

问题不大,只需要点击一个按钮之后他就可以出现,在chromedp.run的条件里面加点击语句就和等待语句可以了

但是这里出现了问题,一个网页page有多个想法,每个想法又有自己的评论,也就是说每个想法的评论按钮都需要点击,这是一个批量的操作,这时chromedp自身所提供的函数Click()已经无法满足需求了,也就是说需要自己造轮子.


在这里我直接把函数贴出来,其实非常简单,拥有些许编程功力的人在阅读了源码中的Click()函数应该都可以完成.只是有几点需要注意一下

  1. 迭代变量 i 每次的自增是2, 这个具体原因我也说不清楚,似乎是因为chromedp中的Query每次寻找某一元素都会产生两个结果,所以我们要每次都跳过一个伴随生成的元素.
  2. MouseClickNode()函数会自动将页面滚动到要点击的地方,如果需要点击处不在当前页面中的话. 而后台程序移动页面的速度非常的均匀和迅速,会导致阿乎的监控程序监测出非人为操作,从而弹出登录窗口.类似下图.

我原本想做一个模拟登录的过程,但是奈何阿乎的验证码系统有点难搞,所以我选择了最简单最暴力的方法,等待这个登录窗口出现之后,直接关闭这个登录窗口,即上述代码的1、2处.

最后,在chromedp.run下面加入相应的action即可

至此,大功告成.