如何使用XMLHttpRequest在后台下载HTML页面并从中提取文本元素?

时间:2014-11-05 19:19:34

标签: javascript xmlhttprequest cross-domain greasemonkey tampermonkey

我想创建一个Greasemonkey脚本,当您在URL_1中时,脚本会在后台解析URL_2的整个HTML网页,以便从中提取文本元素。

具体来说,我想在后台下载整个页面的HTML代码(烂番茄页面)并将其存储在变量中,然后使用getElementsByClassName[0]来提取我希望从类名为“critic_consensus”的元素中获取的文本。


我在MDN中找到了这个:HTML in XMLHttpRequest所以,我最终在这个不幸的非工作代码中结束了:

var xhr = new XMLHttpRequest();
xhr.onload = function() {
  alert(this.responseXML.getElementsByClassName(critic_consensus)[0].innerHTML);
}
xhr.open("GET", "http://www.rottentomatoes.com/m/godfather/",true);
xhr.responseType = "document";
xhr.send();

当我在Firefox Scratchpad中运行它时显示此错误消息:

  

阻止跨源请求:同源策略禁止读取   http://www.rottentomatoes.com/m/godfather/处的远程资源。   这可以通过将资源移动到同一个域来修复   启用CORS。


PS。我不使用烂番茄API的原因是they've removed the critics consensus from it

3 个答案:

答案 0 :(得分:4)

对于跨源请求,如果获取的站点没有帮助设置许可CORS policy,则Greasemonkey提供the GM_xmlhttpRequest() function。 (大多数其他用户脚本引擎也提供此功能。)

GM_xmlhttpRequest明确设计为允许跨源请求。

要获取目标信息,请在结果上创建DOMParser。不要使用jQuery方法,因为这会导致无关的图像,脚本和对象加载,减慢速度或崩溃页面。

这里有一个完整的脚本,用于说明该过程:

// ==UserScript==
// @name        _Parse Ajax Response for specific nodes
// @include     http://stackoverflow.com/questions/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant       GM_xmlhttpRequest
// ==/UserScript==

GM_xmlhttpRequest ( {
    method: "GET",
    url:    "http://www.rottentomatoes.com/m/godfather/",
    onload: function (response) {
        var parser  = new DOMParser ();
        /* IMPORTANT!
            1) For Chrome, see
            https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#DOMParser_HTML_extension_for_other_browsers
            for a work-around.

            2) jQuery.parseHTML() and similar are bad because it causes images, etc., to be loaded.
        */
        var doc         = parser.parseFromString (response.responseText, "text/html");
        var criticTxt   = doc.getElementsByClassName ("critic_consensus")[0].textContent;

        $("body").prepend ('<h1>' + criticTxt + '</h1>');
    },
    onerror: function (e) {
        console.error ('**** error ', e);
    },
    onabort: function (e) {
        console.error ('**** abort ', e);
    },
    ontimeout: function (e) {
        console.error ('**** timeout ', e);
    }
} );

答案 1 :(得分:0)

问题是:XMLHttpRequest无法加载http://www.rottentomatoes.com/m/godfather/。 No&#39; Access-Control-Allow-Origin&#39;标头出现在请求的资源上。

由于您不是资源的所有者,因此无法设置此标头。

您可以做的是在heroku上设置代理,代理对rottentomatoes网站的所有请求 这是一个小node.js代理https://gist.github.com/igorbarinov/a970cdaf5fc9451f8d34

var https = require('https'),
    http  = require('http'),
    util  = require('util'),
    path  = require('path'),
    fs    = require('fs'),
    colors = require('colors'),
    url = require('url'),
    httpProxy = require('http-proxy'),
    dotenv = require('dotenv');

dotenv.load();

var proxy = httpProxy.createProxyServer({});
var host = "www.rottentomatoes.com";
var port = Number(process.env.PORT || 5000);

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

var server = require('http').createServer(function(req, res) {
    // You can define here your custom logic to handle the request
    // and then proxy the request.
    var path = url.parse(req.url, true).path;

    req.headers.host = host;
res.setHeader("Access-Control-Allow-Origin", "*");
    proxy.web(req, res, {
        target: "http://"+host+path,

    });

}).listen(port);

proxy.on('proxyRes', function (res) {
    console.log('RAW Response from the target', JSON.stringify(res.headers, true, 2));
});


util.puts('Proxying to '+ host +'. Server'.blue + ' started '.green.bold + 'on port '.blue + port);

我为此修改了https://github.com/massive/firebase-proxy/代码

我在http://peaceful-cove-8072.herokuapp.com/http://peaceful-cove-8072.herokuapp.com/m/godfather上发布了代理,您可以对其进行测试

这是测试http://jsfiddle.net/uuw8nryy/

的要点
var xhr = new XMLHttpRequest();
xhr.onload = function() {
  alert(this.responseXML.getElementsByClassName(critic_consensus)[0]);
}
xhr.open("GET", "http://peaceful-cove-8072.herokuapp.com/m/godfather",true);
xhr.responseType = "document";
xhr.send();

答案 2 :(得分:-1)

JavaScript same origin policy阻止您访问属于其他域的内容。

上述参考文献还为您提供了四种放宽此规则的技术(CORS就是其中之一)。