7

Webページを取得し、Facebookのようなボタンが使用された回数を検出するスクリプトを作成しています。これはDOMで行うのが最適なので、PHPのDOMDocumentを使用することにしました。

しかし、私が遭遇した1つの問題は、Facebookの「いいね」ボタンのような要素に関するものです。

<fb:like send="true" width="450" show_faces="true"></fb:like>

この要素は技術的には「fb」の名前空間を持っているため、DOMDocumentはこの名前空間プレフィックスが定義されていないことを示す警告をスローします。次に、プレフィックスの削除に進みます。そのため、上記の要素に到達すると、そのタグはfb:likeではなく、のようになります。

名前空間を「事前登録」する方法はありますか?助言がありますか?

4

6 に答える 6

4

xmlパーサーを使用する前に、 tidyを使用して物事を整えることができます。

$tidy = new tidy();
$config = array(
    'output-xml'   => true, 
    'input-xml'    => true, 
    'add-xml-decl' => true,
);
$tidy->ParseString($htmlSoup, $config);
$tidy->cleanRepair();
echo $tidy;
于 2012-06-11T19:27:18.363 に答える
1

これは決して「解決」されなかったので、正規表現を理解するのが嫌いな人のために、シンダンスのソリューションを実装することにしました。

// do this before you use loadHTML()    
// store any name spaced elements so we can re-add them later
$postContent = preg_replace('/<(\w+):(\w+)/', '<\1 data-namespace="\2"' , $postContent);

// once you are done using domdocument fix things up
// re-construct any name-spaced tags
$postContent = preg_replace('/<(\w+) data-namespace="(\w+)"/', '<\1:\2 ' , $postContent);
于 2015-08-12T19:02:10.877 に答える
0

これはあなたが探しているものですか?

SimpleHTMLDOMを試すことができます。次に、次のようなものを実行できます...

$html = new simple_html_dom();
$html->load_file('fileToParse.html');
$count=0;
foreach($html->find('fb:like') as $element){
    $count+=1
}
echo $count;

それはうまくいくはずです。

もう少し調べてみると、これが見つかりました。これは、PHP.netのDOMDocumentから取得しました。

$dom = new DOMDocument;
$dom->loadHTML('fileToParse.html'); // or $dom->loadXML('fileToParse.html'); 
$likes = $dom->getElementsByTagName('fb:like');
$count=0;
foreach ($likes as $like) {
    $count+=1;
}

この後私は立ち往生しています

$file=file_get_contents("other.html");
$search = '/<fb:like[^>]*>/';
$count  = preg_match_all($search , $file, $matches);
echo $count;
//Below is not needed
print_r($matches);

ただし、これは正規表現であり、非常に低速です。私は試した:

$dom = new DOMDocument;
$xpath = new DOMXPath($dom);
$dom->load("other.html");
$xpath = new DOMXPath($dom);
$rootNamespace = $dom->lookupNamespaceUri($dom->namespaceURI); 
$xpath->registerNamespace('fb', $rootNamespace); 
$elementList = $xpath->query('//fb:like'); 

しかし、あなたと同じエラーが発生しました。

于 2012-06-11T18:25:30.733 に答える
0

でそれを行う方法を見つけることができませんでしたDOMDOMDocument通常はそうではないので 、正規表現が遅いことに驚いています。strposただし、最速である必要があります。

strpos($dom, '<fb:like');

これは最初の出現を見つけるだけですが、オフセットを適切に変更する単純な再帰関数を書くことができます。

于 2012-06-12T16:35:32.850 に答える
0

私は同じ問題を抱えていて、次の解決策/回避策を思いつきました:

名前空間を失うことなく、DOMDocumentを使用して名前空間を持つHTMLを解析するクリーンな方法はありませんが、いくつかの回避策があります。

  • HMTLコードで名前空間を受け入れる別のパーサーを使用します。HTMLパーサーの詳細なリストについては、こちらをご覧ください。これはおそらくそれを行うための最も効率的な方法です。
  • DOMDocumentを使い続けたい場合は、基本的にコードを前処理および後処理する必要があります。

    • コードをDOMDocument->loadHTMLに送信する前に、正規表現、ループなど、名前空間付きのすべてのタグを検索し、名前空間を含む開始タグにカスタム属性を追加します。

      <fb:like send="true" width="450" show_faces="true"></fb:like>
      

      その結果、

      <fb:like xmlNamespace="fb" send="true" width="450" show_faces="true"></fb:like>
      
    • 次に、編集したコードをDOMDocument->loadHTMLに渡します。名前空間は削除されますが、結果として得られる属性は保持されます。

      <like xmlNamespace="fb" send="true" width="450" show_faces="true"></like>
      
    • ここで(ここでも正規表現、ループ、または必要なものを使用して)、属性xmlNamespaceを持つすべてのタグを検索し、属性を実際の名前空間に置き換えます。終了タグにも名前空間を追加することを忘れないでください!

OPはまだ答えを探しているとは思いません。調査でこの投稿を見つけた人のために、これを投稿しています。

于 2015-05-10T07:54:24.470 に答える
-1

regEx-solutionを試しました...属性を受け入れないため、終了タグに問題があります。

<ns namespace="node">text</ns>

(何よりも、正規表現は終了タグを探しませんでした...)最後に私は次のような醜いことをしました

$output = preg_replace('/<(\/?)(\w+):(\w+)/', '<\1\2thistaghasanamespace\3' , $output);

$output = preg_replace('/<(\/?)(\w+)thistaghasanamespace(\w+)/', '<\1\2:\3' , $output);
于 2016-02-16T16:14:55.890 に答える