使用Node.js实时抓取网页

66
使用Node.js爬取网站内容的好方法是什么?我想构建一个非常快速的东西,可以以kayak.com的方式执行搜索,其中一个查询被分派到几个不同的站点,结果被爬取,并在可用时返回给客户端。
假设此脚本应仅以JSON格式提供结果,我们可以直接在浏览器中或在另一个Web应用程序中处理它们。
一些起点: 使用node.js和jquery来爬取网站 有人有任何想法吗?

我觉得你提供的第二个链接已经回答了你自己的问题。 - Brandon Boone
19
作为node.io的作者,我可以保证这一点 ;) - chriso
这回答解决了您的问题吗?如何使用node.js抓取动态内容的网页? - ggorlen
9个回答

24

Node.io 似乎是当之无愧的冠军 :-)


15
作为作者,我可以保证 node.io 的可靠性。 - chriso
3
Node.io不再得到维护,已经停止更新,原域名已被出售。这个答案已经过时了。 - Evan Carroll

5
所有上述解决方案都假定在本地运行爬虫。这意味着您的性能将受到严重限制(因为它们是按顺序或在有限的一组线程中运行)。我认为更好的方法是依赖于现有的,尽管是商业的,爬取网格。
以下是一个示例:
var bobik = new Bobik("YOUR_AUTH_TOKEN");
bobik.scrape({
  urls: ['amazon.com', 'zynga.com', 'http://finance.google.com/', 'http://shopping.yahoo.com'],
  queries:  ["//th", "//img/@src", "return document.title", "return $('script').length", "#logo", ".logo"]
}, function (scraped_data) {
  if (!scraped_data) {
    console.log("Data is unavailable");
    return;
  }
  var scraped_urls = Object.keys(scraped_data);
  for (var url in scraped_urls)
    console.log("Results from " + url + ": " + scraped_data[scraped_urls[url]]);
});

在这里,远程执行抓取并且只有当结果准备好时才会向您的代码发出回调(也有一种选项可以在结果可用时收集结果)。
您可以在 https://github.com/emirkin/bobik_javascript_sdk 下载 Bobik客户端代理SDK

2
我已经进行了自己的研究,https://npmjs.org/package/wscraper 自称为基于 cheerio.js 的网页爬虫代理,是一个快速、灵活和精简的核心 jQuery 实现;构建在 request.js 之上;受 http-agent.js 启发。据 npmjs.org 数据显示,使用率非常低,但对任何感兴趣的人来说都值得一看。

1

使用ES7 / promises的新方法

通常在爬取信息时,您需要使用某种方法来:

  1. 获取Web服务器上的资源(通常是HTML文档)
  2. 将该资源读取并作为以下内容进行处理:
    1. DOM /树结构,并使其可导航
    2. 使用类似SAS的东西将其解析为令牌文档。

树和令牌解析都有优点,但树通常更简单。我们将使用它。请查看request-promise,以下是其工作原理:

const rp = require('request-promise');
const cheerio = require('cheerio'); // Basically jQuery for node.js 

const options = {
    uri: 'http://www.google.com',
    transform: function (body) {
        return cheerio.load(body);
    }
};

rp(options)
    .then(function ($) {
        // Process html like you would with jQuery... 
    })
    .catch(function (err) {
        // Crawling failed or Cheerio 

这里使用的是 cheerio,它是一种轻量级的类似于 jQuery 的服务器端库(不需要 window 对象或 jsdom)。
由于使用了 promises,您还可以以异步函数的形式编写代码。它看起来像同步代码,但实际上是 ES7 异步的:
async function parseDocument() {
    let $;
    try {
      $ = await rp(options);
    } catch (err) { console.error(err); }

    console.log( $('title').text() ); // prints just the text in the <title>
}

1

你并不总是需要使用jQuery。例如,如果你玩弄jsdom返回的DOM,你可以轻松地自己获取所需内容(同时也不必担心跨浏览器问题)。参见:https://gist.github.com/1335009 这并不是要否定node.io的作用,只是说你可能可以根据情况自己完成...


0
我认为这有两个不同的问题。
1. "我想要构建一个非常非常快的东西,可以在几个不同的网站上执行搜索..." 要做任何快速的事情,尤其是多个任务(因为你想要爬取多个网站),我建议学习 "Node.js 中的多线程编程"。也许 DigitalOcean 上的这篇文章可以帮到你:如何在 Node.js 中使用多线程编程
2. 其次,关于使用 Node.js 进行爬虫。这取决于你想要爬取的网站,如果它们是 "静态/服务器渲染" 的,那么你可以使用 Cheerio 将 HTML 结果解析为结构化的格式。如果是 "JavaScript 渲染的网站",那么你必须使用像 Puppeteer 这样的工具来模拟真实访问者的某些操作。你可以阅读这篇文章,它强调了使用 Puppeteer VS Cheerio 在 JavaScript 中爬取网站的区别:使用 Puppeteer VS Cheerio 在 JavaScript 中爬取网站。希望对你有所帮助!
另外一个我应该提到的技巧是查看网站使用的外部脚本,有时你要找的数据可能就在那里!
我以前从未在Javascript上运行过多线程任务,但这似乎是完全有可能的!

0

请查看https://github.com/rc0x03/node-promise-parser

Fast: uses libxml C bindings
Lightweight: no dependencies like jQuery, cheerio, or jsdom
Clean: promise based interface- no more nested callbacks
Flexible: supports both CSS and XPath selectors

0

这是我编写的基于Node.JS的易于使用但拼写不佳的通用 爬虫https://github.com/harish2704/html-scraper。 它可以根据预定义的模式提取信息。 模式定义包括CSS选择器和数据提取函数。 当前使用Cheerio进行DOM解析。


0

我看到大多数答案都使用了正确的方法,例如cheerio等,但是一旦你到达需要解析和执行JavaScript的点(例如SPA等),那么我建议查看https://github.com/joelgriffith/navalia(我是作者)。Navalia是专门构建用于支持在无头浏览器上下文中进行爬虫,而且速度相当快。谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接