【问题标题】:Can Javascript read the source of any web page?Javascript 可以读取任何网页的源代码吗?
【发布时间】:2010-10-15 09:34:34
【问题描述】:

我正在处理屏幕抓取,并希望检索特定页面的源代码。

如何使用 javascript 实现这一点?请帮帮我。

【问题讨论】:

  • Here is similar page you may get your answer因为它解决了我获取HTML页面来源stackoverflow.com/questions/1367587/javascript-page-source-code的问题
  • @mikenvck 当问题是关于 JavaScript 的时候,你为什么还要提到 PHP?下面的答案展示了如何使用 JavaScript 做到这一点。
  • 要获取链接的来源,您可能需要使用$.ajax 获取外部链接。这是解决方案 - stackoverflow.com/a/18447625/2657601
  • 没有一个答案是原生 Javascript,它们都是基于 jquery 的。
  • jQuery 是原生 JavaScript。它只是你可以从 jquery.com 而不是从 stackoverflow.com 复制的 JavaScript。

标签: javascript html


【解决方案1】:

简单的开始方式,试试jQuery

$("#links").load("/Main_Page #jq-p-Getting-Started li");

更多jQuery Docs

另一种以更加结构化的方式进行屏幕抓取的方法是使用YQL or Yahoo Query Language.,它将返回结构化为 JSON 或 xml 的抓取数据。
例如
让我们刮一下 stackoverflow.com

select * from html where url="http://stackoverflow.com"

会给你一个像这样的 JSON 数组(我选择了那个选项)

 "results": {
   "body": {
    "noscript": [
     {
      "div": {
       "id": "noscript-padding"
      }
     },
     {
      "div": {
       "id": "noscript-warning",
       "p": "Stack Overflow works best with JavaScript enabled"
      }
     }
    ],
    "div": [
     {
      "id": "notify-container"
     },
     {
      "div": [
       {
        "id": "header",
        "div": [
         {
          "id": "hlogo",
          "a": {
           "href": "/",
           "img": {
            "alt": "logo homepage",
            "height": "70",
            "src": "http://i.stackoverflow.com/Content/Img/stackoverflow-logo-250.png",
            "width": "250"
           }
……..

这样做的好处是您可以执行 projections 和 where 子句,最终让您获得结构化的抓取数据,只有数据您需要(最终线路上的带宽要少得多)
例如

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

会得到你

 "results": {
   "a": [
    {
     "href": "/questions/414690/iphone-simulator-port-for-windows-closed",
     "title": "Duplicate: Is any Windows simulator available to test iPhone application? as a hobbyist who cannot afford a mac, i set up a toolchain kit locally on cygwin to compile objecti … ",
     "content": "iphone\n                simulator port for windows [closed]"
    },
    {
     "href": "/questions/680867/how-to-redirect-the-web-page-in-flex-application",
     "title": "I have a button control ....i need another web page to be redirected while clicking that button .... how to do that ? Thanks ",
     "content": "How\n                to redirect the web page in flex application ?"
    },
…..

现在只得到我们做的问题

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

注意投影中的标题

 "results": {
   "a": [
    {
     "title": "I don't want the function to be entered simultaneously by multiple threads, neither do I want it to be entered again when it has not returned yet. Is there any approach to achieve … "
    },
    {
     "title": "I'm certain I'm doing something really obviously stupid, but I've been trying to figure it out for a few hours now and nothing is jumping out at me. I'm using a ModelForm so I can … "
    },
    {
     "title": "when i am going through my project in IE only its showing errors A runtime error has occurred Do you wish to debug? Line 768 Error:Expected')' Is this is regarding any script er … "
    },
    {
     "title": "I have a java batch file consisting of 4 execution steps written for analyzing any Java application. In one of the steps, I'm adding few libs in classpath that are needed for my co … "
    },
    {
……

一旦您编写查询,它就会为您生成一个 url

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'%2F%2Fdiv%2Fh3%2Fa'%0A%20%20%20%20&format=json&callback=cbfunc

在我们的例子中。

所以最终你最终会做这样的事情

var titleList = $.getJSON(theAboveUrl);

和它一起玩。

很漂亮,不是吗?

【讨论】:

  • 太棒了,尤其是暗示雅虎的穷人解决方案,它消除了对获取数据的代理的需要。谢谢!!我冒昧地修复了 query.yahooapis.com 的最后一个演示链接:它在 url 编码中缺少一个 % 符号。很酷,这仍然有效!
  • 知道如何从amazon.in/Xiaomi-Redmi-4A-Grey-16GB/dp/… 抓取图像和元描述吗?
  • query.yahooapis 已于 2019 年 1 月停用。看起来非常整洁,可惜我们现在不能使用它。在此处查看推文:twitter.com/ydn/status/1079785891558653952?ref_src=twsrc%5Etfw
【解决方案2】:

只要您通过域上的代理抓取您要访问的任何页面,就可以使用 Javascript:

<html>
<head>
<script src="/js/jquery-1.3.2.js"></script>
</head>
<body>
<script>
$.get("www.mydomain.com/?url=www.google.com", function(response) { 
    alert(response) 
});
</script>
</body>

【讨论】:

  • 为什么需要基于域的代理?
  • 因为同源策略
  • 这真的很有趣。大概需要在服务器上安装一些代码来实现这一点?
  • @ejbytes:实际上我认为 node.js 有一些模块。我假设 OP 想要进行网络抓取。
  • 你会得到一个'from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource。'如果您不在同一个域中
【解决方案3】:

您可以简单地使用 XmlHttp (AJAX) 来访问所需的 URL,来自该 URL 的 HTML 响应将在 responseText 属性中可用。如果不是同一个域,您的用户将收到一条浏览器警报,提示“此页面正在尝试访问不同的域。您要允许这样做吗?”

【讨论】:

  • 很遗憾,您不会收到任何警报,它只会阻止请求
【解决方案4】:

你可以使用fetch:

const URL = 'https://www.sap.com/belgique/index.html';
fetch(URL)
.then(res => res.text())
.then(text => {
    console.log(text);
})
.catch(err => console.log(err));

【讨论】:

    【解决方案5】:

    作为一项安全措施,Javascript 无法读取来自不同域的文件。虽然可能有一些奇怪的解决方法,但我会考虑使用不同的语言来完成这项任务。

    【讨论】:

      【解决方案6】:

      如果您绝对需要使用 javascript,您可以使用 ajax 请求加载页面源。

      请注意,使用 javascript,您只能检索与请求页面位于同一域下的页面。

      【讨论】:

        【解决方案7】:

        使用 jquery

        <html>
        <head>
        <script src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.js" ></script>
        </head>
        <body>
        <script>
        $.get("www.google.com", function(response) { alert(response) });
        </script>
        </body>
        

        【讨论】:

        【解决方案8】:

        我使用了ImportIO。如果您在他们那里设置了一个帐户(这是免费的),他们允许您从任何网站请求 HTML。他们让您每年最多可以提出 5 万个请求。我没有花时间去寻找替代方案,但我确信有一些替代方案。

        在您的 Javascript 中,您基本上只需发出这样的 GET 请求:

        var request = new XMLHttpRequest();
        
        request.onreadystatechange = function() {
          jsontext = request.responseText;
        
          alert(jsontext);
        }
        
        request.open("GET", "https://extraction.import.io/query/extractor/THE_PUBLIC_LINK_THEY_GIVE_YOU?_apikey=YOUR_KEY&url=YOUR_URL", true);
        
        request.send();

        旁注:我在研究我认为是同一个问题时发现了这个问题,因此其他人可能会觉得我的解决方案有帮助。

        更新:我创建了一个新的,他们只允许我使用不到 48 小时,然后他们说我必须为服务付费。如果您不付款,他们现在似乎很快就关闭了您的项目。我使用 NodeJS 和一个名为 NightmareJS 的库创建了自己的类似服务。您可以查看他们的教程here 并创建自己的网络抓取工具。这相对容易。我没有尝试将其设置为我可以向其发出请求的 API 或其他任何东西。

        【讨论】:

          【解决方案9】:

          您可以通过创建浏览器扩展程序甚至在 Windows(HTML 应用程序)中将文件另存为 .hta 来绕过同源策略。

          【讨论】:

            【解决方案10】:

            你可以生成一个 XmlHttpRequest 并请求页面,然后使用 getResponseText() 来获取内容。

            【讨论】:

              【解决方案11】:

              您可以使用FileReader API获取文件,选择文件时,将您网页的url放入选择框中。 使用此代码:

              function readFile() {
                  var f = document.getElementById("yourfileinput").files[0]; 
                  if (f) {
                    var r = new FileReader();
                    r.onload = function(e) { 
                      alert(r.result);
                    }
                    r.readAsText(f);
                  } else { 
                    alert("file could not be found")
                  }
                }
              }
              

              【讨论】:

                【解决方案12】:

                尽管有很多 cmets 相反,但我相信使用简单的 JavaScript 可以克服同源要求。

                我并没有声称以下内容是原创的,因为我相信我不久前在其他地方看到过类似的东西。

                我只在 Mac 上使用 Safari 对此进行了测试。

                以下演示在基本标记中获取页面,并将其 innerHTML 移动到新窗口。我的脚本添加了 html 标签,但对于大多数现代浏览器,这可以通过使用 outerHTML 来避免。

                <html>
                <head>
                <base href='http://apod.nasa.gov/apod/'>
                <title>test</title>
                <style>
                body { margin: 0 }
                textarea { outline: none; padding: 2em; width: 100%; height: 100% }
                </style>
                </head>
                <body onload="w=window.open('#'); x=document.getElementById('t'); a='<html>\n'; b='\n</html>'; setTimeout('x.innerHTML=a+w.document.documentElement.innerHTML+b; w.close()',2000)">
                <textarea id=t></textarea>
                </body>
                </html>
                

                【讨论】:

                • 我使用带有 webkit 补丁的 Safari 5.0.6 将其更新到与更新版本相当的版本。您使用的是哪个版本的 Safari,发生了什么?
                • 8.0.3.除了控制台中出现一些错误(我没有记住)之外,什么也没发生。
                • 您使用的是哪个 Safari 浏览器,错误究竟是什么?
                • 还是 8.0.3,如果你真的想让我重现测试用例:TypeError: undefined is not an object (evaluating 'w.document')
                • 对您所做的最有可能的解释是,您发现了一个安全漏洞,这要归功于您非常古老的浏览器和非官方补丁的某种组合。在大多数情况下,这没有实际用途。
                【解决方案13】:

                jquery 不是做事的方式。 用纯 JavaScript 做

                var r = new XMLHttpRequest();
                    r.open('GET', 'yahoo.comm', false);
                    r.send(null); 
                if (r.status == 200) { alert(r.responseText); }
                

                【讨论】:

                  【解决方案14】:
                  <script>
                      $.getJSON('http://www.whateverorigin.org/get?url=' + encodeURIComponent('hhttps://example.com/') + '&callback=?', function (data) {
                          alert(data.contents);
                      });
                  
                  </script>
                  

                  包含 jQuery 并使用此代码获取其他网站的 HTML。 将 example.com 替换为您的网站

                  此方法涉及外部服务器获取站点 HTML 并将其发送给您。 :)

                  【讨论】:

                    【解决方案15】:
                    javascript:alert("Inspect Element On");
                    javascript:document.body.contentEditable = 'true';
                    document.designMode='on'; 
                    void 0;
                    javascript:alert(document.documentElement.innerHTML); 
                    

                    突出显示它并将其拖到您的书签栏,当您想编辑和查看当前站点源代码时单击它。

                    【讨论】:

                      【解决方案16】:

                      在 Linux 上

                      1. 下载 slimerjs (slimerjs.org)

                      2. 下载火狐59版

                      3. 添加此环境变量:export SLIMERJSLAUNCHER=/home/en/Letöltések/firefox59/firefox/firefox

                      4. 在 slimerjs 下载页面上使用这个 .js 程序(./slomerjs program.js):

                         var page = require('webpage').create();
                         page.open(
                          'http://www.google.com/search?q=görény',
                           function() 
                           {
                             page.render('goo2.pdf');
                             phantom.exit();
                           }
                         );
                        

                      使用 pdftotext 获取页面上的文本。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2017-06-04
                        • 2020-03-01
                        • 1970-01-01
                        • 2012-08-01
                        • 2014-07-13
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-05-22
                        相关资源
                        最近更新 更多