专栏首页用CasperJS构建你的网络爬虫

用CasperJS构建你的网络爬虫

为应用程序收集数据有时候是一件困难和费力的事。一个急需的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的函数更加受限.

本文的版权归 FesonX 所有,如需转载请联系作者。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 内存数据网格主要特性简介

    将主存储器用作存储区域而不是使用磁盘是并不是一种全新的尝试。你可以在日常生活中发现许多使用主内存DBMS(数据库管理系统)(MMDB)执行比磁盘快得多的情况。一...

    FesonX
  • 在CentOS 6上使用Postfix,Dovecot和MySQL发送电子邮件

    Postfix 邮件传输代理(MTA)是一种高性能的开源电子邮件服务器系统。本指南将帮助你在CentOS 6 Linode上运行 Postfix,使用 Dove...

    FesonX
  • 在 Docker 中部署 Node.js 网络服务器

    Node.js 是服务器端的 JavaScript 包,通常用于各种云应用程序。Docker 是一个容器平台。使用 Docker,用户无需经过安装和配置即可下载...

    FesonX
  • 不同浏览器input file样式不一样

    2、判断浏览器类型,如果是非IE,则将页面上的input 设置为近乎透明,然后将图片放在上面。

    一笠风雨任生平
  • 不同浏览器input file样式不一样

    2、判断浏览器类型,如果是非IE,则将页面上的input 设置为近乎透明,然后将图片放在上面。

    一笠风雨任生平
  • JavaScript 10分钟入门

    简介 JavaScript是一门面向对象的动态语言,他一般用来处理以下任务: 1、修饰网页 生成HTML和CSS 生成动态HTML内容 生成一些特效 2、提供...

    前朝楚水
  • 深入理解JavaScript系列(37):设计模式之享元模式

    享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。

    用户4962466
  • js重修课[四]:函数

    函数有两种定义方法:定义表达式如var f = function(){};和声明语句如function f(){}。须知在变量提前这一现象中,声明语句可被提前,...

    星回
  • 原生js编写的安全色拾色器

    <html > <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8...

    欢醉
  • 【Golang语言社区--H5编程】smoke.js

    大家好,我是社区主编彬哥,今天给大家带来的H5游戏编程中,烟雾特效的js库; 源码如下 var smokemachine = function (c...

    李海彬

扫码关注云+社区

领取腾讯云代金券