各ページからタイトルと日付を取得 - PHPプロ!Q&A掲示板

1478

  • 0P

各ページからタイトルと日付を取得

質問日時 / 2008年9月3日 23:58    回答数 / 17件

Questioner:  Memory  このエントリーをはてなブックマークに追加 

キーワード / キーワードが設定されていません

以前の回答はどうもありがとうございました。
分け合って、1つ1つのページからタイトルを抽出したいと思い、
自分なりに改造したのですが、エラーが出てしまいます。。。
http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice&idx=
こちらのidx=の後に数字が来るわけで、その数字を変数で出し、それを代入しました。
それで、例えば34615の記事を表示したとします。
http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice&idx=34615
こうなるわけです。タイトルはフルで表示されるので、1つ1つのページから取得したいと思いました。
また、以前は画像や閲覧数を載せてくれていただいたのですが、 日付とタイトルだけで構いません。
尚、今回試したページは
http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice&idx=34615
です。php暦は1週間で変数しか使えません。ただ、関数やif-elseif-elseなどde
どのような形でどのようにしたいかはアバウトですがわかります。

元ソースの少し改造

  1. <?php 
  2. // 念の為、言語、エンコードの指定 
  3. //mb_internal_encoding('ja'); 
  4. //mb_language('utf-8'); 
  5. //mb_regex_encoding('shift-JIS'); 
  6.  
  7. //ログファイルへの階層チェックなしでの記述
  8. $log_addres = 'Handle/Source/Dat/info.log';
  9. $Rows_Line = ' | ';
  10. $log = ''// 結果を納める変数の初期化 
  11.   
  12. // データの読込み 
  13. $str = file_get_contents('http://tenvi.nexon.co.jp/support/notice.asp')
  14.   
  15. // 目的の table タグのデータのみ抽出 
  16. preg_match('/<table.*?id="info-tbl">(.*?)<\/table>/s'$str$res)
  17.   
  18. // 1行分のデータは </tr> で終わるので、これを目印に1行毎に配列に納める 
  19. $src = explode('</tr>'$res[1])
  20.   
  21. // 配列の各要素に1行分のデータがあるので、各要素ごとに必要データを抜き出す作業をする 
  22. foreach($src as $s){ 
  23.   // アイコンのアドレスの抜き出し 
  24.   // 失敗した時=関係ない行であったとして、読み飛ばす(次の配列要素を処理する) 
  25.   if (!preg_match('/<td class="info-icn"><img src="(.+?)"/'$s$res)) continue
  26.   $icon = $res[1]
  27.   
  28.   // ページアドレスとタイトルの抜き出し 
  29.   preg_match('/<td class="info-txt"><a href="(.+?)">(.+?)<\/a>/'$s$res)
  30.   $page = $res[1]
  31.   $title = trim($res[2]);  // タグで括られた部分の余分な空白を削除してから代入する 
  32.   
  33.   // 日付の抜き出し 
  34.   preg_match('/<td class="info-date">(.+?)<\/td>/'$s$res)
  35.   $date = trim($res[1])
  36.   
  37.   // 閲覧数の抜き出し 
  38.   preg_match('/<td class="info-view">(\d+)<\/td>/'$s$res)
  39.   $view = $res[1]
  40.   
  41.   // 結果変数に追加する
  42.   if (mb_strlen($title) > 35) {
  43.     // 35 文字以上の場合
  44.     $title = mb_substr($title035) . '...';
  45.   }
  46.   //2バイト数値は利用不可と確認。1バイト以内で収める事。
  47.   $log .= '20'.$date.$Rows_Line.'<a href="http://tenvi.nexon.co.jp'.$page.'">'.$title.'</a><!--約('.$view.")人が閲覧--><br>\n"
  48.  
  49. } 
  50.  
  51. //UTF-8 から Euc-Jpに変換する
  52. mb_convert_variables("EUC-JP""utf-8"$log);
  53.  
  54. // ファイルのオープンと書き出し 
  55. $fp = fopen("$log_addres"'w')
  56. $res = fwrite($fp$log)
  57. include("$log_addres");
  58. ?>

1つ1つのページからタイトルと日付を抽出しようと試みたソース。
  1. <?php 
  2. // 念の為、言語、エンコードの指定 
  3. //mb_internal_encoding('ja'); 
  4. //mb_language('utf-8'); 
  5. //mb_regex_encoding('shift-JIS'); 
  6.  
  7. //ログファイルへの階層チェックなしでの記述
  8. $Rows_Line = ' | ';
  9. $log = ''// 結果を納める変数の初期化 
  10.   
  11. // データの読込み 
  12. $str = file_get_contents('http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice&idx=' . $number . '')
  13.  
  14. // 1行分のデータは </tr> で終わるので、これを目印に1行毎に配列に納める 
  15. $src = explode('</div>'$res[1])
  16. $table = explode('</tr>'$res[1])
  17.  
  18. // 目的の table タグのデータのみ抽出 
  19. preg_match('/<div id="info-cont">(.*?)<\/div>/s'$str$res)
  20.  
  21. // 配列の各要素に1行分のデータがあるので、各要素ごとに必要データを抜き出す作業をする 
  22. foreach($src as $s){ 
  23.   // アイコンのアドレスの抜き出し 
  24.   // 失敗した時=関係ない行であったとして、読み飛ばす(次の配列要素を処理する) 
  25.   //if (!preg_match('/<td class="info-icn"><img src="(.+?)"/', $s, $res)) continue; 
  26.   //$icon = $res[1]; 
  27.   
  28.   // タイトルの抜き出し 
  29.   if (!preg_match('/<h5 class="detail-ttl"><img src="(.+?)">(.+?)/'$s$res))
  30.   $icon = $res[1]
  31.   $titlea = $res[2];
  32.   
  33.   // 日付の抜き出し 
  34.   preg_match('/<p class="detail-view">(.+?)/'$s$res)
  35.   $date = trim($res[1])
  36.  
  37.   
  38.   // 閲覧数の抜き出し 
  39.   //preg_match('/<p class="detail-view">(\d+)<\/td>/', $s, $res); 
  40.   //$view = $res[1]; 
  41.   
  42.   // 結果変数に追加する
  43.   if (mb_strlen($title) > 35) {
  44.     // 35 文字以上の場合
  45.     $title = mb_substr($title035) . '...';
  46.   }
  47.   //2バイト数値は利用不可と確認。1バイト以内で収める事。
  48.   $log .= $date.$Rows_Line.'<a href="'.$str.'">'.$titlea.'</a><br>\n"; 
  49.  
  50.  
  51. // 目的の table タグのデータのみ抽出 
  52. preg_match('/<table border="0" cellpadding="0" cellspacing="0" id="info-tbl">(.*?)<\/table>/s', $str, $res);
  53.  
  54. // 配列の各要素に1行分のデータがあるので、各要素ごとに必要データを抜き出す作業をする 
  55. foreach($table as $s){ 
  56.   preg_match('/<td class="info-txt"><a href="/support/notice_view.asp?bid=tenvinotice&idx=(.+?)/', $s$res); 
  57.   $number = trim($res[1]); 
  58.  
  59. //UTF-8 から Euc-Jpに変換する
  60. mb_convert_variables("EUC-JP""utf-8"$log);
  61.  
  62. // ファイルのオープンと書き出し 
  63. $fp = fopen("test.log", 'w'); 
  64. $res = fwrite($fp$log); 
  65. include("test.log");
  66. ?>

上記のソースですと、1つのページから検索をみたいなんですが・・・

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┣A01tezcello> 1つ1つのページからタイトルを抽出したい どれ程
┃┗A01-1Memoryご返答ありがとうございます。 >> 1つ1つのペー
┃ ┗A01-1-1tezcello> 動いてます。エラーもでていません。 マニュアルに
┃  ┗A01-1-1-1Memoryご返答ありがとうございます。 一部修正してみました
┃   ┗A01-1-1-1-1tezcello> 行数が少ないほど読み込むのが早くなると思ったので
┃    ┗A01-1-1-1-1-1Memoryそこは自分自身のコメントで、 2バイト以降の数値を
┃     ┗A01-1-1-1-1-1-1tezcello2バイト以降の数値っていうと、-128 より小さく、 12
┃      ┗A01-1-1-1-1-1-1-1MemoryエンコードはEuc-jp、編集方法もEuc-jpです。 話が
┃       ┗A01-1-1-1-1-1-1-1-1tezcello> エンコードはEuc-jp、編集方法もEuc-jpです。 うち
┗A02signalこの手のスクリプトは勉強にはもってこいです。 基
 ┗A02-1Memory>>tezcello様 返答が遅くなって申し訳ございません・・
  ┗A02-1-1tezcello> utf-8だと文字化けしちゃうので 全体を EUC-JP で
   ┗A02-1-1-1Memoryご返答ありがとうございます。 UTF-8ではなく、初回
    ┣A02-1-1-1-1signalちなみに、このサンプルスクリプトはロリポで動作確認
    ┗A02-1-1-1-2tezcello> ロリポップサーバーへと、環境はどうなっているのか
     ┗A02-1-1-1-2-1Memory現状では、何の支障もありません。 もちろん火狐やOp
      ┗A02-1-1-1-2-1-1tezcello> 関係ない話になりますが... 1つのスレッドは1つ

回答一覧

並び替え:

A01
answerertezcello [9月4日 01:04]

> 1つ1つのページからタイトルを抽出したい
どれ程の頻度でこのスクリプトを実行しようとしているのか不明ですが、毎回全ての記事を調べにいくのでは相手のサーバの負荷増となるので避けるべきでは無いでしょうか?
僕なら、毎日全データを取りに来る利用者は、IP 等でアクセス拒否するかも知れません。

更に、データ利用の違法性も解決出来ていないと、それが切っ掛けでサイト閉鎖に追い込まれるかも知れませんよ。

「少し改造」のスクリプトは、これで上手く動いていますか?
ファイルをクローズする前に、include() しているので、何も読み込めていない可能性が高いです。
   ただ、その為エラーが出てないと思います。
   include するなら、PHPとして意味のあるスクリプトでないとエラーになると思います。

"$log_addres" は、 " (二重引用符) の意味が無いですね。単に $log_addres とすればいいです。


「1つ1つ...」のスクリプトは、エラーが盛大に出るでしょうね。
 ' (単一引用符) " (二重引用符) の組み合わせがおかしいです。

エラーメッセージは、割合簡単な英語です。毛嫌いせずに読む努力をすれば、何となく分かりますよ。

この意見に回答する

ツリーへ TOPへ

A01-1
replyerMemory [9月4日 08:02]

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

>> 1つ1つのページからタイトルを抽出したい
>どれ程の頻度でこのスクリプトを実行しようとしているのか不明ですが、毎回全ての記事を調べにいくので>は相手のサーバの負荷増となるので避けるべきでは無いでしょうか?
>僕なら、毎日全データを取りに来る利用者は、IP 等でアクセス拒否するかも知れません。
>更に、データ利用の違法性も解決出来ていないと、それが切っ掛けでサイト閉鎖に追い込まれるかも知れませんよ。

データーを取得しているのはネクソン社オンラインゲームのTENVIのお知らせです。

>「少し改造」のスクリプトは、これで上手く動いていますか?
>ファイルをクローズする前に、include() しているので、何も読み込めていない可能性が高いです。
>   ただ、その為エラーが出てないと思います。
>   include するなら、PHPとして意味のあるスクリプトでないとエラーになると思います。

>"$log_addres" は、 " (二重引用符) の意味が無いですね。単に $log_addres とすればいいです。

動いてます。エラーもでていません。インクルードを利用した訳は、そのまま改造したphpへアクセスをしてもログが表示されないので、インクルードで呼び出しました。

実際$log_addresで書き込んだ、ファイルにそのままアクセスしても、
向こう側の更新を収集しないので、 php側でする必要がありました。

また、各ページからのタイトル自動収集はしてもいいか、ネクソン側にメールを送りましたので、
結果がきしだし、お知らせいたします。

この意見に回答する

ツリーへ TOPへ

A01-1-1 参考になった
replyertezcello [9月4日 13:49]

> 動いてます。エラーもでていません。
マニュアルによると
「ファイルが読み込まれるときには、読み込まれるファイルの先頭で PHPモードを抜けてHTMLモードになり、最後に再びPHPモードに戻ります。」
とあるので、HTMLファイルをインクルードしても問題ないんですね。勉強になりました。

> インクルードを利用した訳は、そのまま改造したphpへアクセスをしてもログが表示されないので、インクルードで呼び出しました。
単に表示したいだけなら、既に変数 $log にその内容は収められているので、インクルードするまでも無く
  1. print $log;
すればOKです。

このログファイルは何のために作っていますか?
include() を使って表示するためなら、上記の通り不要です。ですが、お知らせ関連の全ページを毎回スキャンされるのは本家サーバからすると大迷惑です。

表示速度の向上(毎回本家にアクセスして、必要事項を抽出し、ログファイルに書き出すのは時間が掛かる)と、本家サーバへのアクセス過多への配慮なら、そのように変更すべきところがいくつかありそうです。
   本家サーバへのアクセスを抑える仕組みや、ログの残し方等々


引用符について説明が足らなかったかもしれませんので、補足を。
シングル( ' )とダブル( " )があり、ダブルの中では変数をその値と置き換えてくれます。
マニュアルにも「文字列を指定する最も簡単な方法」とある通り、代入や関数の引数など、単に文字列を括るならシングルが最適です。
変数があるかどうかを調べる必要もないので、その分処理が早いでしょう。
日本語を扱うときはエスケープ等が発生しないので、シングルの方がより安全と思います。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1
replyerMemory [9月4日 14:37] (最終編集:9月4日 15:18)

ご返答ありがとうございます。
一部修正してみました。行数が少ないほど読み込むのが早くなると思ったので
コメント行を一部削除しました。

  1. <?php 
  2. $log = ''// 結果を納める変数の初期化 
  3.   
  4. // データの読込み 
  5. $str = file_get_contents('http://tenvi.nexon.co.jp/support/notice.asp')
  6.   
  7. // 目的の table タグのデータのみ抽出 
  8. preg_match('/<table.*?id="info-tbl">(.*?)<\/table>/s'$str$res)
  9.   
  10. // 1行分のデータは </tr> で終わるので、これを目印に1行毎に配列に納める 
  11. $src = explode('</tr>'$res[1])
  12.   
  13. // 配列の各要素に1行分のデータがあるので、各要素ごとに必要データを抜き出す作業をする 
  14. foreach($src as $s){ 
  15.   // アイコンのアドレスの抜き出し 
  16.   // 失敗した時=関係ない行であったとして、読み飛ばす(次の配列要素を処理する) 
  17.   if (!preg_match('/<td class="info-icn"><img src="(.+?)"/'$s$res)) continue
  18.   $icon = $res[1]
  19.   
  20.   // ページアドレスとタイトルの抜き出し 
  21.   preg_match('/<td class="info-txt"><a href="(.+?)">(.+?)<\/a>/'$s$res)
  22.   $page = $res[1]
  23.   $title = trim($res[2]);  // タグで括られた部分の余分な空白を削除してから代入する 
  24.   
  25.   // 日付の抜き出し 
  26.   preg_match('/<td class="info-date">(.+?)<\/td>/'$s$res)
  27.   $date = trim($res[1])
  28.   
  29.   // 閲覧数の抜き出し 
  30.   preg_match('/<td class="info-view">(\d+)<\/td>/'$s$res)
  31.   $view = $res[1]
  32.   
  33.   // 結果変数に追加する
  34.   if (mb_strlen($title) > 35) {
  35.     // 35 文字以上の場合
  36.     $title = mb_substr($title035) . '...';
  37.   }
  38.   //2バイト数値は利用不可と確認。1バイト以内で収める事。
  39.   $log .= '20'.$date.' | <a href="http://tenvi.nexon.co.jp'.$page.'">'.$title."</a><br>\n"
  40.  
  41. } 
  42.  
  43. //UTF-8 から Euc-Jpに変換する
  44. mb_convert_variables("EUC-JP""utf-8"$log);
  45.  
  46. //出力
  47. print $log;
  48. ?>

こんなところですか?
サーバーの負担に関しましては、
http://www.nexon.co.jp/JP/Page/NX.aspx?URL=guide/agreement_authorship
こちらにも書いてあるとおり、「引用」としてならば、利用可能となっております。
つまりは、ネクソンホームページ内での文章・テキスト・画像は許容範囲ならば利用していい事となっております。
利用規約にもう一度目を通しましたが、禁止事項などには一切負担をかけてはいけないと書いてあるので、問題ないかと思います。

http://www.nexon.co.jp/JP/Page/NX.aspx?URL=guide/agreement_agreement

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1
replyertezcello [9月4日 17:41]

> 行数が少ないほど読み込むのが早くなると思ったので
コメントの量が数キロ~数メガという巨大なサイズでなければ、ほとんど変わらないそうです。

僕が書いたコメントは、説明するためだけのモノなので、それらの方が不要のように思います。


> //2バイト数値は利用不可と確認。1バイト以内で収める事。
僕にはこのコメントの意味が理解できませんでした。


> つまりは、ネクソンホームページ内での文章・テキスト・画像は許容範囲ならば利用していい事となっております。
これは違っていませんか?

「ご利用にあたって」のページに、
権利者に無断で転載や複製、放送、公衆送信、翻訳、販売、貸与などの利用をすることはできません。インターネットや雑誌上などで、データや画像などを使用する場合、下記の点にご留意いただくことにより掲載が可能となります。

と記述があります。
サイトのデータを拾ってきて、自分のページに掲載する事は、上記の「公衆送信」に当たるので基本的にNGであると書いてあります。

「下記の点に...」で示されているのは、ゲーム内の画像と文章についてのみですね。
これらについては引用の範囲内で「無断で」使えます。
それ以外のデータについては記述がありませんので、無断では使えません。

既に連絡をとっていらっしゃるようですが、利用の許可が得られれば当然掲載は可能です。

ここはPHPの掲示板なので、これ以上この件に関して議論するつもりはありません。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1
replyerMemory [9月4日 18:33]

そこは自分自身のコメントで、
2バイト以降の数値を使うと?で表示されたので、英数字及び1バイトの数値しか利用できませんよ
というメモです。

今後は自分で改造して以降と思うんですが・・・。
でも、一番手っ取り早いのは、TENVI側がRSSで配信してくれれば
それ相応の対応ができるんですけどね・・・。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1
replyertezcello [9月4日 21:03]

2バイト以降の数値っていうと、-128 より小さく、 127 より大きい値って事のはずだけど、
> 英数字及び1バイトの数値しか
から、2バイト以上で表される文字(=マルチバイトの文字)、つまり日本語って事だろうと。

それが入るとおかしくなる所は、どこだろうか?
2バイト文字をやめて1バイト文字を使っているはずだけど...
$date の後ろの " | " くらいだろうけど、なんでダメかなぁ って思ってました。


?が表示されるのは、文字のエンコードがHTTPヘッダと合っていない場合によくあるように思います。
PHPから出力すると、PHPの内部エンコードがHTTPヘッダとして出力されるので、スクリプトを記述しているエンコードとPHP内部エンコードが違うと、よくこういう文字化けを起こします。
Apache の設定に因っても起きる事があります。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1
replyerMemory [9月4日 22:10]

エンコードはEuc-jp、編集方法もEuc-jpです。

話が変わりますが、
ネクソンからのメールによりますと、
著作権ガイドラインに則っていれば、いいとの事です。
データー収集に関しましては、あまり負担をかけない又は
正規な書き方。どちらが正しいかわかりませんが・・・。

いろんな人のアドバイスを得て、再度file_get_contentsでフルタイトルの記載されているページ
を変数を用いて解析しようとしましたが、無理でした。

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1218920042

こちらに詳しく書いてあります。

この意見に回答する

ツリーへ TOPへ

A01-1-1-1-1-1-1-1-1
replyertezcello [9月4日 23:35]

> エンコードはEuc-jp、編集方法もEuc-jpです。
うちの環境だと、" | " のところに日本語をいれても全然OKなので、環境依存(=PHPの内部エンコードやスクリプトのエンコード等)だろうと思ってます。
因に、IE は HTTP ヘッダを無視するので、予想外の表示になる事があるように思います。


> いろんな人のアドバイスを得て...
ここ以外にも、同じ質問を他所でされていたのですね。マルチポストについてお調べください。


テスト時は
  1. ini_set(display_errors, 1);
  2. error_reporting(E_ALL);
をスクリプトの最初の方に入れておくと、エラーメッセージをたくさん出してくれて、デバッグし易いです。

これらは、(マニュアルにもありますが)本番時は削除してください。

この意見に回答する

ツリーへ TOPへ

A02
answerersignal [9月6日 12:14]

この手のスクリプトは勉強にはもってこいです。

基本的な構文はもちろん、ファイル操作、正規表現、日付、連想配列など
それなりに使えないと面白いものが作れません。


ということで、サンプル的なコードを書いてみました。

初回の動作は若干ヘビーですが、以降の動作は相手側に優しくなっています。
# いくらでも調整できますが、サンプルなので・・・

  1. <?php
  2. # このファイルは UTF-8 で保存すること
  3. header('Content-Type: text/html;charset=UTF-8');
  4.  
  5. # 取得したページの内容を保存するディレクトリ
  6. # Linux系であればパーミッションは「777」or「707」
  7. $datadir = './data';
  8.  
  9. # 更新日ファイルが存在しないとき
  10. if ( ! file_exists("{$datadir}/update") ) {
  11.   touch( "{$datadir}/update"time() - 24 * 60 * 60 )# 前日の日付で作成
  12.   chmod( "{$datadir}/update"0606 );
  13. }
  14.  
  15. # 取得済みページの取得
  16. $files = array();
  17. foreach ( glob("{$datadir}/*.dat") as $path ) {
  18.   $name = basename( $path'.dat' );
  19.   list( $date$id ) = explode( '_'$name );
  20.   $files[$id] = $path;
  21. }
  22.  
  23. # 一日に一回更新
  24. $now    = explode( '.'date('Y.m.d') );
  25. $limit  = date( 'Ymd'mktime( 000$now[1]$now[2] - 1$now[0] ) );
  26. $update = date( 'Ymd'filemtime("{$datadir}/update") );
  27. if ( $limit >= $update ) {
  28.  
  29.   # 全ページのIDを格納する
  30.   $list = array();
  31.  
  32.   # 一覧ページの取得
  33.   $p = 1;
  34.   while ( 1 ) {
  35.  
  36.     $buff = @file_get_contents("http://tenvi.nexon.co.jp/support/notice.asp?p={$p}");
  37.     if ( ! $buff ) {
  38.       print "一覧ページを取得できません";
  39.       exit;
  40.     }
  41.  
  42.     # 記事一覧よりIDの抽出
  43.     if ( ! preg_match_all( '/<td class="info-txt"><a href=".*?idx=(\d+).*?">/'$buff$match ) ) {
  44.       break;
  45.     }
  46.  
  47.     foreach ( $match[1] as $id ) $list[$id] = true;
  48.  
  49.     $p ++;
  50.   }
  51.  
  52.   # 各ページの取得
  53.   foreach ( $list as $id => $flag ) {
  54.     if ( file_exists( $files[$id] ) ) continue;
  55.  
  56.     $buff = @file_get_contents("http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice&idx={$id}");
  57.     if ( ! $buff ) continue;
  58.  
  59.     $data = array( 'id' => $id );
  60.  
  61.     # タイトルの抽出
  62.     if ( ! preg_match( '/<h5 class="detail-ttl"[^>]*?><img[^>]+>(.+?)<\/h5>/'$buff$match ) ) continue;
  63.     $data['title'] = $match[1];
  64.  
  65.     # 日付の抽出
  66.     if ( ! preg_match( '/<p class="detail-view"[^>]*?>(\d+)\D+(\d+)\D+(\d+).*?<\/p>/'$buff$match ) ) continue;
  67.     $data['date'] = mktime( 000$match[2]$match[3]$match[1] );
  68.  
  69.     # コメントの抽出
  70.     if ( ! preg_match( '/<p class="detail-txt"[^>]*?>(.+?)<\/p>/'$buff$match ) ) continue;
  71.     $data['comment'] = str_replace( '<br>'"\n"$match[1] );
  72.  
  73.     # データの保存
  74.     $path = sprintf( '%s/%s_%s.dat'$datadirdate( 'Ymd'$data['date'] )$data['id'] );
  75.     $fp = @fopen( $path'w' );
  76.     if ( ! $fp ) {
  77.       print "データを作成できません";
  78.       exit;
  79.     }
  80.     fwrite( $fpserialize( $data ) );
  81.     fclose( $fp );
  82.     chmod( $path0606 );
  83.  
  84.     $files[$data['id']] = $path;
  85.  
  86.   }
  87.  
  88.   touch("{$datadir}/update");
  89. }
  90.  
  91. # ここからは好きなように
  92. $id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0;
  93. $mode = '';
  94. if ( $id ) {
  95.   if ( ! isset( $files[$id] ) ) {
  96.     print "データがありません";
  97.     exit;
  98.   }
  99.   $buff = @file_get_contents( $files[$id] );
  100.   if ( ! $buff ) {
  101.     print "ファイルが開けません";
  102.     exit;
  103.   }
  104.   $view = unserialize( $buff );
  105.   if ( ! $view || ! is_array( $view ) ) {
  106.     print "データが壊れています";
  107.     unlink( $files[$id] );
  108.     exit;
  109.   }
  110.   $mode = 'view';
  111. } else {
  112.   rsort( $files );
  113.   $files = array_slice( $files05 );
  114.   $list = array();
  115.   foreach ( $files as $path ) {
  116.     $buff = @file_get_contents( $path );
  117.     if ( ! $buff ) continue;
  118.     $data = unserialize( $buff );
  119.     if ( ! $data || ! is_array( $data ) ) {
  120.       unlink( $files[$id] );
  121.       continue;
  122.     }
  123.     $list[] = $data;
  124.   }
  125.   $mode = 'list';
  126. }
  127.  
  128. ?>
  129. <html>
  130.  
  131. <head>
  132. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  133. <title>ウフフ</title>
  134. </head>
  135.  
  136. <body>
  137.  
  138. <?php if ( $mode == 'view' ) { ?>
  139. <h1><?php print $view['title']?></h1>
  140. <p><?php print $view['comment']?></p>
  141. <p><?php print date( 'Y.m.d'$view['date'] )?></p>
  142. <?php } else { ?>
  143. <table>
  144. <?php foreach ( $list as $item ) { ?>
  145. <tr>
  146. <td><a href="?id=<?php print $item['id']?>"><?php print $item['title']?></a></td>
  147. <td><?php print date( 'Y.m.d'$item['date'] )?></td>
  148. </tr>
  149. <?php } ?>
  150. </table>
  151. <?php } ?>
  152.  
  153. </body>
  154.  
  155. </html>

この意見に回答する

ツリーへ TOPへ

A02-1
replyerMemory [9月6日 15:18]

>>tezcello様
返答が遅くなって申し訳ございません・・・。
マルチポストのことを知らず、いろんなところに質問をしてしまった事を非常に心よりお詫び申し上げます・・・。
マルチポストの件に関しましては、以後気をつけます。

>>signal様
ご返答ありがとうございます。
当サイトはutf-8だと文字化けしちゃうので、euc-jpにする関数を付け加えた上、多少改造してみました。

  1. <?php 
  2. # このファイルは UTF-8 で保存すること 
  3. //header('Content-Type: text/html;charset=UTF-8'); 
  4.  
  5. #表示数
  6. $textview ='10';
  7.   
  8. # 取得したページの内容を保存するディレクトリ 
  9. # Linux系であればパーミッションは「777」or「707」 
  10. $datadir = './data'
  11.   
  12. # 更新日ファイルが存在しないとき 
  13. if ( ! file_exists("{$datadir}/update") ) { 
  14.   touch( "{$datadir}/update"time() - 24 * 60 * 60 )# 前日の日付で作成 
  15.   chmod( "{$datadir}/update"0606 )
  16. } 
  17.   
  18. # 取得済みページの取得 
  19. $files = array()
  20. foreach ( glob("{$datadir}/*.dat") as $path ) { 
  21.   $name = basename( $path'.dat' )
  22.   list( $date$id ) = explode( '_'$name )
  23.   $files[$id] = $path
  24. } 
  25.   
  26. # 一日に一回更新 
  27. $now    = explode( '.'date('Y.m.d') )
  28. $limit  = date( 'Ymd'mktime( 000$now[1]$now[2] - 1$now[0] ) )
  29. $update = date( 'Ymd'filemtime("{$datadir}/update") )
  30. if ( $limit >= $update ) { 
  31.   
  32.   # 全ページのIDを格納する 
  33.   $list = array()
  34.   
  35.   # 一覧ページの取得 
  36.   $p = 1
  37.   while ( 1 ) { 
  38.   
  39.     $buff = @file_get_contents("http://tenvi.nexon.co.jp/support/notice.asp?p={$p}")
  40.     if ( ! $buff ) { 
  41.       print "一覧ページを取得できません"
  42.       exit
  43.     } 
  44.   
  45.     # 記事一覧よりIDの抽出 
  46.     if ( ! preg_match_all( '/<td class="info-txt"><a href=".*?idx=(\d+).*?">/'$buff$match ) ) { 
  47.       break
  48.     } 
  49.   
  50.     foreach ( $match[1] as $id ) $list[$id] = true
  51.   
  52.     $p ++; 
  53.   } 
  54.   
  55.   # 各ページの取得 
  56.   foreach ( $list as $id => $flag ) { 
  57.     if ( file_exists( $files[$id] ) ) continue
  58.   
  59.     $buff = @file_get_contents("http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice&idx={$id}")
  60.     if ( ! $buff ) continue
  61.   
  62.     $data = array( 'id' => $id )
  63.   
  64.     # タイトルの抽出 
  65.     if ( ! preg_match( '/<h5 class="detail-ttl"[^>]*?><img[^>]+>(.+?)<\/h5>/'$buff$match ) ) continue
  66.     $data['title'] = $match[1]
  67.   
  68.     # 日付の抽出 
  69.     if ( ! preg_match( '/<p class="detail-view"[^>]*?>(\d+)\D+(\d+)\D+(\d+).*?<\/p>/'$buff$match ) ) continue
  70.     $data['date'] = mktime( 000$match[2]$match[3]$match[1] )
  71.   
  72.     # コメントの抽出 
  73.     if ( ! preg_match( '/<p class="detail-txt"[^>]*?>(.+?)<\/p>/'$buff$match ) ) continue
  74.     $data['comment'] = str_replace( '<br>'"\n"$match[1] )
  75.  
  76.   // 抽出文字を切り取る
  77.   if (mb_strlen($data['title']) > 50) { 
  78.     // 50 文字以上の場合 
  79.     $data['title'] = mb_substr($data['title']050) . '...'
  80.   }
  81.   //テキストをutf-8からeuc-jpにする
  82. mb_convert_variables("EUC-JP""utf-8"$data['title']);
  83. mb_convert_variables("EUC-JP""utf-8"$data['date']);
  84.  
  85.     # データの保存 
  86.     $path = sprintf( '%s/%s_%s.dat'$datadirdate( 'Ymd'$data['date'] )$data['id'] )
  87.     $fp = @fopen( $path'w' )
  88.     if ( ! $fp ) { 
  89.       print "データを作成できません"
  90.       exit
  91.     } 
  92.     fwrite( $fpserialize( $data ) )
  93.     fclose( $fp )
  94.     chmod( $path0606 )
  95.   
  96.     $files[$data['id']] = $path
  97.   
  98.   } 
  99.   
  100.   touch("{$datadir}/update")
  101. } 
  102.   
  103. # ここからは好きなように 
  104. $id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0
  105. $mode = ''
  106. if ( $id ) { 
  107.   if ( ! isset( $files[$id] ) ) { 
  108.     print "データがありません"
  109.     exit
  110.   } 
  111.   $buff = @file_get_contents( $files[$id] )
  112.   if ( ! $buff ) { 
  113.     print "ファイルが開けません"
  114.     exit
  115.   } 
  116.   $view = unserialize( $buff )
  117.   if ( ! $view || ! is_array( $view ) ) { 
  118.     print "データが壊れています"
  119.     unlink( $files[$id] )
  120.     exit
  121.   } 
  122.   $mode = 'view'
  123. } else { 
  124.   rsort( $files )
  125.   $files = array_slice( $files0$textview )
  126.   $list = array()
  127.   foreach ( $files as $path ) { 
  128.     $buff = @file_get_contents( $path )
  129.     if ( ! $buff ) continue
  130.     $data = unserialize( $buff )
  131.     if ( ! $data || ! is_array( $data ) ) { 
  132.       unlink( $files[$id] )
  133.       continue
  134.     } 
  135.     $list[] = $data
  136.   } 
  137.   $mode = 'list'
  138. } 
  139. ?>
  140. <?php if ( $mode == 'view' ) { ?>
  141. <?php print date( 'Y.m.d'$view['date'] )?>
  142. <?php print $view['title']?>
  143. <?php print $view['comment']?>
  144. <?php } else { ?> 
  145. <?php foreach ( $list as $item ) { ?><div class="border-bottom"><?php print date( 'Y.m.d'$item['date'] )?> | <a target="_blank" class="Information" href="http://tenvi.nexon.co.jp/support/notice_view.asp?bid=tenvinotice?id=<?php print $item['id']?>"><?php print $item['title']?></a></div>
  146. <?php } ?> 
  147. <?php } ?>

ロリポップサーバーですと、header関数が使えないようです。。。

この意見に回答する

ツリーへ TOPへ

A02-1-1
replyertezcello [9月7日 17:20]

> utf-8だと文字化けしちゃうので
全体を EUC-JP で保存したけど、文字化けしちゃうー>header() をコメントアウトしたら表示OK
という考え方で、
> ロリポップサーバーですと、header関数が使えないようです。。。
となったのなら、早とちりだと思います。

  1. header('Content-Type: text/html;charset=UTF-8');
のエンコードの宣言が UTF-8 のままなので文字化けが起きていたのでは?

header() が使えないと、いろいろ困る事が出て来そうです。


文字化けのほとんどがエンコードの不統一に起因するものだと思います。(今回の問題の発端は、EUC-JP に変換してしまったデータ(元はUTF-8)を、UTF-8 だというヘッダを出した後にそのまま表示してしまって文字化け...の感じが...)

内部エンコードや、(自前あるいは取得した)データ、記述しているスクリプト、によって使用する関数が違って来るでしょうし、プログラム構造に変更が必要になるかも知れません。
正規表現を使う際、UTF-8 なら preg系を使えばいいけど、EUC-JP だったらmb系を使うとか。

使用される環境の設定がどうなっているのかは把握しておく事が必要でしょうね。


何も php.ini を変更しなくても、そのスクリプト中で統一されていればOKのはずです。
実際、今使っているサーバはデフォルトが UTF-8 だったり EUC-JP だったりしているので、どのサーバでも同じスクリプトを使う為に、ほとんどのスクリプトの最初の方で
  1. mb_language('ja');
  2. mb_internal_encoding('UTF-8');
  3. mb_regex_encoding('UTF-8');
  4. header('Content-Type: text/html; charset="UTF-8"');
  5. mb_http_output("pass");
のように書いておいて、スクリプトそのものも UTF-8 (もちろんBOM無し)で保存しています。
(つまり、UTF-8 でやる事に統一しています)

この意見に回答する

ツリーへ TOPへ

A02-1-1-1
replyerMemory [9月7日 18:35]

ご返答ありがとうございます。
UTF-8ではなく、初回にEUC-JPに変更し、やってみましたが、無理でした。
実際今は、header関数を利用しないでも、エラーなどは起きていません・・・。

ロリポップサーバーへと、環境はどうなっているのか、メールを送りましたので、
後ほど返ってくるかと思います。

utf-8に関しましては、以前「TeraPad」というソフトを使っていたのですが、
何故かたまに、処理されなくなり、shift-jisの環境で開いてしまうので、
あまり、utf-8での作成は好ましくないと思っております。

この意見に回答する

ツリーへ TOPへ

A02-1-1-1-1
replyersignal [9月7日 19:40]

ちなみに、このサンプルスクリプトはロリポで動作確認しています。

> 実際今は、header関数を利用しないでも、エラーなどは起きていません・・・。
header はなくても普通に動作します。
ただあったほうが文字化けに悩まされず確実に動作します。

あることで問題が発生するなら、なくしてもいいと思います。

この意見に回答する

ツリーへ TOPへ

A02-1-1-1-2
replyertezcello [9月7日 20:59]

> ロリポップサーバーへと、環境はどうなっているのか、メールを送りましたので、
これは自分で調べられます。
  1. <?php
  2. phpinfo();
  3. ?>
とだけ書いたファイルを置いて、これをブラウザで呼び出します。
かなりたくさんの情報が得られます。
というか、どんなサーバでも先ずはこれでどんな状況になっているのかを調べないと、エンコード絡みでかなり苦労する事になります。
うまく関数が使えないのが、自分のミスではなくインストールされていないからなんて事も有り得ます。

header() を使わなくても文字化けが起こらないのは、PHP(及びそのサーバ)のデフォルトが EUC-JP なんでしょう。
php.ini の default_charset が EUC-JP にセットされているのかも知れません。
(そういう事も phpinfo() でわかります)

全部は覚えられないので、(ブラウザで)ローカルに書き出しておく事をお勧めします。
あまり見せびらかすべき情報も含まれているかも知れませんので、そのファイルを置きっぱなしにしない方が良いのかも知れません。

> UTF-8ではなく、初回にEUC-JPに変更し、やってみましたが、無理でした。
無理とか、ダメとか、失敗したでは、何がどうなったのかを推測するのがとても難しいです。
signal さんも確認されているようですし、パッと見では文字化けに繋がるような所は無いように思いますが...
スクリプト以外の部分とのマッチングかも知れませんね。
IE で見ておられるなら、FF でもチェックされるといいでしょう。IE は HTTP ヘッダを無視するようですしエンコード関係では原因を見逃す事が多いように感じています。(IE6 はでの感想ですが)


僕も TeraPad を使っています。PHPモードが無いのは残念ですが、非常に気に入っています。
エンコードを間違えて開いてしまうのにはほとんど出会った事は無いですねぇ。
別のエンコードで開き直すのも一発なので、あまり気にしませんが...

正規表現を使う事は結構多く preg系の方が痒い所に手が届くように感じているのと、xml もちょくちょく使うので UTF-8 にしています。

この意見に回答する

ツリーへ TOPへ

A02-1-1-1-2-1
replyerMemory [9月7日 22:06]

現状では、何の支障もありません。
もちろん火狐やOperaで見ても多少スタイルがずれるくらいで、
PHP構文エラーなどは一切出ていませんでした。

Terapadは、やはり使いやすいですよね。
でもeuc-jpで編集してるとき、何かとshift-jisに切り替わっちゃうんですよね。
別のeucエディターで開くと、「不正な改行文を発見しました。」と出るんです。
プログラム的な問題だと思いますが・・・。
でも、phpファイルでもcとして扱うように設定すれば、中々いけますよね。


関係ない話になりますが、phpbbの質問で、{USERNAME}などを1階層下のファイルに
使用できるようにしたいです・・・。
ログイン有効期限が切れた場合は、入力フォームが出るような仕組みにはできませんでしょうか?
入力フォームは条件文を使えばいけると思うんですが・・・。
といっても、phpbbのログインデーターがなければ、意味がないので・・・。

現状のディレクトリ

[www]
 │[phpbb_forum] ・・・ phpbb本体の全てのデーター
  │
  ┼他ファイル省略....
 │
  └index.php ・・・ {USERNAME}を適応させたいファイル

この意見に回答する

ツリーへ TOPへ

A02-1-1-1-2-1-1
replyertezcello [9月11日 22:27]

> 関係ない話になりますが...
1つのスレッドは1つの質問にしましょう。
内容の全く違う質問は、相応しいタイトルをつけて新しく質問すべきです。


質問内容を反映したタイトルであれば、他の人が調べる時に見つけ易いです。
回答する側も自分の守備範囲かどうかが判れば答え易いです。
だから「教えてください」とか、「質問です」とかのタイトルは嫌われるんです。

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
動的なURLを静的に見せる方法
 このエントリーをはてなブックマークに追加 
A
普通に考えて、mod_rewrite でしょうね。 http://www.nishishi.com/blog/2006/01/mod_rewrite_url.html...

>>続きを読む

GETのままでは検索エンジンのロボットが拾ってくれなかったためにSEO対策として有効だと言われていますね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)