phpの正規表現で、

htmlソース内の「A」タグによるリンクを
urlencodeしたいと思っています。

初めのリンクだけや、最後の文字まで .+ で見て行ったりして、
なかなかうまくいきません。

htmlソース内のAタグのリンクを、
全てurlencodeする正規表現を実現するにあたって
アドバイス頂けると助かります。

回答の条件
  • 1人5回まで
  • 登録:2007/08/08 17:19:04
  • 終了:2007/08/13 13:14:23

回答(3件)

id:Yota No.1

Yota回答回数453ベストアンサー獲得回数282007/08/08 20:23:15

ポイント25pt

<?php

mb_regex_encoding("UTF-8") ;

$str = '<a href="http://こんにちは赤ちゃん.html">赤ちゃん</a>' ;

// $pattern = "<a href=.+([一-龠|ぁ-ん|ァ-ヴー]+)[^<]+>";

$pattern = "/(<a href=\"http:\/\/)([一-龠|ぁ-ん|ァ-ヴー]+)([^<]+>)/";

// mb_ereg ( $pattern, $str ,$regs ) ;

// print_r($regs) ;

preg_match_all($pattern,$str,$matches) ;

// print_r($matches[0]) ;

$replacement = '$1'. urlencode('$2') .'$3';

for($i = 0 ;$i < count($matches[0]) ;$i++ ) {

$matches_r[] = preg_replace($pattern,$replacement,$matches[0][$i]) ;

}

// print_r($matches_r);

echo str_replace($matches[0],$matches_r,$str) ;


?>

id:onigirin

どうもありがとうございます。

Aタグの開始と閉じる間に<B>等、

他のタグが入るとダメでした・・・。

2007/08/09 02:58:47
id:tezcello No.2

tezcello回答回数460ベストアンサー獲得回数692007/08/09 00:20:51

ポイント50pt

過去の質問の続きの様なので、それらを織り込んでみました。

中途半端になっていたらゴメンナサイ。

// 後で使うので読み込み先のURLを変数に入れておく
$url0 = 'http://www.hatena.ne.jp/';
$html = file_get_contents($url0);

// 念の為、UTF-8に変換
$html = mb_convert_encoding($html, 'UTF-8', 'auto');
// スクリプト中にURLがある場合を考慮
$html = preg_replace('!<script.*?>.*?</script.*?>!is', '', $html) ;

// strip_tags() ではうまくいかなかったので、aタグのみを抜き出すようにしました
// リンクが文字列だけではなく、イメージの場合も考慮
// 冗長な所があるかもしれません
preg_match_all('/<a href=["\'](((https?:\/\/)?([^"\'?]*))((\?)([^"\']+))?)["\'][^>]*>(([^<]+)|((<img[^>]*src=")([^"\']+)("[^>]*>)))<\/a>/', $html, $res,PREG_SET_ORDER);

// var_dump($res);

foreach($res as $r){
  // URLが不完全な場合、先頭に追加する。
  // ただし、最初のURLがディレクトリまで含んでいる場合はもう少しチャンと対策する必要有り
  $url = preg_replace('/^\//', "$url0", $r[2]);
  if ($r[7]){
    // この中身を作っている所で力尽きましたごめんなさい。
    // 方向としては、$r[7]にパラメータ群が格納されているので、それぞれに分解し、
    // 必要な部分をエンコードして連結し直します。
    $encrd = urlencode($r[7]);
    $url .= '?'.$encrd;
  }

// 以下は不要かも知れませんが、リンクを示す文字列あるいは画像のURLを取り出します
  if ($r[9]){
    // 文字によるリンクの場合はその文字列が $r[9] に格納されている
    $itm = $r[9];
  }else{
    // 画像のURLは,$r[11]$r[12]$r[13] に分かれて格納されている
    $adr = preg_replace('/^\//', $url0, $r[12]);
    $itm = $r[11].$adr.$r[13];
  }
  // $lst に結果を格納します
  $lst[] = array('url'=>$encrd, 'itm'=>$itm);
}
id:onigirin

どうもありがとうございます。

<a href=xxx>なんた<B>ら</B>だよ</a>

というように、タグ間に、font等の別タグがあると、ダメでした・・・。

</a>でない言葉の連続、で試みようとしましたが、

http://www.kt.rim.or.jp/~kbk/regex/regex.html#CCLASS

ここを見ると、なかなか厳しいようですね・・・。

質問文で書き足りなかったのですが、

元のURLをurlencodeしたものに「置換」しようと思ってます。

preg_replaceだけで、頂いた正規表現でなんとかできないか頑張ってみましたが、

ちょっと今回は山が大きい感じです。。。

2007/08/09 02:57:31
id:Yota No.3

Yota回答回数453ベストアンサー獲得回数282007/08/09 10:09:26

ポイント25pt

<?php

$html = '<a href=http://konichiwa.com/こんにちは赤ちゃん.html>赤ちゃん<b>こんにちは</b></a><br/>' ;

$html .= '<a href=http://konnichiwa.akachian.com/hoge/赤ちゃんこんにちは.htm><b>こんにちは</b><b>赤ちゃん</b></a>' ;

$html .= '<br/><a href="http://konnichiwa.akachian.com/hoge/foo.html">foo</a>' ;

$pattern = "/(<a[^一-龠|ぁ-ん|ァ-ヴー]+)([一-龠|ぁ-ん|ァ-ヴー]+)([^>]*>)/e";

$replace = "'$1'. urlencode('$2') .'$3'";

echo preg_replace($pattern,$replace,$html) ;

?>

  • id:kn1967
    回答拒否数による制限にひっかかって回答出来ない人多いんだよね。
    んで、前回の続き? http://q.hatena.ne.jp/1186496028

    (1)
    .+ だと改行文字まで到達してしまいますので
    [^¥"]+ などにしてみてください。

    [^a] と書けばa以外という意味になりますし
    [^>] と書けば>以外という意味になります。
    [^ は後に続く文字以外という使い方になりますので覚えておいてください。

    ※ ¥は本来半角ですが文字化けするので全角で書いてます。

    (2)
    複数のキーワードが含まれている場合は
      id=ほにゃほにゃ&msg=ほげほげ
    という形となりますので
    preg_match_allで xx=[^¥"\&]+ といったような形で抜き出せば良いでしょう。
  • id:onigirin
    どうもありがとうございます。
    回答数が多くなると、そうなるのですね・・・。
    自分も拒否数が増えてきたのか、回答できないのがあり寂しいです。
    拒否数なくしておきました!


    前回の続きみたいなものです。
    「~以外」をうまく組み込みたいのですが、
    なかなか思い通りに動かなくて・・・。

    .+を修正して、もう少し試行錯誤してみます。
  • id:tezcello
    元になるHTMLのサンプルを示していただけませんか?
    NGのチェックが出来ますので。

    正規表現で特定の文字列以外とマッチするのは難しいです。
    大抵の場合、それ以外の方法を考えた方が早いです。

    そこで、+、*が最長一致してしまうのに困っていらっしゃるようですが、最短一致という方法もありますよ。
    http://www.php.net/manual/ja/reference.pcre.pattern.syntax.php
    中ほどの「繰り返し」の項をご覧下さい。


    で、プロクシののようなものをお考えの様子ですので、少し変更して a タグで囲まれた部分を単純に抜き出すだけにしてみました。

    preg_match_all('/<a href=["\']([^"\']*)["\'][^>]*>(.*?)<\/a>/', $html, $res,PREG_SET_ORDER);

    $res[][0] aタグ全て(パターンに一致した全て)
    $res[][1] リンク先アドレス
    $res[][2] aタグに囲まれた部分

    となるので、あとは必要に応じて編集するという感じでどうでしょう?
  • id:Yota
    回答3ですがちょっと間違えました。
    $html = '<a href="http://konichiwa.com/こんにちは赤ちゃん.html">赤ちゃん<b>こんにちは</b></a><br/>' ;
    $html .= '<a href="http://konnichiwa.akachian.com/hoge/赤ちゃんこんにちは.htm"><b>こんにちは</b><b>赤ちゃん</b></a>' ;
    $html .= '<br/><a href="http://konnichiwa.akachian.com/hoge/foo.html">foo</a>' ;

    $pattern = "/(<a[^一-龠|ぁ-ん|ァ-ヴー]+)([一-龠|ぁ-ん|ァ-ヴー]+)([^>]*>)/e";
    $replace = "'$1'. urlencode('$2') .'$3'";

    echo str_replace("\\","",preg_replace($pattern,$replace,$html)) ;
  • id:onigirin
    どうもありがとうございます。

    いろいろ試行錯誤した結果、無事目的を達成することができました!

    aタグの部分を抜き出す正規表現と、
    preg_matche_allで置換していくコードを組み合わせて
    実現することができました。


    $replace = "'$1'. urlencode('$2') .'$3'";

    これをpreg_replaceで行なおうとしていたのですが、
    どうも$2という文字列のみエンコードするか、
    エラーが出てうまくいきませんでした。
    これができればコードが短くなるので粘ってみましたが、
    無理だったので、for文の方を使わせていただきました。


    とても助かりました。
    どうもありがとうございました!

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません