使用 javascript (phantomjs) 导航/抓取 hashbang 链接
Posted
技术标签:
【中文标题】使用 javascript (phantomjs) 导航/抓取 hashbang 链接【英文标题】:Navigating / scraping hashbang links with javascript (phantomjs) 【发布时间】:2011-09-18 20:09:43 【问题描述】:我正在尝试下载几乎完全由 javascript 生成的网站的 html。所以,我需要模拟浏览器访问并一直在玩PhantomJS。问题是,该站点使用 hashbang URL,我似乎无法让 PhantomJS 处理 hashbang - 它只是不断调用主页。
该网站是http://www.regulations.gov。默认将您带到#!home。我尝试使用以下代码(来自 here)来尝试处理不同的 hashbang。
if (phantom.state.length === 0)
if (phantom.args.length === 0)
console.log('Usage: loadreg_1.js <some hash>');
phantom.exit();
var address = 'http://www.regulations.gov/';
console.log(address);
phantom.state = Date.now().toString();
phantom.open(address);
else
var hash = phantom.args[0];
document.location = hash;
console.log(document.location.hash);
var elapsed = Date.now() - new Date().setTime(phantom.state);
if (phantom.loadStatus === 'success')
if (!first_time)
var first_time = true;
if (!document.addEventListener)
console.log('Not SUPPORTED!');
phantom.render('result.png');
var markup = document.documentElement.innerHTML;
console.log(markup);
phantom.exit();
else
console.log('FAIL to load the address');
phantom.exit();
此代码生成正确的 hashbang(例如,我可以将 hash 设置为 '#!contactus'),但它不会动态生成任何不同的 HTML——只是默认页面。但是,当我调用 document.location.hash
时,它会正确输出。
我也尝试将初始地址设置为 hashbang,但是脚本只是挂起并且没有执行任何操作。例如,如果我将 url 设置为 http://www.regulations.gov/#!searchResults;rpp=10;po=0
,则脚本在将地址打印到终端后就会挂起,并且什么也没有发生。
【问题讨论】:
这与 Python 有什么关系? 好点 - 我不知道为什么我把那个标签放在那里。 我在windows上试过了。但很可能,我成功了。 @mattn -- 你能提供更多关于你做了什么以及它是否有效的信息吗? 我可以看到 result.png 是存在的。和 html 出现。我没有挂起。 【参考方案1】:这里的问题是页面的内容是异步加载的,但您希望它在页面加载后立即可用。
为了抓取异步加载内容的页面,您需要等待抓取,直到您感兴趣的内容加载完毕。根据页面的不同,可能有不同的检查方法,但最简单的方法是定期检查您希望看到的内容,直到找到为止。
这里的诀窍是弄清楚要查找的内容 - 您需要在加载所需内容之前不会出现在页面上的内容。在这种情况下,我为***页面找到的最简单的选项是手动输入您希望在每个页面上看到的 H1 标签,将它们键入哈希:
var titleMap =
'#!contactUs': 'Contact Us',
'#!aboutUs': 'About Us'
// etc for the other pages
;
然后在您的成功块中,您可以设置重复超时以在h1
标记中查找您想要的标题。当它出现时,你就知道你可以渲染页面了:
if (phantom.loadStatus === 'success')
// set a recurring timeout for 300 milliseconds
var timeoutId = window.setInterval(function ()
// check for title element you expect to see
var h1s = document.querySelectorAll('h1');
if (h1s)
// h1s is a node list, not an array, hence the
// weird syntax here
Array.prototype.forEach.call(h1s, function(h1)
if (h1.textContent.trim() === titleMap[hash])
// we found it!
console.log('Found H1: ' + h1.textContent.trim());
phantom.render('result.png');
console.log("Rendered image.");
// stop the cycle
window.clearInterval(timeoutId);
phantom.exit();
);
console.log('Found H1 tags, but not ' + titleMap[hash]);
console.log('No H1 tags found.');
, 300);
上面的代码对我有用。但是,如果您需要抓取搜索结果,它就行不通了 - 您需要找出可以查找的识别元素或文本,而无需提前知道标题。
编辑:另外,看起来newest version of PhantomJS 现在在获取新数据时会触发onResourceReceived
事件。我没有对此进行研究,但您也许可以将侦听器绑定到此事件以达到相同的效果。
【讨论】:
太棒了!搜索标头不起作用,但一个简单的超时就可以了。
以上是关于使用 javascript (phantomjs) 导航/抓取 hashbang 链接的主要内容,如果未能解决你的问题,请参考以下文章
在Selenium / PhantomJS上执行Javascript
如何在 PhantomJS 中使用 JavaScript 检测网页上的声音?