htmlSQLというPHPのWebスクレイピングライブラリがある。
ライセンスは修正BSDライセンス。
内部的にはSnoopyのVersion1.01を使っている。(こちらはLGPLライセンス。バージョンがあがるとGPLになるみたい?
)
これを使って何かしてみよう
例えば、携帯でプロ野球速報を見られるようにするのはどうだろう?
プロ野球速報と言えばnikkansports.com。
FLASH版のリアルタイム速報もhtml版の詳細な試合情報も重宝する。
しかし、これ(html版の方)を携帯で見ようとするとなかなか使い辛い。いわゆる携帯ブラウザでは見られないので、フルブラウザ(auだからPCサイトビューア。中身はOpera)で見ることになるが、重い重い
携帯のネットワークには情報量が多過ぎる。レンダリング負荷も高い。地下鉄で見ようものなら一苦労。
これをサクッと見られるようにスクレイピングしてみよう。
こんな感じで。
スコア速報のページを取得
お目当てのチームの試合詳細のページを探す
試合詳細から、見たい情報だけ取り出してhtmlにして出力
見てみると、nikkansports.comはhtml的になかなかよくできてる。
フォーマットはxhtmlだし(validじゃないけど)、class属性やid属性を誠実に付けている。文字コードがUTF-8なのも個人的にはありがたい。
100行くらいでできた。意外と簡単だね
できたソースコードはこんな感じ。中途半端にclass化したのはどんなもんだろう
<?php
/**
* version 0.1.1
*/
include_once('snoopy.php');
include_once('htmlsql.php');
//表示したいチーム
$team = '中日';
class NikkanScraper {
const DOMAIN = 'http://www.nikkansports.com';
private $_wsql;
public function connect($src) {
$this->_wsql = new htmlsql();
$this->_wsql->set_user_agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
if (!$this->_wsql->connect('url', NikkanScraper::DOMAIN . $src)){
throw new Exception('Error while connecting: ' . $this->_wsql->error);
}
}
public function query($sql) {
if ($this->_wsql->query($sql)) {
return $this->_wsql;
}
throw new Exception('Query error: ' . $this->_wsql->error);
}
public function showTable($whereClass, $showClass = '') {
$this->_wsql->query('SELECT * FROM table WHERE $class == "' . $whereClass . '"');
foreach($this->_wsql->fetch_array() as $row){
$data = mb_convert_kana(mb_ereg_replace('(……| )', '', $row['text']), 'k');
echo '<table class="' . $showClass . '">' . $data . '</table>';
}
}
}
?>
<html>
<head>
<title>pb</title>
<style type="text/css">
table, th, td{
text-align: center;
border-collapse: collapse;
border: solid #666 1px;
}
table.score th{ /* 得点表 */
padding: 0 0.5em 0 0.5em;
}
th{
font-size: 0.8em;
}
td.line{ /* 投手情報のチームの境目 */
border-bottom-width: 3px;
}
td.hit{
color: red;
}
</style>
</head>
<body>
<?php
echo date('Y/m/d H:i');
$ns = new NikkanScraper();
try {
//スコア一覧ページを取得
$ns->connect('/baseball/professional/score/pf-score.html');
//全ての試合状態を取り出す
$statuses = $ns->query('SELECT text FROM h5');
foreach($statuses->fetch_array() as $row){
$allStatus .= $row['text'] . '<br />';
}
//試合詳細ページを1つずつ取得し、該当チームの試合詳細ページを探す
$links = $ns->query('SELECT href FROM a WHERE $text == "ニッカン式スコア"');
$hitFlg = false;
foreach($links->fetch_array() as $row){
$ns->connect($row['href']);
$detail = $ns->query('SELECT text FROM title');
$title = $detail->fetch_array();
//お目当てのチームを探す
if (mb_ereg($team, $title[0]['text'])) {
$hitFlg = true;
break;
}
}
if ($hitFlg) {
//詳細ページがあれば内容を表示
$ns->showTable('scoreTable', 'score'); //得点表
$ns->showTable('pitcher'); //投手情報
$ns->showTable('batter'); //打者情報
}
//全試合の状態を表示
echo $allStatus;
} catch (Exception $e) {
echo $e->getMessage();
}
?>
</body>
</html>