【发布时间】:2012-06-18 13:04:10
【问题描述】:
我想爬取页面并检查相应页面中的超链接,并跟踪这些超链接并从页面中捕获数据
【问题讨论】:
-
对于新访问者(2017 年之后)-> 从 Google 查看有关 Puppeteer 的答案
我想爬取页面并检查相应页面中的超链接,并跟踪这些超链接并从页面中捕获数据
【问题讨论】:
一般来说,浏览器 JavaScript 只能在其源域内进行爬取,因为获取页面将通过 Ajax 完成,而这受到 Same-Origin Policy 的限制。
如果运行爬虫脚本的页面位于 www.example.com 上,则该脚本可以爬取 www.example.com 上的所有页面,但不能爬取任何其他来源的页面(除非一些边缘情况适用,例如,Access-Control-Allow-Origin 标头是为另一台服务器上的页面设置的)。
如果你真的想在浏览器JS中编写一个功能齐全的爬虫,你可以编写一个浏览器扩展:例如,Chrome extensions是打包的Web应用程序以特殊权限运行,包括@987654325 @。这种方法的困难在于,如果要支持多个浏览器,就必须编写多个版本的爬虫。 (如果爬虫只是供个人使用,那可能不是问题。)
【讨论】:
如果您使用服务器端 javascript,这是可能的。 你应该看看 node.js
并且可以在下面的链接中找到爬虫的示例:
http://www.colourcoding.net/blog/archive/2010/11/20/a-node.js-web-spider.aspx
【讨论】:
我们可以借助无头 webkit 从服务器端使用 Javascript 抓取页面。对于爬虫,我们很少有像 PhantomJS、CasperJS 这样的库,还有一个新的 PhantomJS 包装器,称为 Nightmare JS,它使工作更容易。
【讨论】:
Google's Chrome team has released puppeteer,2017 年 8 月,一个节点库,为无头和非无头 Chrome 提供高级 API(无头 Chrome 可用 since 59)。
它使用 Chromium 的嵌入式版本,因此可以保证开箱即用。如果你想使用特定的 Chrome 版本,你可以通过启动 puppeteer 来实现,并以可执行路径作为参数,例如:
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
导航到网页并从中截取屏幕截图的示例显示了它是多么简单(取自 GitHub 页面):
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
【讨论】:
有一些方法可以规避 JS 的同源策略。我为 facebook 编写了一个爬虫,它从我的朋友和我朋友的朋友的 facebook 个人资料中收集信息,并允许按性别、当前位置、年龄、军事状态(你明白我的意思)过滤结果。这很简单。我只是从控制台运行它。这样,您的脚本将获得在当前域上执行请求的特权。您还可以制作一个小书签来从您的书签中运行脚本。
另一种方法是提供 PHP 代理。您的脚本将访问当前域上的代理并使用 PHP 从另一个请求文件。只是要小心那些。如果您不小心,这些可能会被第三方劫持并用作公共代理。
祝你好运,也许你会像我一样在这个过程中结交一两个朋友 :-)
【讨论】:
我的典型设置是使用带有跨域权限集的浏览器扩展,它同时注入爬虫代码和 jQuery。
对 Javascript 爬虫的另一种看法是使用无头浏览器,如 phantomJS 或 casperJS(增强 phantom 的能力)
【讨论】:
这就是你需要的http://zugravu.com/products/web-crawler-spider-scraping-javascript-regular-expression-nodejs-mongodb 他们使用 NodeJS、MongoDB 和 ExtJs 作为 GUI
【讨论】:
是的,有可能
【讨论】:
对此有一种客户端方法,使用 Firefox Greasemonkey 扩展。使用 Greasemonkey,您可以创建每次打开指定 url 时要执行的脚本。
这里是一个例子:
如果你有这样的网址:
http://www.example.com/products/pages/1
http://www.example.com/products/pages/2
然后你可以使用这样的东西来打开所有包含产品列表的页面(手动执行)
var j = 0;
for(var i=1;i<5;i++)
{
setTimeout(function(){
j = j + 1;
window.open('http://www.example.com/products/pages/ + j, '_blank');
}, 15000 * i);
}
然后您可以创建一个脚本以在每个产品列表页面的新窗口中打开所有产品,并将此 URL 包含在 Greasemonkey 中。
http://www.example.com/products/pages/*
然后是每个产品页面的脚本来提取数据并调用webservice传递数据和关闭窗口等等。
【讨论】:
我在 github 上做了一个示例 javascript 爬虫。
它是事件驱动的,并使用内存中的队列来存储所有资源(即 url)。
如何在你的节点环境中使用
var Crawler = require('../lib/crawler')
var crawler = new Crawler('http://www.someUrl.com');
// crawler.maxDepth = 4;
// crawler.crawlInterval = 10;
// crawler.maxListenerCurrency = 10;
// crawler.redisQueue = true;
crawler.start();
这里我只是向你展示 2 个 javascript 爬虫的核心方法。
Crawler.prototype.run = function() {
var crawler = this;
process.nextTick(() => {
//the run loop
crawler.crawlerIntervalId = setInterval(() => {
crawler.crawl();
}, crawler.crawlInterval);
//kick off first one
crawler.crawl();
});
crawler.running = true;
crawler.emit('start');
}
Crawler.prototype.crawl = function() {
var crawler = this;
if (crawler._openRequests >= crawler.maxListenerCurrency) return;
//go get the item
crawler.queue.oldestUnfetchedItem((err, queueItem, index) => {
if (queueItem) {
//got the item start the fetch
crawler.fetchQueueItem(queueItem, index);
} else if (crawler._openRequests === 0) {
crawler.queue.complete((err, completeCount) => {
if (err)
throw err;
crawler.queue.getLength((err, length) => {
if (err)
throw err;
if (length === completeCount) {
//no open Request, no unfetcheditem stop the crawler
crawler.emit("complete", completeCount);
clearInterval(crawler.crawlerIntervalId);
crawler.running = false;
}
});
});
}
});
};
这里是github链接https://github.com/bfwg/node-tinycrawler。 它是一个用 1000 行代码编写的 JavaScript 网络爬虫。 这应该会让你走上正轨。
【讨论】:
您可以创建一个从远程 json 文件驱动的网络爬虫,该文件会在每个选项卡加载后立即在新选项卡中打开页面中的所有链接,已打开的链接除外。如果您设置一个在基本浏览器中运行的浏览器扩展程序(除了 Web 浏览器和 Internet 配置程序之外什么都不运行),并将其运送并安装在具有良好 Internet 的地方,您可以使用旧计算机创建网页数据库。那只需要检索每个选项卡的内容。与大多数对搜索引擎成本的估计相反,你可以花大约 2000 美元来做到这一点。您只需要基本上让您的算法根据页面的 innerText 属性中出现的术语数量、关键字和描述来提供页面。您还可以设置另一台 PC 从一次性数据库中重新抓取旧页面并添加更多。我估计最多需要 3 个月和 20000 美元。
【讨论】:
您可以使用 axios 和 Cheerios 来做到这一点。检查axios docs 的响应格式。
const cheerio = require('cheerio');
const axios = require('axios');
//crawl
//get url
var url = 'http://amazon.com';
axios.get(url)
.then((res) => {
//response format
var body = res.data;
var statusCode = res.status;
var statusText = res.statusText;
var headers = res.headers;
var request = res.request;
var config = res.config;
//jquery
let $ = cheerio.load(body);
//example
//meta tags
var title = $('meta[name=title]').attr('content');
if(title == undefined || title == 'undefined'){
title = $('title').text();
}else{
title = title;
}
var description = $('meta[name=description]').attr('content');
var keywords = $('meta[name=keywords]').attr('content');
var author = $('meta[name=author]').attr('content');
var type = $('meta[http-equiv=content-type]').attr('content');
var favicon = $('link[rel="shortcut icon"]').attr('href');
}).catch(function (e) {
console.log(e);
});
您可以使用 node-fetch 和cheerio 做同样的事情。
fetch(url, {
method: "GET",
}).then(function(response){
//response
var html = response.text();
//return
return html;
})
.then(function(res) {
//response html
var html = res;
//jquery
let $ = cheerio.load(html);
//meta tags
var title = $('meta[name=title]').attr('content');
if(title == undefined || title == 'undefined'){
title = $('title').text();
}else{
title = title;
}
var description = $('meta[name=description]').attr('content');
var keywords = $('meta[name=keywords]').attr('content');
var author = $('meta[name=author]').attr('content');
var type = $('meta[http-equiv=content-type]').attr('content');
var favicon = $('link[rel="shortcut icon"]').attr('href');
})
.catch((error) => {
console.error('Error:', error);
});
【讨论】: