我想爬取页面并检查相应页面中的超链接,并关注这些超链接并从页面中捕获数据
12 回答
一般来说,浏览器 JavaScript 只能在其源域内进行爬取,因为获取页面将通过受Same-Origin Policy限制的Ajax完成。
如果运行爬虫脚本的页面位于www.example.com上,则该脚本可以爬取 www.example.com 上的所有页面,但不能爬取任何其他来源的页面(除非适用某些边缘情况,例如Access-为其他服务器上的页面设置了Control-Allow-Origin标头)。
如果你真的想在浏览器 JS 中编写一个全功能的爬虫,你可以编写一个浏览器扩展:例如,Chrome 扩展是打包的具有特殊权限的 Web 应用程序运行,包括跨域 Ajax。这种方法的困难在于,如果要支持多个浏览器,就必须编写多个版本的爬虫。(如果爬虫仅供个人使用,那可能不是问题。)
如果您使用服务器端 javascript,这是可能的。你应该看看node.js
可以在下面的链接中找到爬虫的示例:
http://www.colourcoding.net/blog/archive/2010/11/20/a-node.js-web-spider.aspx
我们可以借助 headless webkit 从服务器端使用 Javascript 抓取页面。对于爬虫,我们很少有像 PhantomJS、CasperJS 这样的库,还有一个新的 PhantomJS 包装器,称为 Nightmare JS,它使工作更容易。
谷歌的 Chrome 团队于 2017 年 8 月发布了 puppeteer,这是一个节点库,为无头和非无头 Chrome 提供高级 API(无头 Chrome从 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 从另一个请求文件。只是要小心那些。如果您不小心,这些可能会被第 3 方劫持并用作公共代理。
祝你好运,也许你像我一样在这个过程中结交一两个朋友:-)
我的典型设置是使用具有跨源权限集的浏览器扩展,它同时注入爬虫代码和 jQuery。
对 Javascript 爬虫的另一种看法是使用无头浏览器,如 phantomJS 或 casperJS(增强 phantom 的能力)
这就是你需要的http://zugravu.com/products/web-crawler-spider-scraping-javascript-regular-expression-nodejs-mongodb 他们使用 NodeJS、MongoDB 和 ExtJs 作为 GUI
对的,这是可能的
- 使用 NODEJS(它的服务器端 JS)
- nodeJS 中有 NPM(处理 3rd 方模块的包管理器)
- 在NodeJS中使用PhantomJS(可以爬取网站的第三方模块是PhantomJS)
您可以创建一个从远程 json 文件驱动的网络爬虫,该文件会在每个选项卡加载后立即在新选项卡中打开页面中的所有链接,除了已经打开的链接。如果您设置一个在基本浏览器中运行的浏览器扩展程序(除了 Web 浏览器和 Internet 配置程序之外什么都不运行),并将其运送并安装在具有良好 Internet 的地方,您可以使用旧计算机创建网页数据库。那只需要检索每个选项卡的内容。与大多数对搜索引擎成本的估计相反,你可以花大约 2000 美元来做到这一点。您只需要基本上让您的算法根据页面的 innerText 属性中出现的术语数量、关键字和描述来提供页面。您还可以设置另一台 PC 从一次性数据库中重新抓取旧页面并添加更多内容。我'
我在 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 网络爬虫。这应该使您走上正确的轨道。
对此有一种客户端方法,使用 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/ *
然后为每个产品页面编写一个脚本来提取数据并调用 web 服务传递数据和关闭窗口等。
Axios + Cheerio
您可以使用 axios 和cheerios 来做到这一点。检查axios 文档的响应格式。
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);
});
节点获取 + Cheerio
你可以用 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);
});