Neo Inspiration

  • Search

    • About Me

      • inspi 改め
        jakk@webアーキテクト(自称)
        php,javascript,seoなど
        得意技は extract();

  • カテゴリー

  • Ranking

  • Archive for 4 月, 2008

    ex_file_get_contents を作ったので。。

    金曜日, 4 月 25th, 2008

    前のエントリーで書いてた fsockopen のソースがひどいやつだったので
    ちゃんと動くように修正したので、一応。

    最初strippos使ってたんだけど、php4じゃ動かないから書き直したりして
    結局php4でも動くように。

    ちなみに
    ヘッダーからゴソっともってきてるので、
    html部分に出すのはワンクッションおいてください。

    https とか ssl はめんどくさくて非対応w

    /**
    * ex_file_get_contents:file_get_contentsの代替バージョン。
    *
    * @author jakk
    * @copyright 2008/04/25 neoinspirations
    * @param string $server 形式のURL
    * @param int $timeout タイムアウト秒数
    * @return 成功した場合 $urlのhtmlデータをstringで返す 失敗した場合 false

    Ex.
    $html = ex_file_get_contents($url);

    */
    function ex_file_get_contents($uri=”,$timeout=10){
    if (!empty($uri)) {
    $uri = strtr($uri,array(”http://”=>”"));
    $domain = strpos(strtolower($uri),strtolower(’/'),3);

    if ($domain !== false) {
    $server = substr($uri, 0, $domain);
    $file = substr($uri, $domain);
    } else {
    $server = $uri;
    $file = “/”;
    }

    $fp = @fsockopen($server, 80,$errno, $errstr, $timeout);
    if ($fp) {
    $out = “GET ” . $file . ” HTTP/1.1\r\n”;
    $out .= “Host: ” . $server . “\r\n”;
    $out .= “Connection: Close\r\n\r\n”;

    @fwrite($fp, $out);

    $data = ”;
    while ($eofCheck=@fgets($fp,1024)) {
    $data .= $eofCheck;
    }
    @fclose($fp);
    } else {
    return false;
    }
    } else {
    return false;
    }
    return $data;
    }

    php の file_get_contents で true も false も返ってこない

    木曜日, 4 月 24th, 2008

    特定のURLでfile_get_contents で true も false も返ってこない現象があって
    困っていたのでその対策メモ

    現象

    単純に

    $html = file_get_contents($url);

    ってやるとタイムアウトすることがあって、
    それは
    ini_set(’default_socket_timeout’,3);
    ってやってもダメなパターン。

    問題はタイムアウトじゃない?

    file_get_contentsがだめでもこれ以上切り分けできないので、
    処理を1個づつかくために fsockopen 使ってみたけどやっぱりだめ。

    fsockopen がダメな時のソースはこんなかんじ。

    $fp = fsockopen($server,80,$errno,$errstr,$timeout);
    if($fp){
      while(!feof($fp)){
        $data .= fread($fp, 1024);
      }
    }
    echo $data;

    で こっから1こづつ切り分けていくと
    どうも

    while(!feof($fp)){
      $data .= fread($fp,1024);
    }

    ここが無限ループになってるらしい。

    file_get_contentsのCソースまでは追いきれないので
    (Cソース探したけどどこにあるかわからなくて)
    カンですが、file_get_contents も同じ感じの処理をしていて、
    feof のとこで詰まってるんじゃないかと。
    だとしたら、ソケットの問題じゃないので、default_socket_timeout を指定しても意味なかったってわけです。

    こうやって解決

    問題が無限ループだったので php feof で検索したら・・・

    関連検索: php feof 無限ループ, php feof fgets

    同じ問題で詰まった人がいっぱいいるw!

    で見ていくと

    http://jp.php.net/feof
    無効なファイルポインタを渡した場合、無限ループに陥ることがあります。 なぜなら EOF が TRUE を返すことができないからです。

    ということらしい。

    つまり feof が true を返さないので、feof で判定するのはダメなわけだ。
    おそらく何らかの形でEOFが受信できない場合も trueが返らないんだろう。。
    なので feof じゃなくて fread が成功したかで判定するように変更

    $fp = fsockopen($server,80,$errno,$errstr,$timeout);
    if($fp){
    while($eof_check= fread($fp,1024)){
      $data .= $eof_check;
    }
    }
    echo $data;

    したら うまくいった!

    ってことで

    結局こんな感じの関数作って対処しました。

    function ex_file_get_contents($server=”,$timeout=10){
      $data = ”;
      if(isset($server)){
        $fp = @fsockopen($server, 80,$errno, $errstr, $timeout);
        if($fp){
          while($eof_check=@fread($fp, 1024)){
            $data .= $eof_check;
          }
          @fclose($fp);
        }else{
          return false;
        }
      }else{
        return false;
      }
      return $data;
    }

    Ngramを利用したページ類似度チェッカー+Ngram計算のphpクラス

    月曜日, 4 月 21st, 2008

    Ngramを利用したページ類似度チェッカー+Ngram計算のphpクラス

    Ngram

    まあ何がやりたかったって
    スパムチェック的な類似度チェッカーです。

    こんなかんじ。
    類似度チェッカー

    全く違うURLだと5~10%くらいになって
    ちょっと関係がある(リンク紹介してたり)すると20%くらいかな
    同じブログの違う記事とかだと40%くらいになって
    60%超えたらかなり似てるページってかんじのラインです。

    例えば wikiの アイスランドのページとアイルランドのページとかでやると
    重複度77%とかになります。

    Googleは言語にとらわれない解析方法を使っているとのことなので、
    高確率で、どっかにNgramは使ってると思うので、
    デュプリケイトコンテンツとかの参考に使えるかなーと。

    一応ソース公開

    たいしたものじゃないんですが、たいしたものじゃないだけに
    ソースくらい出しとけというお話です。

    アルゴリズム的には単純に
    ・URLからタグを引っぺがす
    ・出てきたテキストのNgram(3)を抽出
    ・2個URLの共通項を出す(php の array_instersect 使っただけ)
    ・(共通項の数 / Ngram(3)の個数) %

    まあなんか array_intersect とarray_diff がま逆の動きをしないので
    あやしいんですが。。
    ソースを追うのもめんどいので後で検証。

    使い方

    Newして(引数でNgram2,3とかコントロール)
    RunメソッドにURL突っ込むだけです。

    こんなかんじです。
    (以下見やすくする為にインデントを全角スペースに変換してあります。)

    $Ngram = new CreateNgram();
    if($Ngram->run(”http://neoinspire.net/archives/92″,”http://neoinspire.net/archives/90″)){
      print($Ngram->result);
      echo”<pre>”;
      print_r($Ngram->mainNgram);
      print_r($Ngram->checkNgram);
      echo”</pre>”;
    }else{
      echo “対象のURLを解析できませんでした。”;
    }

    以下ソースです。コピペしてUTF8で保存してください。

    <?php
    /*
    *2つのURLのNgramを比較して類似度を出すクラス
    *引数を一つで出した場合単純に対象URLのNgramを抽出する
    */
    Class CreateNgram{

      var $mainNgram; //第一引数URLのNgram
      var $checkNgram; //第二引数URLのNgram

      var $ngram; //Ngramをいくつでやるか
      var $result; //類似度

      function CreateNgram($ngram=3){
        $this->ngram = $ngram;
      }

      function run($mainUrl=null,$checkUrl=null){
        if(!empty($mainUrl) && !empty($checkUrl)){
          if($mainHtml = mb_convert_encoding(@file_get_contents($mainUrl), ‘UTF-8′, ‘auto’))
            $this->mainNgram = $this->_ngram($this->_solid($mainHtml));

          if($checkHtml = mb_convert_encoding(@file_get_contents($checkUrl), ‘UTF-8′, ‘auto’))
            $this->checkNgram = $this->_ngram($this->_solid($checkHtml));

          if(!empty($this->mainNgram) && !empty($this->checkNgram)){
            $mainResult = @array_intersect($this->mainNgram,$this->checkNgram);
            $checkResult = @array_intersect($this->checkNgram,$this->mainNgram);
            $result1 = count($mainResult);
            $result2 = count($checkResult);
            $cnt1 = count($this->mainNgram);
            $cnt2 = count($this->checkNgram);
            $this->result = @round((($result1 + $result2) / ($cnt1 + $cnt2)),3);
            return true;
          }else{
            return false;
          }
        }else{
          return false;
        }
      }

      function _ngram($query=null){
        $query = trim($query);
        if(!empty($query)){
          $len = mb_strlen($query,’UTF-8′);
          for($i=0; $i< $len; $i++){
            $buf = trim(mb_substr($query, $i, $this->ngram,’UTF-8′));
            if(isset($buf))$ngrams[] = $buf;
          }
        }else{
          $ngrams = “”;
        }
        return $ngrams;
      }

      function _solid($html=null){
        if($html){
          $pat[]=”/<script.+?\/script>/is”;
          $pat[]=”/<style.+?\/style>/is”;
          $pat[]=”/<\!\-\-.+?\-\->/is”;
          $pat[]=”/<.*?>/is”;
          $pat[]=”/\r|\n|\s/is”;
          $rep=”";
          return preg_replace($pat,$rep,$html);
        }else{
          return “”;
        }
      }
    }
    ?>

    2008/07/05 03:32:36