Python 网页在它之后抓取一页';s加载了它的数据
试图为学校项目收集图书价格波动的数据。我正在使用Python从图书回购聚合器(在本例中为BookCouter)中获取数据,但我发现,由于站点必须加载数据,因此通过urllib2包获取源代码会在加载数据之前为我提供源代码。加载数据后如何从中提取Python 网页在它之后抓取一页';s加载了它的数据,python,web-scraping,Python,Web Scraping,试图为学校项目收集图书价格波动的数据。我正在使用Python从图书回购聚合器(在本例中为BookCouter)中获取数据,但我发现,由于站点必须加载数据,因此通过urllib2包获取源代码会在加载数据之前为我提供源代码。加载数据后如何从中提取 示例:您不能仅使用Python进行此操作。您需要一个JavaScript引擎API,如 使用Phantom,可以非常轻松地设置所有页面内容的web抓取,静态和动态JavaScript内容(如您案例中的Ajax调用结果)。事实上,您可以向页面解析器注册页面事
示例:您不能仅使用Python进行此操作。您需要一个JavaScript引擎API,如 使用Phantom,可以非常轻松地设置所有页面内容的web抓取,静态和动态JavaScript内容(如您案例中的Ajax调用结果)。事实上,您可以向页面解析器注册页面事件处理程序,如(这是node.js+phantom.js示例) 在这一点上,您可以完全控制正在发生的事情,以及您必须在页面中下载的时间,如:
var onResourceError = function(resourceError) {
var errorReason = resourceError.errorString;
var errorPageUrl = resourceError.url;
}
var onResourceRequested = function (request) {
var msg = ' request: ' + JSON.stringify(request, undefined, 4);
};
var onResourceReceived = function(response) {
var msg = ' id: ' + response.id + ', stage: "' + response.stage + '", response: ' + JSON.stringify(response);
};
var onNavigationRequested = function(url, type, willNavigate, main) {
var msg = ' destination_url: ' + url;
msg += ' type (cause): ' + type;
msg += ' will navigate: ' + willNavigate;
msg += ' from page\'s main frame: ' + main;
};
page.onResourceRequested(
function(requestData, request) {
//request.abort()
//request.changeUrl(url)
//request.setHeader(key,value)
var msg = ' request: ' + JSON.stringify(request, undefined, 4);
//console.log( msg )
},
function(requestData) {
//console.log(requestData.url)
})
PageHelper.registerHandlers(page,
{
onLoadStarted : onLoadStarted,
onLoadFinished: onLoadFinished,
onError : null, // onError THIS HANDLER CRASHES PHANTOM-NODE
onResourceRequested : null, // MUST BE ON PAGE OBJECT
onResourceReceived : onResourceReceived,
onNavigationRequested : onNavigationRequested,
onResourceError : onResourceError
});
正如您所看到的,您可以定义页面处理程序并控制该页面上加载的流和资源。因此,在获取整个页面源代码之前,您可以确保所有数据都已准备就绪并已设置,如:
var Parser = {
parse : function(page) {
var onSuccess = function (page) { // page loaded
var pageContents=page.evaluate(function() {
return document.body.innerText;
});
}
var onError = function (page,elapsed) { // error
}
page.evaluate(function(func) {
return func(document);
}, function(dom) {
return true;
});
}
} // Parser
在这里,您可以看到onSuccess回调中加载的整个页面内容:
var pageContents=page.evaluate(function() {
return document.body.innerText;
});
该页面直接来自Phantomjs,如以下代码片段所示:
phantom.create(function (ph) {
ph.createPage(function (page) {
Parser.parse(page)
})
},options)
当然,这是为了让您了解node.js+Phantomjs可以做什么,它们结合在一起时非常强大
您可以在Python环境中运行phantomjs,就像
try:
output = ''
for result in runProcess([self.runProcess,
self.runScript,
self.jobId,
self.protocol,
self.hostname,
self.queryString]):
output += '' + result
print output
except Exception as e:
print e
print(traceback.format_exc())
使用子流程Popen执行二进制文件的位置:
def runProcess(exe):
p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while(True):
retcode = p.poll() #returns None while subprocess is running
line = p.stdout.readline()
yield line
if(retcode is not None):
break
当然,在本例中要运行的进程是node.js
self.runProcess='node'
使用所需的参数作为参数。挑战在于一旦数据被web浏览器呈现,就要读取数据,这需要一些额外的技巧。如果您可以查看站点是否具有预渲染版本*或API 对你需要做的事情有一个很好的分解。但可以总结为:
*小咆哮——我很生气,因为我希望得到一个静态网页的预渲染版本。答案总是很美。虽然答案很长,很有趣,但根本不能回答提问者的问题。使用Python有很多方法可以做到这一点,我不建议您使用Python(我是一个有经验的Python开发人员)。Phantomjs(用C++编写)是顶级公司使用的真实Javascript引擎。这是我的2美分()。然后你决定。我会建议使用另一个python web解析器,但不是,我认为这不是最好的答案。但是问题是“我如何用Python做X?”,而X在Python中是可能的,所以不要只回答“不要,用另一种语言就行了。”@legostrmtroopr我不同意。1) 它回答了这样一个事实,即该解决方案在考虑客户端JavaScript VM机器代码执行的情况下呈现整个页面。2) 然后显示要处理哪些事件来实现这一点。3) 它显示了phantomjs如何获取网页、传递到解析器对象页面、注册回调并在正确的时间获取页面内容。@Legostrmtropr是的,但我的答案是。不,忘记python,选择一个更好的解决方案,在我看来,这是一个正确的答案,因为它实现了相同的结果。不管怎样,请随意否决,我也理解你的观点。
self.runProcess='node'