如何使用 JavaScript 从另一台服务器获取数据?

How to get data with JavaScript from another server?

提问人:user46665 提问时间:2/23/2009 最后编辑:DRosenfelduser46665 更新时间:7/20/2019 访问量:71448

问:

如何在用户浏览器中使用 JavaScript 向其他服务器发出请求(即从任何所需的服务器获取页面)?对于像 XMLHttpRequest 这样的方法,有一些限制可以防止这种情况,有没有办法绕过它们或其他方法?

这是一个普遍的问题,具体来说,我想检查一系列随机网站,看看它们是否包含某个元素,所以我需要一个网站的HTML内容,而无需下载任何额外的文件;所有这些都在 JavaScript 文件中,服务器上没有任何转发或代理机制

(注意:一种方法是使用 Greasemonkey 及其GM_xmlhttpRequest。

JavaScript 跨域

评论

3赞 rfunduk 2/24/2009
你需要服务器端代码来做到这一点,跨域请求是一个安全漏洞,不仅要绕过这种情况非常困难,而且你真的不应该这样做。使用像 PHP 这样的简单后端,甚至是像 Sinatra 这样的东西。

答:

25赞 Sampson 2/23/2009 #1

您应该查看 jQuery。它具有丰富的 AJAX 功能基础,可以为您提供完成所有这些操作的能力。您可以加载外部页面,并使用类似 CSS 的直观选择器解析其 HTML 内容。

使用$.get();

$.get("anotherPage.html", {}, function(results){
  alert(results); // will show the HTML from anotherPage.html
  alert($(results).find("div.scores").html()); // show "scores" div in results
});

对于外部域,我不得不编写一个本地PHP脚本,该脚本将充当中间人。jQuery将调用本地PHP脚本,传入另一个服务器的URL作为参数,本地PHP脚本将收集数据,jQuery将从本地PHP脚本中读取数据。

$.get("middleman.php", {"site":"http://www.google.com"}, function(results){
  alert(results); // middleman gives Google's HTML to jQuery
});

中间人 .php 一些东西,类似于

<?php

  // Do not use as-is, this is only an example.
  // $_GET["site"] set by jQuery as "http://www.google.com"
  print file_get_contents($_GET["site"]);

?>

评论

0赞 Sampson 2/23/2009
@mmattax,检查我的最后一段。
0赞 user46665 2/24/2009
您提到了“在某些情况下”——其他情况是什么?(注意:我已经更新了问题以排除中间人服务器脚本。
2赞 Sampson 2/24/2009
@petersidor,某些网站不允许来自其他域的 javascript 有任何访问权限。因此,您需要合并 file_get_contents() 或其他类似方法来获取它们的 HTML。
0赞 Crescent Fresh 2/24/2009
@Jonathan:更正,任何网站都不会允许来自其他 [顶级] 域的 JavaScript 访问。
0赞 user46665 2/24/2009
对于一般问题来说,这似乎是一个可以接受的解决方案,所以我投了赞成票;不幸的是,它并没有完全涵盖我的具体问题,因此我无法将其标记为最终解决方案。
0赞 zihotki 2/23/2009 #2

为此,您需要在服务器上编写代理。所有请求都将发送到您的服务器,然后您的服务器将加载 html 并将其发送回客户端。而且没有好的方法可以仅通过 javascript 来实现这一点。
jQuery 包含使用 XmlHttpRequest 加载 JSON 数据或外部脚本的功能,但此功能不能用于 html 页面。您也可以查看jQuery邮件列表的此线程

3赞 mmattax 2/23/2009 #3

编写一个代理脚本,从您的域转发 http 请求,这将绕过 XMLHttpRequest 限制。

如果您使用的是 PHP,只需使用 cURL 来请求和读取页面,然后只需吐出 html,就好像它来自您的域一样。

1赞 Chepech 2/24/2009 #4

您还可以使用 iframe 来模拟 ajax 请求。这样可以省去为前端问题编写后端解决方案的麻烦。下面是一个示例:

function setUploadEvent(typeComponet){
       var eventType = "";
       var iframe = document.getElementById("iframeId");
       try{
           /* for Mozilla / Opera9 */
           if (/(?!.*?compatible|.*?webkit)^mozilla|opera/i.test(navigator.userAgent)) {
                eventType = "onload";
           }else{
           /* IE  */
                eventType = "onreadystatechange";
           }

           iframe[eventType] = function(){
                var doc = iframe.contentDocument || iframe.contentWindow.document;
                var response = doc.body.innerHTML; /* or what ever content you are looking for */
             }
           }
       catch(e){
           alert("Error loading content")}
       } 

这应该可以解决问题。请注意,浏览器检测线不是最干净的,您绝对应该使用所有最常见的 JS 框架(Prototype、JQuery 等)中提供的行

评论

0赞 user46665 2/24/2009
现在,这看起来更像是它 - 将尝试一下并报告,已经投票了。它可能看起来很粗糙,但有时,越简单越好。:)
0赞 user46665 3/2/2009
试过了;不幸的是,浏览器不会授予从其他服务器访问具有网站的 iframe 属性的权限。因此,这基本上与XMLHttpRequest的问题相同,因此,似乎我的问题是不可能的。
0赞 Kristoffer Bohmann 1/21/2010 #5

<script language=“JavaScript” type=“text/javascript” src=“http://www.example.com/hello.js”></script>

将数据作为数组、JSON 或类似内容添加到 hello.js 中。例: var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

从另一台服务器获取 JavaScript 并不简单。:-)

评论

0赞 user46665 1/21/2010
:)Wanted 是一种使用 JavaScript 脚本从另一台服务器获取数据的方法,但它很有趣。:)
0赞 Kristoffer Bohmann 1/22/2010
请参阅我关于如何向外部 JavaScript 添加数据的更新。
0赞 user46665 1/25/2010
抱歉,我的问题不清楚,我已经更新了它 - 目的是从服务器获取数据 - 就像整个 HTML 页面一样,并使用在用户浏览器中运行的 JavaScript 访问它。
5赞 ewwink 5/30/2011 #6

2018年更新:

您只能在满足以下 4 个条件的情况下进行跨域访问

  • 在响应标头中具有Access-Control-Allow-Origin: *

演示

$.ajax({
  url: 'https://api.myjson.com/bins/bq6eu',
  success: function(response){
    console.log(response.string);
  },
  error: function(response){
    console.log('server error');
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

  • 使用服务器作为目标的桥接器或代理

演示:

$.ajax({
  url: 'https://cors-anywhere.herokuapp.com/http://whatismyip.akamai.com/',
  success: function(response){
    console.log('server IP: ' + response);
  },
  error: function(response){
    console.log('bridge server error');
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

  • 使用浏览器插件启用Allow-Control-Allow-Origin: *
  • 禁用浏览器 Web 安全性

chrome.exe --args --disable-web-security

火狐浏览器

about:config -> security.fileuri.strict_origin_policy -> false

结束


菜鸟旧答案 2011

$.get();可以从 jsbin.com 获取数据,但我不知道为什么它不能从其他站点获取数据,例如 google.com

$.get('http://jsbin.com/ufotu5', {},
  function(results){  alert(results); 
});

演示:http://jsfiddle.net/Xj234/ Firefox、Chrome 和 Safari 上进行了测试。

3赞 GitaarLAB 3/8/2013 #7

这很容易......如果你知道“秘密”技巧,几乎没有人分享..

它被称为雅虎yql...

因此,为了重新获得“用户的权力”(并回到方便的口头禅:“永远不要接受不”),只需使用 http://query.yahooapis.com/(而不是php?代理服务器端脚本)。
严格来说,jQuery并不是必需的。

示例 1:
使用类似 SQL 的命令:

select * from html 
where url="http://stackoverflow.com" 
and xpath='//div/h3/a'

以下链接将抓取 SO 以获取最新问题(绕过跨域安全 bull$#!7):
http://query.yahooapis.com/v1/public/yql?q=select%20title%20from%20html%20where%20url%3D%22http%3A%2F%2Fstackoverflow.com%22%20and%0A%20%20%20%20%20%20xpath%3D%27%2F%2Fdiv%2Fh3%2Fa%27%0A%20%20%20%20&format=json&callback=cbfunc

如您所见,这将返回一个 JSON 数组(也可以选择 xml)并调用 callback-function: 。cbfunc

事实上,作为“奖励”,每次不需要从“标签汤”中正则表达式数据时,您都可以保存一只小猫

你有没有听到你内心的小疯狂科学家开始咯咯笑?

然后查看此答案以获取更多信息(不要忘记它的评论以获取更多示例)。

祝你好运!

评论

1赞 Nathan 4/6/2020
这现已停用;查看 stackoverflow.com/questions/54046823/...
0赞 GniK KinG 8/8/2013 #8

非常感谢,这真的是一个很好的技巧。我是这样做的:

测试.html

<!DOCTYPE html>
<html>
<head>
<script>
function loadXMLDoc()
{
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","sp.php",true);
xmlhttp.send();
}
</script>
</head>
<body>

<h2>Using the XMLHttpRequest object</h2>
<div id="myDiv"></div>
<button type="button" onclick="loadXMLDoc()">Change Content</button>

</body>
</html>

sp.php

<?php
  print file_get_contents("http://your.url.com/you-can-use-cross-domain");
?>