人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

現在、PHPでサイトからデータを抽出してSQLに読み込む練習をしています。
20件ほどいろいろなサイトの抽出を自分で試した結果、取得できるものと取得できないものが出てきました。
そのうちのいくつかのサイトはどこがおかしかったのか原因自体がわからないので、どなたか抽出の模範回答をお願いします。

データベース名:headline、テーブル名:datalist、フィールド名はblogtitle、url、sourcetitleの3つです。
http://blog.livedoor.com/category/111/ranking.html
抽出したいのはブログ名とURLです。

上のURL先のソースを読み取り、ランキング先の20個のブログタイトルとURLを、SQLに入力するようなものを考えています。
対応する「sourcetitle」フィールドには、上のURLのタイトル…つまりhttp://blog.livedoor.com/category/111/ranking.htmlのタイトルである、「今日のできごと : 日記 : ランキング - ライブドアブログ」という文字が入力されます。

練習中ですので、なるべくわかりやすく書いていただけると大変助かります。
どうかよろしくお願いします。

●質問者: holoholobird
●カテゴリ:インターネット ウェブ制作
✍キーワード:PHP SQL URL いもの サイト
○ 状態 :終了
└ 回答数 : 2/3件

▽最新の回答へ

1 ● あすか
●35ポイント

以下のような感じでどうでしょう。


ご質問にあるランキングのURLは配列 $items[N]['url'] に、タイトルは $items[N]['sourcetitle'] に格納するようにしてあります。Nは1?20の整数です。


SQLへの展開をどのような形で行っているのか分からなかったので、ここでは省略しています。

<?php
$url = 'http://blog.livedoor.com/category/111/ranking.html'; //ターゲット
$source_encoding = 'EUC-JP'; //ターゲットのエンコード
$internal_encoding = 'UTF-8'; //本スクリプトのエンコード
mb_internal_encoding($internal_encoding);

//抽出パターン
$pat = "/<span class=\"number[^\"]*\">[0-9]+<\/span>.*<a href=\"([^\"]+)\">(.+)<\/a>/iu";

$cnt = 1;
$items = array();
$fp = fopen($url, 'r');
//1行ずつ読み込んで抽出,配列$itemsへ格納
while (! feof($fp)) {
 $str = fgets($fp);
 $str = mb_convert_encoding($str, $internal_encoding, $source_encoding);
 if (preg_match($pat, $str, $ary) > 0) {
 $items[$cnt]['url'] = $ary[1];
 $items[$cnt]['sourcetitle'] = $ary[2];
 $cnt++;
 }
}
fclose($fp);

//表示
var_dump($items);
?>
◎質問者からの返答

指定したURLのソースを読み取り、

データベース名:headline、テーブル名:datalist、フィールド名が順にblogtitle、url、sourcetitleとなるmySQLのデータベースに登録したいのです。

たとえばhttp://blog.livedoor.com/category/111/ranking.htmlだと

Olz Weblog:http://blog.livedoor.jp/olzjp/:今日のできごと : 日記 : ランキング - ライブドアブログ

人名力:http://blog.livedoor.jp/namepower/:今日のできごと : 日記 : ランキング - ライブドアブログ

嵌る日常:http://shinji.livedoor.biz/:今日のできごと : 日記 : ランキング - ライブドアブログ

みたいに自動でSQLに登録されるPHPを作成したいのですが、書き方が悪かったのでしょうか。


恥ずかしながら

>SQLへの展開をどのような形で行っているのか

という文章の意味が理解できませんでしたので、どういう意味か教えていただけると助かります。


2 ● うぃんど
●35ポイント

>取得できるものと取得できないものが出てきました

正規表現のパターンが今ひとつなのかもしれません

データベース関連はひとまず横において、下のような具合にして「取得成功/失敗の違いを洗い出す」ことをまずは行ってみてください

<?php
// このソースコードはUTF-8で保存されているものとします
// file_get_contentsでhttpから始まるURLも利用可能かどうかはphp.iniの設定によります
// 参考URL // http://jp2.php.net/manual/ja/function.file-get-contents.php
//
// ********** URLからの読み取り **********
$url = 'http://blog.livedoor.com/category/111/ranking.html';
$chrCode = 'UTF-8';
$pattern1 = '!<title+?>(.+?)</title>!i'; // ソースタイトル
$pattern2 = '!<span.+?class="number.+?>(\d+).+?href="(.+?)".*?>(.+?)</!i'; // URLとブログタイトル
$strText = file_get_contents($url) or Die('読み込みに失敗しました'); // 読み取り
$strText = mb_convert_encoding( $strText, $chrCode, mb_detect_encoding( $strText ) ); // キャラクタコード変換
preg_match( $pattern1, $strText, $matchs1) or die('タイトルのパターンにマッチしませんでした'); // パターンマッチング
echo '<pre>'; print_r( $matchs1 ); echo '</pre>';// 抽出結果
preg_match_all( $pattern2, $strText, $matchs2, PREG_SET_ORDER) or die('URLとブログタイトルのパターンにマッチしませんでした'); // パターンマッチング
echo '<pre>'; print_r( $matchs2 ); echo '</pre>';// 抽出結果

$pattern2は下記のようにしてもかまいません

$pattern2 = '!<span class="number">(\d+).+?href="(.+?)">(.+?)</a>!i'; // URLとブログタイトル

パターンのデリミタに/ではなく!を使っているのは…URLに/が含まれるためです

テキストを"ではなく'で囲っているのは…HTMLタグ内部に"が含まれているためです

internal_encodingは不要です(phpは受け入れたデータをそのままの形で保持するからです)

fopenでファイルを開いてfgetsなどで取得する方法を用いる場合もありますが、ネイティブで動作するfile_get_contentsを用いるほうが簡単で早いです

上記で問題点が見当たらない場合はSQLの作成ミスの確認をしてみてください

(phpからMySQLへの接続方法はmysqliやPDO、pearなど複数存在します。下記はよく使われるmysqlモジュールを例にしています)

// mysql_query($sqlStr); //これをコメントにして
echo $sqlStr . "<br />\n"; // SQLをブラウザに返す

この先になりますと、あなたが作成したプログラムをコメントか返信欄に丸投げしてもらうほうが早いです

はてなからの通知メールで確認してもらうと>|php|と||<でソースコードが囲まれているのがわかると思いますが、

ダイアリーや返信欄でも使えます(質問文やコメント欄では無視されます)ので、まねをしていただければソースコードが見やすくて助かります

◎質問者からの返答

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

すみません。私の質問分の書き方がおかしかったせいで、質問の内容がずれてしまいました。

お二人には上の回答分のポイントを差し上げますので、どうかコメントに書いたようなPHPのコードを教えてください。

回答数制限を5回にひきあげました。どうかご回答のほど、よろしくお願いします。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ