PHPでHTML / XMLをどのように解析および処理しますか?


回答:


1897

ネイティブXML拡張

PHPにバンドルされているので、ネイティブXML拡張機能の 1つを使用することを好みます。これらは通常、すべてのサードパーティライブラリよりも高速で、マークアップに対して必要なすべての制御を提供します。

DOM

DOM拡張機能を使用すると、PHP 5のDOM APIを介してXMLドキュメントを操作できます。これは、W3Cのドキュメントオブジェクトモデルコアレベル3の実装です。ドキュメントのコンテンツ、構造、スタイル。

DOMは、実世界の(壊れた)HTMLを解析および変更でき、XPathクエリを実行できます。libxmlに基づいています

DOMで生産的になるには少し時間がかかりますが、その時間はIMOに値するものです。DOMは言語に依存しないインターフェースであるため、多くの言語で実装が見つかるので、プログラミング言語を変更する必要がある場合は、その言語のDOM APIの使用方法をすでに知っていることでしょう。

基本的な使用例はA要素のhref属性の取得にあり、一般的な概念の概要はphpのDOMDocumentにあります。

DOM拡張機能の使用方法はStackOverflow広くカバーされているため、それを使用することを選択した場合、発生した問題のほとんどはStack Overflowを検索/参照することで解決できると確信できます。

XMLReader

XMLReader拡張機能は、XMLプルパーサーです。リーダーは、ドキュメントストリームを先に進み、途中の各ノードで停止するカーソルとして機能します。

XMLReaderは、DOMと同様にlibxmlに基づいています。私はHTMLパーサーモジュールをトリガーする方法を知らないので、壊れたHTMLを解析するためにXMLReaderを使用する可能性は、libxmlのHTMLパーサーモジュールを使用するように明示的に指示できるDOMを使用するよりも堅牢ではない可能性があります。

基本的な使用例は、phpを使用してh1タグからすべての値取得するときに見つけることができます

XMLパーサー

この拡張機能を使用すると、XMLパーサーを作成してから、さまざまなXMLイベントのハンドラーを定義できます。各XMLパーサーには、調整可能ないくつかのパラメーターもあります。

XMLパーサーライブラリもlibxmlに基づいており、SAXスタイルのXMLプッシュパーサーを実装しています。DOMやSimpleXMLよりもメモリ管理には適しているかもしれませんが、XMLReaderによって実装されたプルパーサーよりも操作が難しくなります。

SimpleXml

SimpleXML拡張機能は、XMLを通常のプロパティセレクターや配列イテレーターで処理できるオブジェクトに変換するための非常にシンプルで使いやすいツールセットを提供します。

SimpleXMLは、HTMLが有効なXHTMLであることがわかっている場合のオプションです。壊れたHTMLを解析する必要がある場合は、SimpleXmlを使用しないでください。窒息するからです。

基本的な使用例は、XMLファイルのノードとノードの値をCRUDする単純なプログラムにあります。PHP マニュアルには、その他にも多くの例があります


サードパーティライブラリ(libxmlベース)

サードパーティのlibを使用したい場合は、文字列の解析ではなく、実際にDOM / libxmlを実際に使用するlibを使用することをお勧めします。

FluentDom - レポ

FluentDOMは、jQueryのような流暢なXMLインターフェイスをPHPのDOMDocumentに提供します。セレクターはXPathまたはCSSで記述されます(CSSからXPathへのコンバーターを使用)。現在のバージョンでは、DOM実装標準インターフェースを拡張し、DOM Living Standardの機能を追加しています。FluentDOMは、JSON、CSV、JsonML、RabbitFishなどの形式をロードできます。Composer経由でインストールできます。

HtmlPageDom

Wa72 \ HtmlPageDom`は、HTMLドキュメントを簡単に操作するためのPHPライブラリです。DOMツリーをトラバースするにはSymfony2コンポーネントのDomCrawlerが必要であり、HTMLドキュメントのDOMツリーを操作するメソッドを追加して拡張します。

phpQuery(何年も更新されません)

phpQueryは、PHP5で記述されたjQuery JavaScriptライブラリに基づくサーバーサイドのチェーン可能なCSS3セレクター駆動型ドキュメントオブジェクトモデル(DOM)APIであり、追加のコマンドラインインターフェイス(CLI)を提供します。

次も参照してください:https : //github.com/electrolinux/phpquery

Zend_Dom

Zend_Domは、DOMドキュメントと構造を操作するためのツールを提供します。現在、Zend_Dom_Queryを提供しています。これは、XPathセレクターとCSSセレクターの両方を利用してDOMドキュメントをクエリするための統合インターフェースを提供します。

QueryPath

QueryPathは、XMLおよびHTMLを操作するためのPHPライブラリです。ローカルファイルだけでなく、Webサービスやデータベースリソースでも機能するように設計されています。jQueryインターフェースの多く(CSSスタイルのセレクターを含む)を実装しますが、サーバー側で使用するために大幅に調整されています。Composer経由でインストールできます。

fDOMDocument

fDOMDocumentは、標準のDOMを拡張して、PHPの警告や通知ではなく、エラーが発生した場合に常に例外を使用します。また、便利なように、またDOMの使用を簡略化するために、さまざまなカスタムメソッドとショートカットを追加しています。

sabre / xml

sabre / xmlは、XMLReaderクラスとXMLWriterクラスをラップおよび拡張して、単純な「xml to object / array」マッピングシステムとデザインパターンを作成するライブラリです。XMLの書き込みと読み取りはシングルパスであるため、高速で、大きなxmlファイルに必要なメモリが少なくて済みます。

FluidXML

FluidXMLは、簡潔で流暢なAPIでXMLを操作するためのPHPライブラリです。XPathと流暢なプログラミングパターンを活用して、楽しく効果的なものにします。


サードパーティ(libxmlベースではない)

DOM / libxmlをベースに構築することの利点は、ネイティブ拡張に基づいているため、すぐに使用できる優れたパフォーマンスが得られることです。ただし、すべてのサードパーティライブラリがこの方法を使用するわけではありません。それらのいくつかは以下にリストされています

PHPシンプルHTML DOMパーサー

  • PHP5 +で記述されたHTML DOMパーサーを使用すると、HTMLを非常に簡単に操作できます。
  • PHP 5以降が必要です。
  • 無効なHTMLをサポートします。
  • jQueryのようなセレクターを使用してHTMLページ上のタグを検索します。
  • HTMLからコンテンツを1行で抽出します。

通常、このパーサーはお勧めしません。コードベースは恐ろしいものであり、パーサー自体はかなり遅く、メモリを大量に消費します。すべてのjQueryセレクター(子セレクターなど)が使用できるわけではありません。libxmlベースのライブラリはどれも、これを簡単に上回ります。

PHP HTMLパーサー

PHPHtmlParserは、jQueryなどのcssセレクターを使用してタグを選択できる、シンプルで柔軟なhtmlパーサーです。目標は、HTMLが有効かどうかに関係なく、HTMLをすばやく簡単にスクラップする方法を必要とするツールの開発を支援することです。このプロジェクトは元々sunra / php-simple-html-dom-parserによってサポートされていましたが、サポートが停止しているようですので、このプロジェクトは彼の以前の仕事の私の適応です。

繰り返しますが、このパーサーはお勧めしません。CPU使用率が高いと、かなり遅くなります。また、作成されたDOMオブジェクトのメモリをクリアする機能もありません。これらの問題は、特にネストされたループで拡大します。ドキュメント自体は不正確でスペルが間違っており、4月16日以降の修正に対する応答はありません。

ガノン

  • ユニバーサルトークナイザーとHTML / XML / RSS DOMパーサー
    • 要素とその属性を操作する機能
    • 無効なHTMLおよびUTF8をサポート
  • 要素に対して高度なCSS3のようなクエリを実行できます(jQueryなどの名前空間がサポートされています)
  • HTMLビューティファイヤー(HTML Tidyなど)
    • CSSとJavaScriptを縮小
    • 属性のソート、大文字と小文字の変更、インデントの修正など。
  • 拡張可能
    • 現在の文字/トークンに基づくコールバックを使用してドキュメントを解析する
    • 操作を簡単なオーバーライドのために小さな機能に分割
  • 速くて簡単

使用したことはありません。それが良いかどうかはわかりません。


HTML 5

上記を使用してHTML5を解析できますが、HTML5で許可されているマークアップが原因で問題が発生する可能性あります。したがって、HTML5の場合、次のような専用パーサーの使用を検討してください。

html5lib

WHATWG HTML5仕様に基づくHTMLパーサーのPythonおよびPHP実装で、主要なデスクトップWebブラウザーとの互換性を最大限に高めます。

HTML5が完成すると、専用のパーサーが増える可能性があります。W3の「How-To for html 5 parsing」というブログポストもチェックする価値があります。


ウェブサービス

PHPをプログラミングしたくない場合は、Webサービスを使用することもできます。一般に、これらのユーティリティはほとんど見つかりませんでしたが、それは私と私の使用例にすぎません。

ScraperWiki

ScraperWikiの外部インターフェイスを使用すると、Webまたは独自のアプリケーションで使用する形式でデータを抽出できます。スクレーパーの状態に関する情報を抽出することもできます。


正規表現

最後に推奨される方法として正規表現を使用してHTMLからデータを抽出できます。一般に、HTMLで正規表現を使用することはお勧めしません。

マークアップに一致させるためにWeb上で見つかるスニペットのほとんどは壊れやすいものです。ほとんどの場合、これらは特定のHTMLに対してのみ機能します。どこかに空白を追加したり、タグの属性を追加または変更したりするなど、小さなマークアップを変更すると、正しく記述されていない場合にRegExが失敗する可能性があります。HTMLでRegExを使用する前に、何をしているかを知っておく必要があります。

HTMLパーサーはすでにHTMLの構文規則を知っています。正規表現は、作成する新しいRegExごとに教える必要があります。場合によってはRegExで問題ありませんが、実際にはユースケースによって異なります。

より信頼性の高いパーサーを作成できます、前述のライブラリが既に存在し、これに対してはるかに優れた作業を行う場合、正規表現を使用して完全で信頼性の高いカスタムパーサーを作成するのは時間の無駄です。

Html The Cthulhu Wayの解析も参照してください。


お金を使いたいなら、

私はPHPアーキテクトや作者とは関係ありません。


10
あなたのニーズに依存する@Naveed。CSSセレクタークエリは必要ありません。そのため、XPathと排他的にDOMを使用しています。phpQueryは、jQueryポートになることを目指しています。Zend_Domは軽量です。あなたは本当にそれらをチェックして、どれが一番好きかを見極める必要があります。
ゴードン

2
@ Ms2gerほとんどが、完全ではありません。上記ですでに指摘したように、libxmlベースのパーサーを使用できますが、これらが詰まる特別な場合があります。最大の互換性が必要な場合は、専用のパーサーを使用する方がよいでしょう。私は区別を保つことを好みます。
Gordon

9
PHP Simple HTML DOM Parserを使用しないというあなたの要点は意味がないようです。
ペタ

3
2012年3月29日の時点で、DOMはhtml5をサポートしておらず、XMLReaderはHTMLをサポートしておらず、PHPのhtml5libに対する最後のコミットは2009年9月です。
Shiplu Mokaddim 2012年

4
@Nasha私は悪名高いZalgoの暴言を上からリストから意図的に除外しました。それ自体はあまり役立たず、それが書かれてからかなりのカーゴカルトにつながるからです。正規表現がソリューションとしてどれほど適切であったとしても、人々はそのリンクで平手打ちされました。よりバランスのとれた意見について、代わりに私含めたリンクを参照し、stackoverflow.com / questions / 4245008
Gordon

322

Simple HTML DOM Parserを試す

  • PHP 5以降で記述されたHTML DOMパーサー。HTMLを非常に簡単に操作できます。
  • PHP 5以降が必要です。
  • 無効なHTMLをサポートします。
  • jQueryのようなセレクターを使用してHTMLページ上のタグを検索します。
  • HTMLからコンテンツを1行で抽出します。
  • ダウンロード


例:

HTML要素を取得する方法:

// Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';


HTML要素を変更する方法:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;


HTMLからコンテンツを抽出します。

// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;


スラッシュドットをこする:

// Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);

8
まあまず、悪いDOM、Invlidコード、DNSBLエンジンに対するjs分析など、準備する必要があるものがあります。これは、悪意のあるサイト/コンテンツを探すためにも使用されます。また、フレームワークを中心に自分のサイトを構築したときクリーンで読みやすく、適切に構造化されている必要があります。SimpleDimは素晴らしいですが、コードは少し面倒です
RobertPitt 2010

9
@Robert は、セキュリティに関連することについてhtmlpurifier.orgをチェックすることもできます。
ゴードンは

3
彼は1つの有効なポイントを持っています。simpleHTMLDOMは、私が扱いにくいと思うデコレータパターンを使用しない限り、拡張するのは困難です。私は自分自身が見つけた身震いだけで、基本となるクラスへの変更(ES)自分自身を作ります。
エリック

1
私がしたことは、SimpleDOMに送信する前に、整頓されたHTMLを実行することでした。
MB34 2012

1
私は現在これを使用しており、数百のURLを処理するプロジェクトの一部として実行しています。非常に遅くなり、定期的なタイムアウトが続きます。初心者向けの優れたスクリプトであり、直感的に学ぶのは簡単ですが、より高度なプロジェクトにはあまりにも基本的です。
luke_mclachlan

236

DOMDocument-> loadHTML()を使用するだけで完了です。libxmlのHTML解析アルゴリズムは非常に優れて高速であり、一般的な考えに反して、不正な形式のHTMLには影響しません。


19
本当です。また、コンテンツの抽出に最適なPHPの組み込みXPathおよびXSLTProcessorクラスと連携します。
Kornel

8
本当に壊れたHTMLの場合、DOMに渡す前に、いつでもhtmltidyを実行できます。HTMLからデータを取得する必要があるときはいつでも、常にDOM、または少なくともsimplexmlを使用します。
フランクファーマー、

9
不正な形式のHTML iをロードする際のもう1つのことは、libxml_use_internal_errors(true)を呼び出して、解析を停止する警告を防止するのが賢明な場合があることです。
ハスキー

6
私はDOMDocumentを使用して、約1000のHTMLソースを(さまざまな文字セットでエンコードされたさまざまな言語で)問題なく解析しました。これでエンコーディングの問題に遭遇するかもしれませんが、それらを克服することはできません。3つのことを知っておく必要があります。1)loadHTMLはメタタグの文字セットを使用してエンコーディングを決定します。2)HTMLコンテンツにこの情報が含まれていない場合、#2は誤ったエンコーディング検出を引き起こす可能性があります。そのような場合は、mb_detect_encoding()とSimplepie RSS Parserのエンコードを組み合わせて使用​​するか、回避策として不正なUTF-8文字コードを変換/除去してください。
ゼロ

1
DOMは実際にはXPathをサポートしています。DOMXPathを見てください
Ryan McCue、2012年

147

なぜ正規表現使用すべきではなく、いつ使用すべきですか?

まず、よくある誤解:正規表現はHTML を解析」するためのものではありません。ただし、正規表現はデータを抽出できます。抽出は、彼らのために作られたものです。適切なSGMLツールキットまたはベースラインXMLパーサーに対する正規表現のHTML抽出の主な欠点は、構文上の労力と信頼性のばらつきです。

ある程度信頼できるHTML抽出正規表現を作成することを検討してください。

<a\s+class="?playbutton\d?[^>]+id="(\d+)".+?    <a\s+class="[\w\s]*title
[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?

単純なphpQueryまたは同等のQueryPathよりも読みにくくなります。

$div->find(".stationcool a")->attr("title");

ただし、それらが役立つ特定のユースケースがあります。

  • 多くのDOMトラバーサルフロントエンドはHTMLコメントを公開しませんが<!--、抽出に役立つアンカーになる場合があります。特に、疑似HTMLのバリエーション<$var>やSGMLの残留物は、正規表現で簡単に調整できます。
  • 多くの場合、正規表現は後処理を節約できます。ただし、HTMLエンティティは多くの場合、手作業による注意が必要です。
  • そして最後に、<img src = urlの抽出などの非常に単純なタスクの場合、それらは実際にありそうなツールです。SGML / XMLパーサーに勝る速度の利点は、これらの非常に基本的な抽出手順で主に発揮されます。

正規表現/<!--CONTENT-->(.+?)<!--END-->/を使用してHTMLのスニペットを事前に抽出し、より簡単なHTMLパーサーのフロントエンドを使用して残りを処理することをお勧めすることもあります。

注:私は実際にこのアプリを持っています。XML解析と正規表現を交互に使用しています。ちょうど先週、PyQueryの解析が失敗し、正規表現はまだ機能していました。はい、奇妙で、私はそれを自分で説明することはできません。しかし、それは起こりました。
だから、実際の考慮事項をregex = evil memeと一致しないという理由だけで投票しないでください。しかし、これもあまり投票しないでください。これは、このトピックの補足にすぎません。


20
DOMCommentコメントを読むことができるので、そのために正規表現を使用する理由はありません。
Gordon

4
SGMLツールキットもXMLパーサーも、実際のHTMLの解析には適していません。そのためには、専用のHTMLパーサーのみが適切です。
Alohci

12
@Alohci DOMlibxmlを使用し、libxmlは HTMLをロードするときに使用される個別のHTMLパーサーモジュールを持っているloadHTML()ため、「実世界」(壊れた読み取り)のHTMLを非常に多くロードできます。
Gordon

6
さて、あなたの「現実世界の考慮」の見解についての単なるコメントです。確かに、HTMLを解析するときにRegexに役立つ状況があります。また、GOTOを使用するための便利な状況もあります。また、変数変数には便利な状況があります。したがって、特定の実装は、それを使用するために間違いなくコードを腐敗させるものではありません。しかし、それは非常に強力な警告サインです。そして、平均的な開発者は、違いを見分けるのに十分な微妙な違いがあるとは思えません。したがって、原則として、Regex GOTOとVariable-Variablesはすべて悪です。非
悪用

11
@mario:実際には、正規表現を使用してHTML 「適切に」解析できます、通常、正規表現を実行するにはいくつかの正規表現が必要です。それは一般的なケースではただの王の痛みです。明確に定義された入力がある特定のケースでは、それは取るに足らないことになります。それらは人々正規表現を使うべきケースです。大きな古い空腹の重いパーサーは、一般的なケースで本当に必要なものですが、カジュアルなユーザーにとって、どこに線を引くかは必ずしも明確ではありません。どちらのコードが単純で簡単でも、勝ちます。
tchrist 2010年

131

phpQueryQueryPathは、流暢なjQuery APIの複製において非常に似ています。これが、PHPでHTML を適切に解析する最も簡単な方法の2つである理由でもあります。

QueryPathの例

基本的に、最初にHTML文字列からクエリ可能なDOMツリーを作成します。

 $qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL

結果のオブジェクトには、HTMLドキュメントの完全なツリー表現が含まれています。DOMメソッドを使用してトラバースできます。しかし、一般的なアプローチはjQueryのようにCSSセレクターを使用することです:

 $qp->find("div.classname")->children()->...;

 foreach ($qp->find("p img") as $img) {
     print qp($img)->attr("src");
 }

ほとんどの場合、あなたは簡単に使用したい#id.classDIVのタグセレクタを->find()。ただし、XPathステートメントを使用することもできます。また、典型的なjQueryメソッドは、適切なHTMLスニペットのような->children()->text()特にその->attr()抽出を簡単にします。(そして既にそれらのSGMLエンティティがデコードされています。)

 $qp->xpath("//div/p[1]");  // get first paragraph in a div

QueryPathを使用すると、新しいタグをストリームに挿入し(->append)、後で出力し、更新されたドキュメントをきれいにすることもできます(->writeHTML)。不正な形式のHTMLだけでなく、さまざまなXML方言(名前空間付き)も解析でき、HTMLマイクロフォーマット(XFN、vCard)からデータを抽出することもできます。

 $qp->find("a[target=_blank]")->toggleClass("usability-blunder");

phpQueryまたはQueryPath?

通常、QueryPathはドキュメントの操作に適しています。phpQueryは、jQueryにさらによく似たいくつかの疑似AJAXメソッド(HTTPリクエストのみ)も実装します。多くの場合、phpQueryはQueryPathよりも高速であると言われています(全体的な機能が少ないため)。

違いの詳細については、tagbyte.orgのウェイバックマシンでのこの比較を参照してください。(元のソースがなくなっていたので、ここにインターネットアーカイブリンクがあります。はい、行方不明のページを見つけることができます)。

そして、これが包括的なQueryPathの紹介です。

メリット

  • シンプルさと信頼性
  • 使いやすい代替 ->find("a img, a object, div a")
  • 適切なデータのエスケープ解除(正規表現のgreppingと比較して)

88

シンプルなHTML DOMは、優れたオープンソースのパーサーです。

simplehtmldom.sourceforge

オブジェクト指向の方法でDOM要素を処理し、新しいイテレーションは非準拠コードを多くカバーします。また、JavaScriptに見られるような素晴らしい関数もあります。たとえば、「find」関数は、そのタグ名の要素のすべてのインスタンスを返します。

私はこれをいくつかのツールで使用し、さまざまな種類のWebページでテストしてきました。


61

ここで言及していない一般的なアプローチの1つは、Tidyを介してHTMLを実行することです。Tidyは、保証された有効なXHTMLを出力するように設定できます。その後、古いXMLライブラリを使用できます。

しかし、あなたの特定の問題に、あなたはこのプロジェクトを見てとる必要があります。http://fivefilters.org/content-only/を -それはの修正版です可読性だけで、テキストコンテンツ(ないヘッダを抽出するように設計されたアルゴリズム、およびフッター)から。


56

1aと2の場合:新しいSymfony ComponetクラスDOMCrawler(DomCrawler)に投票します。このクラスでは、CSSセレクターと同様のクエリを使用できます。実際の例については、このプレゼンテーションをご覧くださいnews-of-the-symfony2-world

コンポーネントはスタンドアロンで動作するように設計されており、Symfonyなしで使用できます。

唯一の欠点は、PHP 5.3以降でのみ機能することです。


jqueryのようなcssクエリはよく言われます。これは、w3cのドキュメントには欠けているものもありますが、jqueryの追加機能として存在するためです。
Nikola Petkanski 2013年

53

ちなみに、これは一般にスクリーンスクレイピングと呼ばれています。これに使用したライブラリはSimple HTML Dom Parserです。


8
厳密には当てはまりません(en.wikipedia.org/wiki/Screen_scraping#Screen_scraping)。手がかりは「画面」にあります。説明されているケースでは、画面は含まれていません。確かに、この用語は最近の非常に多くの誤用を被っています。
ボビージャック

4
私はスクリーンスクレイピングではなく、解析されるコンテンツは私の同意の下でコンテンツサプライヤーによって承認されます。
RobertPitt、

41

以前は、私たちのニーズに合わせてかなりの数のクローラーを作成しました。結局のところ、最も効果的なのは通常、単純な正規表現です。上記のライブラリは作成されたという理由で良いですが、探しているものがわかっている場合は、正規表現を使用すると安全です。無効なHTML / XHTML構造も処理できるため、ロードすると失敗します。ほとんどのパーサー経由。



36

これは、W3C XPathテクノロジーの優れたタスクの説明のようです。「にネストされているタグのすべてのhref属性を返す」のようなクエリは簡単に表現できます。PHPの愛好家ではないため、XPathがどのような形で利用できるかはわかりません。外部プログラムを呼び出してHTMLファイルを処理できる場合は、コマンドラインバージョンのXPathを使用できるはずです。簡単な紹介については、http://en.wikipedia.org/wiki/XPathを参照してくださいimg<foo><bar><baz> elements


29

文字列解析の代わりにDOMを使用するSimpleHtmlDomのサードパーティの代替:phpQueryZend_DomQueryPath、およびFluentDom


3
私のコメントをすでにコピーしている場合は、少なくとも適切にリンクしてください;)これは、文字列解析の代わりに実際にDOMを使用するSimpleHtmlDomのサードパーティの代替案:phpQueryZend_DomQueryPath、およびFluentDomです。
Gordon

1
良い答えは素晴らしい情報源です。stackoverflow.com/questions/3606792/...
danidacar

24

はい、目的のためにsimple_html_domを使用できます。ただし、simple_html_domを使用して、特にWebの廃棄についてかなり作業し、脆弱性が高すぎることがわかりました。それは基本的な仕事をしますが、とにかくお勧めしません。

私はその目的でcurlを使用したことはありませんが、curlがより効率的に作業を行うことができ、はるかに堅固であることを学びました。

親切にこのリンクをチェックしてください:scraping-websites-with-curl


2
curl はファイルを取得できますが、HTMLを解析しません。それは難しい部分です。
cHao

23

QueryPathは適切ですが、「追跡状態」の原因に注意してください。意味がわからない場合は、何が起こっているのか、なぜコードが機能しないのかを調べるためにデバッグに多くの時間を費やす可能性があります。

これは、結果セットの各呼び出しがオブジェクトの結果セットを変更することを意味します。jlinkでは、各リンクが新しいセットであり、クエリからの結果である単一のセットがあり、各関数呼び出しが変更されます。その単一のセット。

jqueryのような動作を実現するには、filter / modify like操作を実行する前に分岐する必要があります。つまり、jqueryで発生することをより厳密に反映します。

$results = qp("div p");
$forename = $results->find("input[name='forename']");

$resultsこれでinput[name='forename']、元のクエリの結果セットが含まれなくなりました。これにより"div p"QueryPathはフィルターを追跡し、結果を変更してオブジェクトに保存するすべてのものを追跡します。代わりにこれを行う必要があります

$forename = $results->branch()->find("input[name='forname']")

その後$resultsは変更されず、結果セットを何度も再利用できます。おそらく、より知識のある誰かがこれを少しクリアできるかもしれませんが、基本的には、私が見つけたものからはこのようなものです。


20

Advanced Html Domは、同じインターフェースを提供する単純なHTML DOMの代替品ですが、DOMベースであるため、関連するメモリの問題は発生しません。

jQueryを含む完全なCSSサポートも備えています拡張機能ます。


私はAdvanced Html Domから良い結果を得ました、そしてそれは受け入れられた答えのリストにあるべきだと思います。「このプロジェクトの目標は、PHPの単純なhtml domライブラリのDOMベースのドロップインの置き換えになることです... file / str_get_htmlを使用する場合、その必要はありません。なんでも変えて」archive.is/QtSuj#selection-933.34-933.100は、一部の非互換性に対応するためにコードを変更する必要がある場合があることです。プロジェクトのgithubの問題で私が知っている4つのことを指摘しました。github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ

働いた!ありがとう
ファイサルシャニ

18

以下のためにHTML5、HTML5 libにここ数年のために放棄されました。最近の更新とメンテナンスの記録で私が見つけることができる唯一のHTML5ライブラリーは、1 か月以上前にベータ1.0に導入されたhtml5-phpです。


17

GBファイルを簡単に処理できる汎用のXMLパーサーを作成しました。XMLReaderに基づいており、非常に使いやすいです。

$source = new XmlExtractor("path/to/tag", "/path/to/file.xml");
foreach ($source as $tag) {
    echo $tag->field1;
    echo $tag->field2->subfield1;
}

これがgithubリポジトリです:XmlExtractor


17

PHPPowertools / DOM-Queryという名前のライブラリを作成しました。これにより、jQueryと同じようにHTML5およびXML文書をクロールできます。

内部的には、CSSセレクターからXPathセレクターへの変換にsymfony / DomCrawlerを使用します。適切なパフォーマンスを確保するために、1つのオブジェクトを別のオブジェクトに渡す場合でも、常に同じDomDocumentを使用します。


使用例:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents('https://github.com');

// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));

// Passing a string (CSS selector)
$s = $H->select('div.foo');

// Passing an element object (DOM Element)
$s = $H->select($documentBody);

// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');

[...]

サポートされている方法:


  1. 明らかな理由により、「select」に名前が変更されました
  2. 「空」はPHPの予約語であるため、「void」に名前が変更されました

注意 :

ライブラリには、PSR-0互換ライブラリ用の独自のゼロ設定オートローダーも含まれています。含まれている例は、追加の構成なしでそのまま使用できます。または、composerで使用することもできます。


仕事に適したツールのように見えますが、WorpressのPHP 5.6.23ではロードされません。それを正しく含める方法に関する追加の指示はありますか?含まれています:define( "BASE_PATH"、dirname(FILE)); define( "LIBRARY_PATH"、BASE_PATH。DIRECTORY_SEPARATOR。 'lib / vendor'); LIBRARY_PATHが必要です。DIRECTORY_SEPARATOR。'Loader.php'; ローダー:: init(array(LIBRARY_PATH、USER_PATH)); functions.php内
Lilithlab 2016年

15

HTML Tidyなどを使用して、「壊れた」HTMLをクリーンアップし、HTMLをXHTMLに変換して、XMLパーサーで解析することができます。


15

試すことができる別のオプションはQueryPathです。jQueryに触発されていますが、サーバーはPHPで、Drupalで使用されています。


12

XML_HTMLSaxかなり安定している-それが維持されなくなったとしても。別のオプションは、HTML Tidyを介してHTMLをパイプ処理し、標準のXMLツールで解析することです。


11

Symfonyフレームワークには、HTMLを解析することができ、あなたが選択するために、CSSスタイルを使用することができますバンドルがあるのDOMの代わりに使用してのXPathを


11

HTML / XML DOMを処理する方法はたくさんありますが、そのほとんどはすでに言及されています。したがって、私はそれらを自分でリストしようとはしません。

私が個人的にDOM拡張機能を使用することを好むことと、その理由を追加したいだけです。

  • iitは、基礎となるCコードのパフォーマンス上の利点を最適に利用します
  • それはOO PHPです(そしてそれをサブクラス化することができます)
  • それはかなり低レベルです(これにより、より高度な動作の肥大化しない基盤として使用できます)
  • DOMのすべての部分へのアクセスを提供します(たとえば、あまり知られていないXML機能の一部を無視するSimpleXmlとは異なります)
  • DOMクロールに使用される構文は、ネイティブJavascriptで使用される構文に似ています。

私はCSSセレクタを使用する能力を欠場しながらDOMDocumentサブクラス化:この機能を追加するためではなく、簡単で便利な方法がありDOMDocumentかつJS-などの追加querySelectorAllおよびquerySelector方法あなたのサブクラスには。

セレクターの解析には、Symfonyフレームワークの非常に最小限のCssSelectorコンポーネントを使用することをお勧めします。このコンポーネントは、CSSセレクターをXPathセレクターに変換するだけです。XPath セレクターをにフィードして、対応するノードリストを取得できます。DOMXpath

次に、この(まだ非常に低レベルの)サブクラスを、より高レベルのクラスの基礎として使用できます。非常に特定のタイプのXMLを解析するか、jQueryのような動作を追加します。

以下のコードは、私のDOM-Queryライブラリーをそのまま使用したもので、私が説明した手法を使用しています。

HTML解析の場合:

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

SymfonyのCssSelectorコンポーネントを作成する決定とその使用方法については、Symfonyの作成者であるFabien PotencierによるCSSセレクターを使用したXMLドキュメントの解析も参照してください。


9

ではFluidXMLあなたが使用してクエリを実行し、反復XMLができたXPathCSSセレクタを

$doc = fluidxml('<html>...</html>');

$title = $doc->query('//head/title')[0]->nodeValue;

$doc->query('//body/p', 'div.active', '#bgId')
        ->each(function($i, $node) {
            // $node is a DOMNode.
            $tag   = $node->nodeName;
            $text  = $node->nodeValue;
            $class = $node->getAttribute('class');
        });

https://github.com/servo-php/fluidxml


7

JSONと3行のXMLからの配列:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

だだ!


7

正規表現でHTMLを解析しない理由はいくつかあります。ただし、生成されるHTMLを完全に制御できる場合は、単純な正規表現を使用できます。

上記は、正規表現によってHTMLを解析する関数です。この関数は非常に敏感で、HTMLが特定のルールに従うことを要求しますが、多くのシナリオで非常にうまく機能することに注意してください。単純なパーサーが必要で、ライブラリーをインストールしたくない場合は、これを試してみてください。

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));

2

私はhttps://github.com/ivopetkov/html5-dom-document-phpで自由に利用できるHTML5DOMDocumentと呼ばれるライブラリを作成しました

クエリセレクターもサポートしているので、あなたの場合は非常に役立つと思います。ここにいくつかのサンプルコードがあります:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;

0

jQueryセレクターに慣れている場合は、ScarletsQuery for PHPを使用できます。

<pre><?php
include "ScarletsQuery.php";

// Load the HTML content and parse it
$html = file_get_contents('https://www.lipsum.com');
$dom = Scarlets\Library\MarkupLanguage::parseText($html);

// Select meta tag on the HTML header
$description = $dom->selector('head meta[name="description"]')[0];

// Get 'content' attribute value from meta tag
print_r($description->attr('content'));

$description = $dom->selector('#Content p');

// Get element array
print_r($description->view);

このライブラリは通常、オフラインHTMLの処理に1秒もかかりません。
また、タグ属性で無効なHTMLまたは欠落した引用を受け入れます。


0

XMLを解析するための最良の方法:

$xml='http://www.example.com/rss.xml';
$rss = simplexml_load_string($xml);
$i = 0;
foreach ($rss->channel->item as $feedItem) {
  $i++;
  echo $title=$feedItem->title;
  echo '<br>';
  echo $link=$feedItem->link;
  echo '<br>';
  if($feedItem->description !='') {
    $des=$feedItem->description;
  } else {
    $des='';
  }
  echo $des;
  echo '<br>';
  if($i>5) break;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.