网页抓取基础知识
Web Scraping Basics
我要试一试网页抓取,因为我可以看到用它做很多有趣的事情的潜力。我花了几个小时研究我需要什么,我决定使用node.js与'request'和'cheerio'模块来执行抓取。
因此,对于第一个项目,我想我会尝试从这个随机句子生成器站点获取一个随机句子:http://watchout4snakes.com/wo4snakes/Random/RandomSentence
标记看起来相对简单,这里是我感兴趣的部分:
<div class="resultBox">
<table class="centeredResult">
<tbody><tr>
<td>
<span id="result">An amateur regret slights the lust outside his contentious century.</span>
</td>
</tr>
</tbody></table>
</div>
所以我想要的位在span中(显然它在实际页面的检查中会有所不同),我编写了以下Javascript文件并在node中运行:
var request = require("./node_modules/request/");
cheerio = require('./node_modules/cheerio/');
request('http://watchout4snakes.com/wo4snakes/Random/RandomSentence', function(err, resp, body){
if(!err && resp.statusCode == 200){
console.log("connected...'n");
var $ = cheerio.load(body);
console.log($('#result').html());
}
else console.log("Failed To Connect...");
});
我收到通知,所以我做了一些检查,并确定我已经正确地抓取了页面的数据。现在我要做的就是选择#result
ID字段中的文本。然而,我只是给了一个空白的空间,事实上,如果我让cheerio模块打印该区域的实际标记,我给了一个<span ID="result"></span>
里面没有随机的句子。
我最初的猜测是节点在随机句子脚本完成运行之前抓取标记。但我不知道怎么诊断,有谁有办法吗?
是的,您的直觉是正确的,因为请求模块在随机句子脚本完成运行之前抓取标记。如果你打印出body
,你会看到它包含:
<table class="centeredResult">
<tr>
<td>
<span id="result"></span>
</td>
</tr>
</table>
事实上,请求模块永远不会在获取的页面上执行任何JavaScript。
如果你需要JavaScript在你抓取的页面上运行,我建议你看看像phantomjs这样的无头浏览器,它可以让你通过JavaScript API与页面进行交互。
查看页面:
<script>
(function ($) {
$(document).ready(function () {
var options = {
target: '#result',
beforeSubmit: function () {
$('#result').empty();
$.fnWait();
},
success: function () {
$.unblockUI();
}
};
$('#frmSentence').ajaxForm(options)
.find('input[type=submit]')
.click();
});
})(jQuery);
看起来#evidence
span
正在被AJAX填充。当库加载页面时,它不会执行Javascript,因此不会加载引号。
这可能是最简单的,如果你只是尝试查询相同的页面,他们提取它。否则,您将需要使用一些东西来为您执行页面上的javascript,例如Selenium或类似的东西。
在浏览器中加载页面,并查看网络请求。您将看到,在cheerio停止加载DOM之后,语句被异步加载。有一个POST
到http://watchout4snakes.com/wo4snakes/Random/NewRandomSentence
返回一个纯文本字符串(内容类型:text/html;charset=utf-8),然后插入到DOM中。
我不知道cheerio,但你可以(a)使用计时器等待几秒钟,或(b)切换到wd有一个明确的等待的东西,这将触发一旦DOM元素已经加载。
在对我的脚本进行了一些修改之后,我最终得到了这样的结果:
var page = require('webpage').create();
console.log("connecting...");
page.open("http://watchout4snakes.com/wo4snakes/Random/RandomSentence", function(){
console.log('connected');
var content = page.content;
var phrase = page.evaluate(function() {
return document.getElementById("result").innerHTML;
});
console.log(phrase);
});
多亏了使用phantomjs的提示,看起来好像无头浏览器方法允许脚本在抓取HTML内容之前运行。然后使用page.evaluate()从页面中提取句子。
看起来好像Phantomjs在我的系统上有一些问题。没有一个进程在phantom.exit()上退出,根据谷歌搜索,这与Nvidia显卡驱动有关。此外,该脚本相当慢,因为它等待页面的所有元素加载连接可能需要长达10秒的时间,这对于迭代过程来说不是很好。但是我设法得到了这个句子,所以我会从这里开始,谢谢你的信息!
- 同源策略目的|用户数据与基本页面数据|客户端页面抓取
- JavaScript原型设计基础知识
- VBA正在抓取不在HTML源文件中的生成内容
- 尝试使用Node.js动态路由从IMDB中抓取电影内容.但是在我的output.json文件中没有定义
- 如何从网站上抓取链接和图片
- 用jquery抓取图像SRC-attr
- Javascript Regex-从价格中抓取分隔符
- 使用网络服务器的IP地址而不是域名对其进行屏幕抓取
- Javascript:如何从URL中抓取片段并将其写入一些PHP
- 使用htmlunit抓取动态网页
- 如何抓取URL的一部分并将其粘贴到页面上的某个位置
- Html抓取网站加载错误的J汤Java
- 如何获取网站所有页面的链接以进行数据抓取
- 如何使用AJAX和JSON从一个页面抓取PHP变量到另一个页面
- 我可以使用RubyonRails抓取URL的源代码吗?还是应该使用PHP
- 我如何从一个无限滚动的网站抓取图像,其中api是隐藏的,我无法通过使用Inspect Element获得它->网络
- 淘汰从选项中抓取类
- 在Python中抓取javascript渲染的文本的最快解决方案
- 什么是处理JavaScript的最简单的网络抓取工具
- 网页抓取基础知识