前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用CasperJS构建你的网络爬虫

用CasperJS构建你的网络爬虫

作者头像
FesonX
发布2018-05-31 16:36:00
1.9K0
发布2018-05-31 16:36:00

为应用程序收集数据有时候是一件困难和费力的事。一个急需的API可能会丢失,或者可能有太多的数据需要处理。有时候,只是有时候,你需要通过网络抓取信息。

不用说,这可以是一个合法的雷区,所以你应该确保在版权法的范围内。

有很多工具可以帮助你抓取内容,比如Import.io,但是有时候这些工具并不能让你一直顺利。或者,你只是和我一样好奇,想看看它真的有多容易。

挑战

让我们先从一个简单的挑战开始——一个网络爬虫,可以从Techmeme获得当天最热门的故事列表!

注意:我会在这里使用DZone,但我遇到了捕获页面的问题。稍后再详细介绍

设置你的机器

你需要先安装一些东西。假设你已经安装了Node.js(我的意思是,谁会没安装!)。即使我们没有直接使用PhantomJS,你仍然需要安装它。版本2.0.1现在可用 —— 你可以从网站下载,也可以使用homebrew软件或同等功能的软件包管理器。

如果你使用安装homebrew软件的Mac,则可以用以下命令安装PhantomJS

brew install phantomjs

下载完毕后,你需要以类似的方式安装CasperJS。你可以将CasperJS视为PhantomJS的伴侣。它实际上给你一个更简单的API来处理网页。虽然它就像PhantomJS一样,被设计用来测试网页,但是还有很多功能可以使它适用于抓取内容。

CasperJS允许我们用JavaScript编写我们的脚本。你可以测试它是否已正确安装,并且通过在终端键入casperjs测试它是否在你的安装路径(PATH)上。

编写你的脚本

接下来创建一个新的包含你脚本的JavaScript文件。在我的例子中,我将其命名为index.js。你需要做的第一件事是在你的代码中创建一个casper实例,但需要模块并传入一些基本参数

var casper = require("casper").create({
waitTimeout: 10000,
stepTimeout: 10000,
verbose: true,
pageSettings: {
webSecurityEnabled: false
},
    onWaitTimeout: function() {
          this.echo('** Wait-TimeOut **');
    },
    onStepTimeout: function() {
        this.echo('** Step-TimeOut **');
    }
});

上面的onWaitTimeout回调将在你等待某个元素可见时调用,例如点击一个按钮后,并且waitTimeout已超过限度。

现在你可以启动casper实例并将其指向我们要检查的页面。

casper.start();

casper.open("http://techmeme.com");

Casper使用承诺框架来帮助你以有序的方式运行所有内容。首先,你需要使用then函数。

casper.then(function() {
  //logic here
  // 函数逻辑
});
//start your script
//运行你的脚本
casper.run();

要让casper打开网页并运行你的逻辑,你需要调用run函数。

检查所需元素的网页

当抓取一个网页时,假设有一个特定的结构。在编写脚本之前,你已经查看了页面源代码,或者你可能会使用开发人员工具根据某些操作观察页面的变化。

所以,让我们从一个简单的逻辑开始吧。使用CasperJS断言系统在继续之前确保某个元素已经到位。如果元素不存在,脚本将会失败,但至少你会知道为什么。这种断言行为对于注意过去成功抓取的页面中的更改是非常重要的,但自上次查找以来可能会有新的结构。

如果你检查Techmeme首页上的元素,你会注意到最新消息部分位于id为 topcol1 的div上

让我们使用断言功能来确保此元素存在:

casper.then(function() {

this.test.assertExists("#topcol1");

如果元素不存在,测试(即我们的脚本)将会失败,否则它将继续。

你也可以使用waitForSelector函数以更详细的方式实现相同的结果:

this.waitForSelector("#topcol1",
    function pass () {
       console.log("Continue");
    },
    function fail () {
    	// 无法加载元素...出现错误
        this.die("Did not load element... something is wrong");
    }
);

使用这个函数的好处是它允许页面在执行之前加载元素并等待。你在初始配置中指定的waitTimeout将用于决定在发生故障前要等待多长时间。

注意:有时你可能无法使用CasperJS查找元素。要获取CasperJS可以看到的图片(字面意义上的!),请使用capture()函数来保存屏幕截图this.capture('screener.png');

从页面提取内容

接下来,我们来看看如何从这个页面找到标题,以及链接到这些文章。首先,找到包含你要查找的内容的元素。在我们的案例中,它是与第二类相关的div。

CasperJS附带一个评估(evaluate)函数,它允许你从页面内运行JavaScript,并且可以让该函数返回一个变量以供进一步处理。

如何编写这个JavaScript并没有什么特别之处。在本例中,你会注意到我使用的是普通的旧DOM方法而不是jQuery,不过如果你希望在evaluate函数中使用jQuery,则可以使用jQuery:

var links = this.evaluate(function(){
var results = []; 
var elts = document.getElementsByClassName("ii");
for(var i = 0; i < elts.length; i++){
var link = elts[i].getElementsByTagName("a")[0].getAttribute("href");
var headline = elts[i].firstChild.textContent;
results.push({link: link, headline: headline});
}
return results; 
});

如果你要在evaluate函数中使用console.log语句,那么它们将通过remote.message处理程序输出到你自己的控制台,如下一节所述。

评估完成后,结果将返回供你使用。你可以将它们写入文件系统,或者将它们打印到屏幕上:

console.log("There were "  + links.length + " stories");

for(var i = 0; i < links.length; i++){
console.log(links[i].headline);
}

这将带来像这样的输出:

爬取时捕获错误

有时候,你可能在执行的JavaScript中存在错误,或者你正在抓取的页面可能存在问题。在这些情况下,你可以捕获错误并使用'remote.message'和'page.error'事件将其打印到控制台

casper.on('remote.message', function(msg) {
this.echo('remote message caught: ' + msg);
});

casper.on('page.error', function(msg, trace) {
this.echo('Error: ' + msg, 'ERROR');
});

你还可以监控正在请求的资源以及使用resource.error和resource.received事件加载的资源:

casper.on('resource.error', function(msg) {
this.echo('resource error: ' + msg);
});

casper.on('resource.received', function(resource) {
    console.log(resource.url);
});

更多供了解的内容

这篇文章只能说明你可以用CasperJS做什么。该项目的文档是没有错误的,所以一定要检查一下API,看看你还能做什么。

在本系列的下一篇文章中,我将研究如何从网页下载图像,并且还将讨论如何使用CasperJS中内置的文件系统函数,这些函数比你将习惯使用来自Node.js的函数更加受限.

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 挑战
    • 设置你的机器
      • 编写你的脚本
        • 检查所需元素的网页
          • 从页面提取内容
            • 爬取时捕获错误
              • 更多供了解的内容
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档