KONAMI社のBEMANIシリーズを韓国で稼働させるための提携先にUNIANA社があり、それは下記サイトに詳しい。
韓国の音ゲー事情
そして、ローカライズや運営しているサイトのなかに稼働店舗一覧のページがあるようで、
というツイートを見かけた。
そもそもハングル文字読めないので、どこから稼働店舗一覧のページに遷移できるかを探すのに苦労した。マウスを動かしてリンクを表示させて、というのをひたすらやるしかない。
http://beat.uniana.com/store/store_list.php
ようやく見つけたので、しばらく動かしてみて、HTMLソースも眺めてみたりして、
<tr>
<td>21세기 게임랜드</td>
<td><span>서울시 관악구 신림9동 1538-1 </span><a href="http://map.naver.com/?level=2&lat=37.4810215&lng=126.9516009&query=7ISc7Jq47Yq567OE7IucIOq0gOyVheq1rCDsi6Drprw564%2BZIDE1MzgtMQ%3D%3D&menu=location&stab=ADDRESS%3B1&queryRank=1&mapMode=0&enc=b64" target="_blank"><img src="http://webimage.uniana.com/beatmania2015/common/btn_store.jpg" alt="위치보기" /></a></td>
</tr>
<tr class="detail_view" style="text-align:center;">
<td colspan="2"><img src="http://webimage.uniana.com/uniana/store/jubeat/seoul06.png" alt="게임장 사진" /></td>
</tr>
<tr>
<td>건대 해피 게임천국</td>
<td><span>서울시 광진구 화양동 9-43 </span><a href="http://map.naver.com/?dlevel=11&lat=37.5420939&lng=127.0687863&searchCoord=127.069268%3B37.5404038&query=7ISc7Jq47IucIOq0keynhOq1rCDtmZTslpHrj5kgOS00Mw%3D%3D&menu=location&tab=1&mapMode=0&enc=b64" target="_blank"><img src="http://webimage.uniana.com/beatmania2015/common/btn_store.jpg" alt="위치보기" /></a></td>
</tr>
<tr class="detail_view" style="text-align:center;">
<td colspan="2"><img src="http://webimage.uniana.com/uniana/store/beat/seoul/seoul_6.png" alt="게임장 사진" /></td>
</tr>
この時点で25時だし夜も遅いし明日も仕事だし、
とヒントだけ書いておいた。
数日経って時間に余裕も出来たので、ちょっと試しにつくって見ます。
1. クロール
先ほどのサイトでは、Flashで地域を選ぶとその地域内の店舗をページング表示する作りになっており、以下のようなURL構成になっている。
http://beat.uniana.com/store/store_list.php?p=1&area=1
パラメータ「p」はページで、1-originで指定できる。パラメータ「area」は地域を表し、1~16まで指定できる。
店舗が無かったり、ページ指定が誤り(全2ページなのに3ページ目を指定するなど)だったりすると、
<tr><td colspan='2'>매장이 없습니다.</td></tr>
のようになるので、これを検知すればいいかな。
10wget.sh
指定のゲームに対して、全ページを取得する。
引数に、ゲームの種別、今日の年月日を(yyyyMMdd)書式で指定する。
GAME=$1
TODAY=$2
for (( area=1; area<=16; area++ ))
do
page=1
continueflag=1
while [ ${continueflag} -gt 0 ]
do
url="http://${GAME}.uniana.com/store/store_list.php?p=${page}&area=${area}"
zpage=`echo 000${page} | sed -e 's/.*\(..\)$/\1/'`
zarea=`echo 000${area} | sed -e 's/.*\(..\)$/\1/'`
wgetfile=${GAME}/${TODAY}a${zarea}p${page}.html
./11wget.sh "${url}" "${wgetfile}"
result=$?
if [ ${result} -ne 0 ] ; then
continueflag=0
fi
if [ ${page} -ge 3 ] ; then
continueflag=0
fi
page=$(($page + 1))
done
done
11wget.sh
実際にwgetでHTML文書を取得する。
引数には、アクセスするURLと、保存するファイル名を指定。
戻り値が0だと成功。それ以外だと何らかの失敗。そのエリアではこれ以上HTML取得しない、と判断する。
WGETURL=$1
OUTFILE=$2
TMPFILE=${OUTFILE}.tmp
if [ "${WGETURL}" = "" ] ; then
exit 11
fi
if [ "${OUTFILE}" = "" ] ; then
exit 12
fi
useragent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36"
wget -v --append-output=wget.log \
--output-document="${TMPFILE}" \
--user-agent="${useragent}" ${WGETURL}
nkf -w "${TMPFILE}" > "${OUTFILE}"
rm -rf "${TMPFILE}"
COUNT=`grep "<td colspan='2'>" ${OUTFILE} | wc -l`
if [ ${COUNT} -ge 1 ] ; then
rm ${OUTFILE}
fi
exit ${COUNT}
2. 店舗名と住所の抽出
10wget.shで保存したHTMLファイルから、店舗名を取得して1ファイルにまとめて保存。同様に、住所を取得する。
引数に、ゲームの種別、今日の年月日を(yyyyMMdd)書式で指定する。
30sed.sh
GAME=$1
TODAY=$2
NAMEFILE=${GAME}/m_name${TODAY}.txt
ADDRFILE=${GAME}/m_addr${TODAY}.txt
MERGFILE=${GAME}/m_list${TODAY}.txt
rm -f ${NAMEFILE}
rm -f ${ADDRFILE}
for TARGET in `ls -1 ${GAME}/${TODAY}*`
do
cat ${TARGET} \
| grep -e "<td>[^<]\+</td>" \
| sed -e "s:^.\+<td>\([^<]\+\)</td>.\+$:\1:g" \
>> ${NAMEFILE}
cat ${TARGET} \
| grep -e "<td><span>[^&]\+ </span>" \
| sed -e "s:^.\+<td><span>\([^&]\+\)&.\+$:\1:g" \
>> ${ADDRFILE}
done
php -f ./31merge.php ${NAMEFILE} ${ADDRFILE} ${MERGFILE}
31merge.php
引数に、店舗名だけのファイル名、住所だけのファイル名、出力用ファイル名を指定
<?php
if ($argc < 4) {
echo "$argv[0] in-shopname-file in-shopaddr-file out-merge-file\n";
exit(1);
}
$fpName = fopen($argv[1], "r");
$fpAddr = fopen($argv[2], "r");
$fpMerg = fopen($argv[3], "w");
while (!feof($fpName) && !feof($fpAddr)) {
$shopname = trim( fgets($fpName) );
$shopaddr = trim( fgets($fpAddr) );
if (!empty($shopname) && !empty($shopaddr)) {
fwrite($fpMerg, "<tr><td>${shopname}</td><td>${shopaddr}</td></tr>\n");
}
}
fclose($fpMerg);
fclose($fpAddr);
fclose($fpName);
?>
3.昨日との比較
31merge.phpで保存した m_listYYYYMMDD.txt を、昨日のものと今日のものとで比較することで、昨日なくて今日ある店舗と、昨日あって今日ない店舗を抽出する。
50diff.sh
引数に、ゲームの種別、今日の年月日(yyyyMMdd)書式、昨日の年月日(yyyyMMdd)書式、を指定する。
GAME=$1
TODAY=$2
YESTERDAY=$3
TFILE=${GAME}/m_list${TODAY}.txt
YFILE=${GAME}/m_list${YESTERDAY}.txt
RHTML=${GAME}/result${TODAY}.html
rm -f ${RHTML}
touch ${RHTML}
cat html1.html >> ${RHTML}
echo "<h1>${GAME} - ${TODAY}</h1>" >> ${RHTML}
echo "<h2>NEW COMER</h2>" >> ${RHTML}
echo "<table>" >> ${RHTML}
echo "<tr><th>ShopName</th><th>ShopAddress</th></tr>" >> ${RHTML}
diff ${YFILE} ${TFILE} | grep -e "^> " | sed -e "s/^> //g" >> ${RHTML}
echo "</table>" >> ${RHTML}
echo "<h2>GONE</h2>" >> ${RHTML}
echo "<table>" >> ${RHTML}
echo "<tr><th>ShopName</th><th>ShopAddress</th></tr>" >> ${RHTML}
diff ${YFILE} ${TFILE} | grep -e "^< " | sed -e "s/^< //g" >> ${RHTML}
echo "</table>" >> ${RHTML}
echo "<hr>" >> ${RHTML}
echo ">> <a href=\"result${YESTERDAY}.html\">result${YESTERDAY}.html</a>" >> ${RHTML}
cat html2.html >> ${RHTML}
4. Webサーバ
50diff.shで作成したHTMLファイルを、Webサーバのドキュメントディレクトリへコピー。
index.htmlのエイリアスとして最新の日付のファイルをシンボリックリンク設定する。
60html.sh
GAME=$1
TODAY=$2
RFILE=result${TODAY}.html
RPATH=${GAME}/${RFILE}
WWWPATH=/var/www/html/pub/uniana
DESTPATH=${WWWPATH}/${GAME}/index.html
REALPATH=${WWWPATH}/${GAME}/${RFILE}
cp -p ${RPATH} ${REALPATH}
ln -s -f ${RFILE} ${DESTPATH}
5. 定時実行
上記のシェルスクリプトをシーケンシャルに実行する
00all.sh
cd /usr/local/uniana
TODAY=`date +%Y%m%d`
YESTERDAY=`date --date '1 days ago' +%Y%m%d`
for GAME in beat
do
./10wget.sh ${GAME} ${TODAY}
./30sed.sh ${GAME} ${TODAY}
./50diff.sh ${GAME} ${TODAY} ${YESTERDAY}
./60html.sh ${GAME} ${TODAY}
done
crontab
59 7 * * * /usr/local/uniana/00all.sh