PHPについて質問です。


現在オークションの統計サイトから、検索キーワードを入力した後のHTMLデータを抜き取るプログラムを作成しています。

しかし、うまく出来ず、時間があるかたおりましたら一度プログラムを見ていただけないでしょうか。お願いします。

プログラムの流れですが、以下の様になっています。

1:検索キーワードをデータベースから取得

2:ページ判定 ページが最後のページかどうかを判定をします。
ページが最後のページの場合は1に移動します。

3:ページ移動 

4:ページのHTMLを取得 

5:ページのHTMLをデータベースへ登録

6:ページ判定用の変数を作成

7:2に移動します。

自分で問題があると思うのは6の所です。

1回目、2回目と処理をして最後のページの登録処理をする場合うまく処理できていない気がします。

お手数をおかけしますが一度スクリプトを見ていただけたらと思います。

よろしくお願いします。

回答の条件
  • 1人2回まで
  • 登録:2009/10/02 20:31:15
  • 終了:2009/10/03 00:48:13

ベストアンサー

id:i4ooon No.1

regnif回答回数56ベストアンサー獲得回数202009/10/02 21:17:12

ポイント100pt

この処理⑥の問題は、仮にpreg_match_allで1ページ内に複数ヒットすることがあれば、

最後の$defの値が$hanteiに上書きされてしまうことが「可能性」として1つあります。

ここで確認ですが、

'一致する商品はありませんでした。'

は、

A:最終ページの場合、複数存在することがあるのか?

または、

B:最終ページでなくとも、存在する場合があるのか?

という最終ページの判断基準によって、判定ロジックも変わってきます。

そのオークションの統計サイトがどういう結果を返すのかもわかると良いのですが、

ここでは

A:の場合は、1つでも

'一致する商品はありませんでした。'

が存在するならという前提で回答すると、少し乱暴だけど

$hit = preg_match_all( ・・・);

とすれば、ヒット数が取れるので、

if($hit>0) break;

と続ければ良いです。最後のforeachも不要だし、

while($hantei !== '一致する商品はありませんでした。'){

while(1){

とか

while(true){

で充分です。


B:の場合は、正直ちょっと判断に困りますね。

そもそも正規表現検索をするためのpreg_match_allが本当に必要なのか?という

こともありますし、preg_match_allの挙動も少し自信がないので、Aでなかった

場合に、かつ正確な最終ページの条件を聞いてから回答するか考えます。

id:aiomock

ご回答ありがとうございます。

通常であれば

http://aucfan.com/search1/sya-q~a5a4a5c1a5eda1bca1a1a5b7a5e3a5c4...

このようなページになり

最後のページですと

http://aucfan.com/search1/sya-q~a5a4a5c1a5eda1bca1a1a5b7a5e3a5c4...

のようなページになります。

'一致する商品はありませんでした。' は 最終ページでひとつしか存在しません。


while(1){ だと条件式がなくて 回すことが出来るのですね。 

$hit = preg_match_all( ・・・);

if($hit>0) break;

も非常に便利だと思いました。ありがとうございます。

2009/10/02 21:30:20
  • id:aiomock
    全体の流れと 6 のところだけ見ていただけないでしょうか

    スクリプトは以下になります。


    <?php

    //①キーワードをデータベースから取得

    require "database_connect.php";

    $sql=mysql_query("select * from TEST");
    if(!$sql){echo "失敗です";}


    while ($row = mysql_fetch_array($sql, MYSQL_ASSOC)) {

    $query =''.$row["BRAND"].' '.$row["PRODUCT"].'';
    $brand=$row["BRAND"];
    $product=$row["PRODUCT"];
    $str = mb_convert_encoding($query, 'EUC-JP', 'auto');
    $str = bin2hex($str);
    $kaisuu=0;


    //②ページ判定

    //最後のページでない場合は次のページへ移動する。最後のページである場合は①へ移動する。
    //最後のページである条件は HTML文字の中に 一致する商品はありませんでした。 の文字列を含むページを見つけた場合。

    while($hantei !== '一致する商品はありませんでした。'){


    //③ページ移動

    $kaisuu=$kaisuu+1;
    $url = 'http://aucfan.com/search1/sya-q~'.$str.'-tl30d-ot1-p'.$kaisuu.'.html';


    //④HTML取得

    $html = '';
    $fp = fopen($url, 'r') or die("fopen");

    $meta_data = stream_get_meta_data($fp);
    foreach($meta_data['wrapper_data'] as $response) {

    if (substr(strtolower($response), 0, 10) == 'location: ') {
    $url = substr($response, 10);
    }
    }


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


    //⑤HTML登録


    require "database_connect.php";
    $time=Date("m-d");

    mysql_query("INSERT INTO `abcdefg`.`TEST2` (
    `TIME` ,`BRAND` ,`PRODUCT` ,`HTML`)
    VALUES ('".$time."','".$brand."','".$product."', '".$html."');");




    //⑥判定用の変数を作成 作成後②へ移動します。

    $aaa='';
    preg_match_all('|一致する商品はありませんでした。|',$html,$aaa);

    foreach ($aaa as $def){

    $hantei=$def;

    }


    }}


    ?>
  • id:aiomock
    変更して実行してみました。実行してみると前回同様無限ループみたいな状態になり未だうまくいきません。。
    問題がある部分は⑥部分だとは思うのですが、、。今一度確かめてみたいと思います。。


    <?php

    //①キーワードをデータベースから取得

    require "database_connect.php";

    $sql=mysql_query("select * from TEST");
    if(!$sql){echo "失敗です";}


    while ($row = mysql_fetch_array($sql, MYSQL_ASSOC)) {

    $query =''.$row["BRAND"].' '.$row["PRODUCT"].'';
    $brand=$row["BRAND"];
    $product=$row["PRODUCT"];
    $str = mb_convert_encoding($query, 'EUC-JP', 'auto');
    $str = bin2hex($str);
    $kaisuu=0;


    //②ページ判定

    //最後のページでない場合は次のページへ移動する。最後のページである場合は①へ移動する。
    //最後のページである条件は HTML文字の中に 一致する商品はありませんでした。 の文字列を含むページを見つけた場合。

    while(true){


    //③ページ移動

    $kaisuu=$kaisuu+1;
    $url = 'http://aucfan.com/search1/sya-q~'.$str.'-tl30d-ot1-p'.$kaisuu.'.html';


    //④HTML取得

    $html = '';
    $fp = fopen($url, 'r') or die("fopen");

    $meta_data = stream_get_meta_data($fp);
    foreach($meta_data['wrapper_data'] as $response) {

    if (substr(strtolower($response), 0, 10) == 'location: ') {
    $url = substr($response, 10);
    }
    }


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


    //⑤HTML登録


    require "database_connect.php";
    $time=Date("m-d");

    mysql_query("INSERT INTO `abcdefg`.`TEST2` (
    `TIME` ,`BRAND` ,`PRODUCT` ,`HTML`)
    VALUES ('".$time."','".$brand."','".$product."', '".$html."');");




    //⑥判定用の変数を作成 作成後②へ移動します。

    $hit=preg_match_all('|一致する商品はありませんでした。|',$html);

    if($hit>0) break;



    }


    }


    ?>
  • id:i4ooon
    $hit=preg_match_all('|一致する商品はありませんでした。|',$html);
    は元の
    $hit=preg_match_all('|一致する商品はありませんでした。|',$html,$aaa);
    が良いです。
    $aaaは結局中身を確認する必要はないんだけど、preg_match_allは
    第3引数までは省略できない仕様なので、エラーが発生してFALSEが
    $hitに代入されている可能性が高い。
    ということは、if($hit>0)は成立しないから無限ループ。
    http://www.php.net/manual/ja/function.preg-match-all.php

    つくづくpreg_match_allを使うロジックではないなーという感じだけど。

  • id:aiomock
    ご回答ありがとうございます。

    $hit=preg_match_all('|一致する商品はありませんでした。|',$html);



    $hit=preg_match_all('|一致する商品はありませんでした。|',$html,$aaa);

    に変更させていただきました。

    しかし、未だ無限ループが抜け出せない状況です。。

    他のところに問題がないかも調べて見ます。。

    なぜ抜け出せないのでしょう。。。

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

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

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

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