1

preg_match_all を使用して、HTML コードのブロックからすべての URL を抽出しようとしています。また、すべての画像を無視しようとしています。

HTML ブロックの例:

$html = '<p>This is a test</p><br>http://www.facebook.com<br><img src="http://www.google.com/photo.jpg">www.yahoo.com https://www.aol.com<br>';

以下を使用して、URL のみの配列を作成しようとしています。(画像ではありません)

if(preg_match_all('~(?:(?:https://)|(?:http://)|(?:www\.))(?![^" ]*(?:jpg|png|gif|"))[^" <>]+~', $html, $links))
{ 
 print_r($links); 
}

上記の例では、$links 配列に以下が含まれている必要があります。

http://www.facebook.com, www.yahoo.com, https://www.aol.com 

.jpg 画像拡張子が含まれているため、Google は省略されています。このような画像を $html に追加すると、問題が発生します。

<img src="http://www.google.com/image%201.jpg">

パーセント記号によって preg_match が URL を分解し、次の「リンク」を抽出するようです。

http://www.google.com/image 

画像ではない URL のみを取得する方法はありますか? (URLに一般的に含まれる特殊文字が含まれている場合でも)

4

1 に答える 1

0

DOM を使用すると、HTML 文書の構造を認識することができます。あなたの場合、URLを取得したい部分を認識します。

  1. DOM を使用して HTML をロードする
  2. Xpath を使用してリンクの href 属性から URL を取得します (必要な場合のみ)
  3. Xpath を使用して DOM からテキスト ノードをフェッチする
  4. URL を照合するためにテキスト ノード値で RegEx を使用する

実装例を次に示します。

$html = <<<'HTML'
  <p>This is a test</p>
  <br>
  http://www.facebook.com
  <br>
  <img src="http://www.google.com/photo.jpg">
  www.yahoo.com 
  https://www.aol.com
  <a href="http://www.google.com">Link</a>
  <!-- http://comment.ingored.url -->
  <br>
HTML;

$urls = array();

$dom = new DOMDocument();
$dom->loadHtml($html);
$xpath = new DOMXpath($dom);

// fetch urls from link href attributes
foreach ($xpath->evaluate('//a[@href]/@href') as $href) {
  $urls[] = $href->value;
}

// fetch urls inside text nodes
$pattern = '(
 (?:(?:https?://)|(?:www\.))
 (?:[^"\'\\s]+)
)xS';
foreach ($xpath->evaluate('/html/body//text()') as $text) {
  $matches = array();
  preg_match_all($pattern, $text->nodeValue, $matches);
  foreach ($matches[0] as $href) {
    $urls[] = $href;
  }
}

var_dump($urls);

出力:

array(4) {
  [0]=>
  string(21) "http://www.google.com"
  [1]=>
  string(23) "http://www.facebook.com"
  [2]=>
  string(13) "www.yahoo.com"
  [3]=>
  string(19) "https://www.aol.com"
}
于 2013-11-21T21:05:14.280 に答える