【问题标题】:How to Enhance This? Get a Part of a Web Page in Another Domain如何增强这个?在另一个域中获取网页的一部分
【发布时间】:2013-11-05 09:31:46
【问题描述】:

我做了这个:

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script>
            $(document).ready(
                function()
                {   
                    $("body").html($("#HomePageTabs_cont_3").html());
                }
            );
        </script>
    </head>
    <body>
    <?php
        echo file_get_contents("http://www.bankasya.com.tr/index.jsp");
    ?>

    </body>
</html>

当我用 Firebug 检查我的页面时,它给出了无数的“丢失文件”(图像、css 文件、js 文件等)错误。我只想拥有页面的一部分而不是全部。 这段代码可以满足我的要求。但我想知道是否有更好的方法。

编辑:

该页面可以满足我的需要。我不需要所有的内容。所以iframe 对我来说没用。我只想要 div #HomePageTabs_cont_3 的原始数据。

【问题讨论】:

  • 看起来你真正想要的是一个代理服务器,或者可能是一个简单的 iframe。如果您想解决丢失的文件,您将需要解析 HTML 服务器端并将所有资源 URL 转换为绝对 URL,或者在客户端执行相同的操作(服务器端会更容易,但对用户来说可能看起来更慢)。
  • 我只想要页面的一部分。 iframe 不获取所有内容吗?我不想要iframe
  • 是的,它会的。那么可能您需要指定:您希望页面中的“所有内容”的哪一部分..
  • @OzkanOzlu 您需要将 HTML 加载到 DOMDocument 并在服务器端提取您想要的内容。一个简单的file_get_contents() 是不行的。
  • @OzkanOzlu:你知道(标记你),我刚刚对代码进行了广泛的修改。它不再抱怨他们(失败的)HTML语义了。

标签: php jquery html domdocument


【解决方案1】:

最好的选择是 PHP 服务器端解析。我写了一个小 sn-p 来向您展示如何使用 DOMDocument 来执行此操作(如果您的服务器有它,可能还有 tidy,以消除所有格式错误的 XHTML foo)。

警告:输出 UTF-8。您可以在 DOMDocument 的构造函数中更改它

注意事项 2:如果输入既不是 utf-8 也不是 iso-8859-9,吐出。当前页面的字符集是 iso-8859-9,我认为他们没有理由更改它。

header("content-type: text/html; charset=utf-8");
$data = file_get_contents("http://www.bankasya.com.tr/index.jsp");
// Clean it up
if (class_exists("tidy")) {
   $dataTidy = new tidy();
   $dataTidy->parseString($data,
                                 array(
                                       "input-encoding" => "iso-8859-9",
                                       "output-encoding" => "iso-8859-9",
                                       "clean" => 1,
                                       "input-xml" => true,
                                       "output-xml" => true,
                                       "wrap" => 0,
                                       "anchor-as-name" => false
                                 )
                          );
   $dataTidy->cleanRepair();
   $data = (string)$dataTidy;
}
else {
    $do = true;
            while ($do) {
                    $start = stripos($data,'<script');
                    $stop = stripos($data,'</script>');
                    if ((is_numeric($start))&&(is_numeric($stop))) {
                            $s = substr($data,$start,$stop-$start);
                            $data = substr($data,0,$start).substr($data,($stop+strlen('</script>')));
                    } else {
                            $do = false;
                    }
            }
    // nbsp breaks it?
    $data = str_replace("&nbsp;"," ",$data);
    // Fixes for any element that requires a self-closing tag
    if (preg_match_all("/<(link|img)([^>]+)>/is",$data,$mt,PREG_SET_ORDER)) {
            foreach ($mt as $v) {
                    if (substr($v[2],-1) != "/") {
                            $data = str_replace($v[0],"<".$v[1].$v[2]."/>",$data);
                    }
            }
    }
    // Barf out the inline JS
    $data = preg_replace("/javascript:[^;]+/is","#",$data);
    // Barf out the noscripts
    $data = preg_replace("#<noscript>(.+?)</noscript>#is","",$data);
    // Muppets. Malformed comment = one more regexp when they could just learn to write proper HTML...
    $data = preg_replace("#<!--(.*?)--!?>#is","",$data);
}
$DOM = new \DOMDocument("1.0","utf-8");
$DOM->recover = true;
    function error_callback_xmlfunction($errno, $errstr) { throw new Exception($errstr); }
    $old = set_error_handler("error_callback_xmlfunction");
// Throw out all the XML namespaces (if any)
$data = preg_replace("#xmlns=[\"\']?([^\"\']+)[\"\']?#is","",(string)$data);
try {
      $DOM->loadXML(((substr($data, 0, 5) !== "<?xml") ? '<?xml version="1.0" encoding="utf-8"?>' : "").$data);
} catch (Exception $e) {
      $DOM->loadXML(((substr($data, 0, 5) !== "<?xml") ? '<?xml version="1.0" encoding="iso-8859-9"?>' : "").$data);
}
    restore_error_handler();
error_reporting(E_ALL);
$DOM->substituteEntities = true;
$xpath = new \DOMXPath($DOM);
echo $DOM->saveXML($xpath->query("//div[@id=\"HomePageTabs_cont_3\"]")->item(0));

按出场顺序:

  • 获取数据
  • 如果我们有 tidy,用它清理 HTML
  • 创建一个新的DOMDocument 并加载我们的文档((string)$dataTidy 是一个简洁的 tidy getter)
  • 创建 XPath 请求路径
  • 使用 XPath 请求所有 id 设置为我们想要的 div,获取集合的第一项(-&gt;item(0),这将是一个DOMElement)并请求 DOM 输出其 XML 内容(包括标签本身)

希望它是您正在寻找的...尽管您可能希望将其包装在一个函数中。

编辑

忘了说:http://rescrape.it/rs.php 用于实际的脚本输出!

编辑 2

更正,该站点不是 W3C 有效的,因此,您要么需要 tidy 它,要么在处理之前将一组正则表达式应用于输入。我要看看我是否可以制定一个集合来消除不一致。

编辑 3

为我们这些没有tidy 的人添加了一个修复程序。

编辑 4

无法抗拒。如果您实际上更喜欢这些值而不是表格,请使用它而不是 echo:

 $d = new stdClass();
 $rows = $xpath->query("//div[@id=\"HomePageTabs_cont_3\"]//tr");
 $rc = $rows->length;
 for ($i = 1; $i < $rc-1; $i++) {
     $cols = $xpath->query($rows->item($i)->getNodePath()."/td");
     $d->{$cols->item(0)->textContent} = array(
        ((float)$cols->item(1)->textContent),
        ((float)$cols->item(2)->textContent)
     );
 }

我不了解你,但对我来说,数据比格式错误的表格更有效。

(Welp,那篇文章花了一些时间来写)

【讨论】:

  • 太好了。非常感谢。
  • 我只是在研究使用 jQuery ajax 抓取表中的数据以作为记录插入。这对我有好处。太感谢了。你读懂了我的想法。
  • 我试图用几根羽毛飞起来,你给了我一架喷气式飞机。
  • 狡猾的解决方案没有错 :-) 我正在考虑写一篇关于DOMDocument 使用和数据抓取的教程,顺便说一下,看看我的答案有多少倾向于这个话题.
【解决方案2】:

我会与远程站点的所有者取得联系,并询问是否有我可以使用的数据馈送来返回我想要的内容。

【讨论】:

    【解决方案3】:

    Sébastien answer 是最好的解决方案,但如果您想使用 jquery,您可以在您网站的 head 部分添加 Base 标签,以避免出现未找到的图像错误。

    <base href="http://www.bankasya.com.tr/">
    

    您还需要将源更改为绝对路径。

    但使用 DOMDocument

    【讨论】:

    • 不一定是个好主意。由于三个(三个!)闪存小程序,该页面的大小刚刚超过 MiB。所以在这种情况下,我什至不认为基础黑客是一种解决方案——浪费了太多额外的带宽。
    • @SébastienRenauld 是的,这是一个糟糕的解决方案,但仍然有效...... P.S.从其他网站抓取内容总是不是好主意 :)
    • 有时,您别无选择。旁注,我的生活的一部分是为人们编写解析器;-)
    • 现在我知道你是如何在几分钟内写下这个完整答案的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多