データの取得

PMET臨床研修ガイドブック2013では、

病院からお送りいただいた原稿につき、到着順に、9月18日現在、901病院を、掲載いたしました。

とある。一方、マッチング参加病院数は1015なので、90%ほどがこのデータベースに登録されている。
臨床研修病院検索のトップページから、何も指定せずに検索をかけると、897件ヒットする。

本当はサーバーになにかqueryを投げたらデータを一括ダウンロードするような仕様になっていて欲しいのだが、あいにくそうなっていなさそうだし、オレもそんな技術がない。
ということで、地味にクリック&セーブを行うことにしよう。
下記スクリプトを使えば70分くらいで終了した。
 
Ubuntuでキーボードマクロを行うには、xautomationというソフトがあるらしい。
ということでインストール。

sudo apt-get install xautomation

ターミナル上で

xte

と打てば、xautomationが使えるわけだが、PMETからHTMLファイルを保存するときに、タブボタンを打てばカーソルが移動するのだが、最初のページとそれ以降のページで回数を条件分岐したい。
が、ターミナルで起動したときに、xautomationの使い方がよくわからない。
なので、Pythonでやることにした。これなら条件分岐もいろいろやれる。
Pythonからターミナルへコマンドを送るには、

import sys
os.system

とやればいけるっぽい。
下のスクリプトを、画像の状態から開始すれば、全病院をクリック&セーブをちまちましてくれる。

import os
import time
import sys
try:
	import pygtk
	pygtk.require("2.0")
except:
	pass

try:
	import gtk
	import gtk.glade
except:
	sys.exit(1)

def xte_python(x, y, one_page_hps, all_hps, interval):
	pages = all_hps/one_page_hps + 1
	os.system("xte 'mousemove %d %d'"%(x,y))
	os.system("xte 'mouseclick 1'")
	x1, y1 = x, y
	cmds = ["xte 'key Tab'", "xte 'key Return'", "xte 'keydown Control_L'", "xte 'key s'", "xte 'keyup Control_L'", "xte 'key Return'", "xte 'keydown Control_L'", "xte 'key w'", "xte 'keyup Control_L'"]
	for p in range(pages):
		for i in range(2): #最初の2回はダミー送り
			os.system(cmds[0])
			time.sleep(1) #ここを詰め過ぎると、メインメニューに戻ってしまう。
		
		for i in range(one_page_hps): #病院を移動して
			for cmd0 in cmds:
				os.system(cmd0) #セーブしたりブラウザタブを閉じたりのコマンドを実行している
				time.sleep(interval)
		
		if p < 1: #最初のページだけ、"前の15件"がないので
			os.system("xte 'key Tab'")
			time.sleep(interval)
		else:
			for k in range(2):
				os.system("xte 'key Tab'")
				time.sleep(interval)
		
		os.system("xte 'key Return'") #これで次のページヘ進む
		time.sleep(1) #ここも同様
#実行
#ある程度intervalがないと、HTML読み込みが間に合わずすごいことになるので気長に。
xte_python(100, 500, 15, 897, 0.5)

 
Windowsの場合、UWSCというソフトで同じことが可能である。
スクリプトを作ったはいいが、気長に待つのがめんどくさすぎて待機時間を短めにしたら、いくつかの病院で読み込みがうまくいかず、884件だった。
スクリプトこちらを参考に作成した。
これをpmet.uwsとして保存して、uwscに読み込んで、xautomationと同様に開始する。

//ここからがメインルーチン。
//書物ごとの変更を要するもの
ヒット数=897
一画面件数=15
zeros=100000
画面数=ヒット数/一画面件数+1
初回x=200
初回y=300
stime=1
for m=1 to 画面数
	for k=1 to 一画面件数
		ACW(GETID("研修病院検索結果一覧 - Google Chrome","Chrome_WidgetWin_1"),-4,-4,1608,908,0)
		BTN(LEFT,CLICK,初回x,初回y,100)
		//2回目までのタブは画像なのでダミー送り。
		for i=1 to k+2
			//20行の項目の指定行目に移動
			KBD(VK_TAB,CLICK,50)
		next
		
		KBD(VK_RETURN,CLICK,20)
		Sleep(stime)
		//保存コマンドCTRL+Sを押す。
		KBD(VK_CTRL,DOWN,40)
		KBD(VK_S,DOWN,40)
		KBD(VK_S,UP,10)
		KBD(VK_CTRL,UP,10)
		//保存窓が出るまで待機するループ、不要に思えるが、これがないとしばしば異常な画面に移行する。
		WHILE GETID("名前を付けて保存")< 0
			Sleep(stime)
		WEND
		ACW(GETID("名前を付けて保存"),184,104,656,390,0)//待ち時間無限大
		//Sleep(stime)
		名保id =GETID("名前を付けて保存")
		//保存テキスト名発生。2009年版は桁揃えしていたが今回はゼロサプレスにする。
		n=m*20+k
		//SendStr(名保id,fn+n, 1, True)     // 検索
		//SendStr(名保id,fn+n, 1, True)     // 検索
		//SendStr(名保id,fn+n, 1, True)     // 検索
		//三回も送るなよ、という感じだが、これがないとまれに異常画面に移行する。
		KBD(VK_RETURN,DOWN,1000)
		KBD(VK_RETURN,UP,400)
		//画面閉じる
		KBD(VK_CTRL,DOWN,40)
		KBD(VK_W,DOWN,40)
		KBD(VK_W,UP,10)
		KBD(VK_CTRL,UP,10)
		ACW(GETID("研修病院検索結果一覧 - Google Chrome","Chrome_WidgetWin_1"),-4,-4,1608,908,0)
		if ヒット数=n then EXIT
	next
	//画面表示上限になったら次の20件を検索する。
	BTN(LEFT,CLICK,初回x,初回y,30)
	for k1 = 1 to 18
		KBD(VK_TAB,CLICK,40)
	next
	//2画面目からは1回目のタブは『前の20件』なのでダミー送り。
	If m > 0 then KBD(VK_TAB,CLICK,40)
	KBD(VK_RETURN,CLICK,10)
next