ホリデープログラミング入門

ホリデーにプログラミングを楽しむための入門 by 船木信宏

全体表示

[ リスト ]


前々から自分は、会社の名前を全然知らないなぁ、と思っていました。上場企業にどんな会社があるのかもよくわかっていません。というわけで上場企業のデータを集めて、多少なりとも勉強してみることにしました。

まずはデータ収集。「上場企業」で検索しただけでも一覧を掲載しているらしきページが複数見つかりました。その辺をスクレイピングしてしまうのも手ですが、ごく一般に流布されたデータとはいえ無断で拝借するのは気が引けます。比較的二次利用しやすいWikipediaには


というテンプレートが用意されており、会社情報はこれで詳細に取れそうです。

さて、Wikipediaは全データをXML形式でダウンロードすることができます。
Wikipedia:データベースダウンロード - Wikipedia

不要なデータも多いし、解凍すると数GBになりそうで扱いづらいのですがそこは我慢。

ダウンロード


以下作業はLinux上のコマンドライン。
のんびり待ちます。意外とTorrentでの配布やミラーはないんですね。
クライアントマシンにダウンロードしてそこで作業でもよいですが、僕はサーバとして常時動いているLinuxマシンで。(クライアントマシンはモニタやらマウスをつないで使うPC、サーバはモニタを接続しないで使うPC、という程度の意味です)

こういった巨大ファイルをがりがり処理するのにロリポップをはじめとした共有サーバでは無理です。一度処理した後は静的なHTMLにして公開すればよいので、開発マシンと公開サーバを分けることで対処します。

開発マシンとしては、2万円切っているDellマシンがいいです。24時間稼動させるなら寝室に置くのはやめた方がいいですが、割と静か。僕もSC430や440を使っています。
PowerEdge SC440

OSはCentOSが適当かと思います。

解凍


% nohup bunzip2 jawiki-latest-pages-articles.xml.bz2&
nohup+&をつければバックグラウンドで実行かつ接続を切っても実行し続けてくれます。数時間かかる処理のときなどに便利。この解凍は数十分で終わりました。解凍後は約3GB。

基礎情報 会社


巨大ファイルをWindowsのアプリで開くときとたいていフリーズ状態に陥りますが、Linuxならlessでぱっと見れます。

% less jawiki-latest-pages-articles.xml
UTF-8でないと文字化けるかも。
lessで開いた後、
/基礎情報 会社
と打って探すと「関西国際空港株式会社」が最初にヒットしました。

3GBの中にいくつあるのかわかりませんが、この基礎情報会社、のテンプレート部分をすべて抽出すればよさそうです。

巨大ファイルから必要な箇所を抽出する


ファイルが巨大なので速度が欲しいところです。
というわけで、まずはC言語で書いてみます。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("cannot open.\n");
exit(EXIT_FAILURE);
}
char buf[1024+1];
int flag = 0;
while (fgets(buf, 1024, fp) != NULL) {
if (strstr(buf, "{{基礎情報 会社") == buf) {
flag = 1;
}
if (flag == 1) {
printf("%s", buf);
}
if (flag == 1 && strstr(buf, "}}") == buf) {
flag = 0;
}
}
fclose(fp);
return 0;
}

コンパイルオプションは
% gcc -O3 -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 wikipedia_kisojohokaisha.c
こんな感じで。
実行は以下のように。
% ./a.out jawiki-latest-pages-articles.xml >results.txt

PHPでも書いてみました。

<?php
$fp = fopen($argv[1], 'r');
if (!$fp) {
die("cannot open.\n");
}
$flag = 0;
while (($buf = fgets($fp)) != '') {
if (strpos($buf, '{{基礎情報 会社') === 0) {
$flag = 1;
}
if ($flag == 1) {
echo $buf;
}
if ($flag == 1 && strpos($buf, '}}') === 0) {
$flag = 0;
}
}
fclose($fp);
Cで書いたときとそう変わらないのが見てとれます。PHPはstrstrよりstrposの方が速そうなので変えているだけです。

ここで注意する必要があるのがOSが32ビットか64ビットか、です。

% uname -a
Linux localhost.localdomain 2.6.18-53.1.14.el5 #1 SMP Wed Mar 5 11:37:38 EST 2008 x86_64 x86_64 x86_64 GNU/Linux
とx86_64のように出てくればOKですが、
% uname -a
Linux localhost.localdomain 2.6.20-1.2320.fc5smp #1 SMP Tue Jun 12 19:40:16 EDT 2007 i686 i686 i386 GNU/Linux
とi386のようだと
Warning: fopen(jawiki-latest-pages-articles.xml): failed to open stream: File too large
とエラーが出てファイルを開けません。2GB以上のファイルは扱えないのです。先ほどのgccのコンパイルオプションを指定してPHPをコンパイルし直せば動くようですが少々ややこしそう。
参考:
PHPで大容量のファイルを操作する方法 - PHPプロ!ニュース

実行結果


{{基礎情報 会社 }}で囲まれた1299の企業情報が取得できました。

先ほどの64ビット環境でないとPHPが動かない関係で実行したのがDell SC430ではありませんがC言語版だと15秒、PHP版だと60秒程度で処理できました。

抽出結果のファイルサイズは1.7MB程度。これだけ小さくなれば正規表現を使うことも、file_get_contentsで一気に読み込むことも容易です。


次回


抜き出した文字列をMySQLのデータとしてINSERTしようと思います。
今のところ上場企業以外も抽出してしまっていますがこのままやってしまいます。

閉じる コメント(0)

コメント投稿

顔アイコン

顔アイコン・表示画像の選択

名前パスワードブログ
絵文字
×
  • オリジナル
  • SoftBank1
  • SoftBank2
  • SoftBank3
  • SoftBank4
  • docomo1
  • docomo2
  • au1
  • au2
  • au3
  • au4
投稿

.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事