最近需要抓一点点微博的数据,于是又开始做爬虫的老行当了。不过这次抓的数据相对比较少,本来是觉得会很快,可惜还是因为种种原因多折腾了两个小时。这里对这部分工作做一个记录。
我个人一直觉得爬虫是个很重要的东西,尤其是针对机器学习应用的研发,好的数据、新的数据、源源不断的新的数据是好的模型的前提。甚至不用做什么机器学习模型,仅仅从好的数据发掘的一些规则都很有帮助。所以,可以快速的抓数据、快速的抓各种各样的数据是一个很重要的能力。这里就不展开讲了,还是控制篇幅,以这次任务为主。
从自己的微博首页或者随便一个主题下面抓点纯文本的微博数据,用于测试命名实体识别模型。
很久以前(大约还在读研究生的时候)那个时候的微博有一个移动版本,这个版本里面各种静态 html 非常好爬,所以难点基本就是发现 m.weibo.com
的存在...
不过很遗憾,现在不论是 weibo.com
还是 m.weibo.com
都不再是纯 html 了,都会动态获取数据了,需要有 js 的运行时环境才能以比较自然的方式抓取数据,毕竟目前 weibo 的数据动态加载策略、参数啥的有点复杂了,去解析它更麻烦。
对于动态获取数据的页面来说,可以采用 headless browwser 配合 puppeteer 来模拟页面的操作以加载并获取数据。不过我觉得这样做很明显有这么几个缺点:
针对这个问题,我觉得有两个思路可以大大缓解:
而 webscraper 则恰恰提供了以上两个东西。
webscraper 是一个 chrome 扩展,其实它的内部依然是类似与 puppeteer 的东西,不过它做成了一个扩展,并提供了一些非常强大的封装,可以让你通过点点点就能实现一个数据爬虫的流程。
封装程度高到如下的样子:
包括:
通过点点点,就能简历一个 css selector 来定位所要抓取的 html 元素路径。
在步骤 2 定位了想要抓取的具体数据后,可以在该数据上建立层级结构,标记具体想要抓取的数据结构,非常方便数据的结构化。
有关这个东西有一个 卤蛋工作室 很详细的对它做了系列教程,感兴趣的话推荐一看,我这里就简单说说。不过很遗憾,这个东西在如今的微博也不太能用了。虽然现在的微博很符合它所提供的「滚动到底部」的抓取模式,但目前的微博出于性能的考虑,对自己的这个微博列表做了元素重用,导致不论怎么滚动,最多就只有这么多个元素了。那么套用 webscraper 的「滚动到底部」就只能获取这么多个微博而已了。
Automa 也是一个 chrome 的扩展,相对于 webscraper 只用来做爬虫,automa 可以用来做各种流程自动化的东西,比 webscraper 灵活不少。除此之外,很多思路和 webscraper 一脉相承。简单看了看教程我就做出来如下一个流程:
其中的 javascript code
内容如下:
function inViewport (element) {
if (!element) return false;
if (1 !== element.nodeType) return false;
var html = document.documentElement;
var rect = element.getBoundingClientRect();
return !!rect &&
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.left <= html.clientWidth &&
rect.top <= html.clientHeight;
}
setTimeout(() => {
var elements = document.querySelectorAll("article");
elements.forEach(e => {
if (inViewport(e)) {
const text = e.querySelector('.detail_wbtext_4CRf9').innerText;
console.log(text);
automaNextBlock({ text: text }, true);
}
});
}, 1000);
和 webscraper 一直滚动到满意的个数的元素后再开始解析数据不同,我做的 automa 的流程是每次滚动一点点页面,然后就获取当前视图中的微博元素并把其内容存下来。而获取当前视图的元素就是用的上面的 javascript code
了。
Automa 相对 webscraper 来说更加灵活,可以更加灵活的定制自己的抓取流程,后续可能还会有其他场景的使用吧。