Script JR東日本;
# Copyright(C) 2008 by nTak
路線別時刻表[]:-
<td width="432" class="text-m">${ROSENINFO}</td>
<td width="100" align="center" class="text-m">
${HYPERLINK}
</td>
</tr>
-::
include 'comnlib.inc';
include 'TConv.inc'; // TrainConv用の定義取込み
const
SiteInfo[5] = (
'JR東日本', // サイト名
0, // 変換動作のフラグ
(*!!*) 0x0100, // Hi:バージョン Lo:リビジョン
'Copyright(C) 2008 by nTak',
'http://www.jreast-timetable.jp/'
);
C_ForbidMemo= "メモ,データの再配布は禁止です";
LinkPat[6] = ('/timetable/list','/cgi-bin/st_search.cgi','/www.jreast-timetable.jp/');
(*------------------------------------------------------------------
自動更新を行う
戻値: TRUE: 更新した
FALSE: 更新失敗または更新ファイルが無い
------------------------------------------------------------------*)
function TzAutoUpdate:boolean;export;
begin
Result := DownloadNewScript(DistURL,SiteInfo[2]); // DistURLは作者のスクリプト配布URL
end;
(*------------------------------------------------------------------
ノードの定義リストを返す
戻値: 定義文字列
リストは次の書式文字列で返す。
[アイコン番号],[名前],[検索有無フラグ],[URL]
------------------------------------------------------------------*)
function TzAttachSite(index):string;export;
begin
case index of
0: Result := '16,JR東日本時刻表,-1,';
1: Result := '16,時刻表のみ,0,http://www.jreast-timetable.jp/';
2: Result := '16,到着時刻付,1,http://www.jreast-timetable.jp/';
else Result := '';
end;
end;
(*------------------------------------------------------------------
URLから読み込んでリンクを登録する
時刻表ページのURLが指定されていたら変換処理が必要なことを返す
IN: index ノードインデックス
node 親ノードのID、URLの登録はこのノードに対して実行
stURL 読込むURL
cache キャッシュ有効フラグ
OUT: FALSE 路線リンクを登録した
TRUE 時刻表ページのURLなので変換処理を実行する
------------------------------------------------------------------*)
function TzGetPageLinks(index,node,stURL,cache):boolean;export;
begin
Result := False;
Get(stURL,cache);
case StrPattern(stURL,LinkPat) of
3: begin // トップから路線リストを作成
Skipto('</form>'); // 最初のフォームを捨てる
Skipto('<form action="/cgi-bin/st_search.cgi" method="get">'); // 路線のフォーム
foreach ln in @formitems['rosen'] do
begin
if ln = '' then Next;
putlog(node,0:@sysdate,1:$$,2:0,3:$?+'?rosen='+ln,4:ICO_TRAIN,5:$:,6:$&+'rosen='+ln);
end;
end;
2: begin // 駅名リストを登録
getlog(node,1:rosen); // 路線名を取りだして
foreach lnk in @indexLink[LinkPat[0]] do
putlog(node,0:@sysdate,1:$$,2:1,3:lnk,4:ICO_EKI2,6:rosen); // ConvMainで使えるようPOSTSTRに記憶
end;
else // その他は無視
Result := True;
end;
end;
//------------------------------------------------------------------
// 時刻表データの抽出と変換
//------------------------------------------------------------------
function TimePageConv(RosenName,DocData):string;
//var i,j,ns,ds,ss,ln;
function MakeMark(Kind,lc,rc,AList):string;
begin
Result := Kind - ' ' - ' '-'・';
if Result = '' then Exit;
Kind := Result;
Result := '';
repeat
Mark := Kind;
ll := 0;
foreach dd in @CSV[AList] do
begin
split('−',dd,略,詳細);
略 := 略 - '#' - lc - rc; // 種別判定用の文字は削除しておく
if (TextPos(略,Kind) = 1) and (Length(略) > ll) then // 最長一致
begin
ll := Length(略);
Mark := 略;
end;
end;
kind := Delete(kind,1,Length(Mark));
Mark := lc + Mark + rc;
if TextPos(Mark,Result) = 0 then Result := Result + Mark;
until Kind = '';
end;
begin
TableNestMode(3,23); // TABLEタグのネスト
Strip(DocData);
// 作業変数をクリアする
init('',Caption,MapURL,DestInfo,KindList,DestList,TimeValue);
// 駅名と方面名を一緒に処理できるようにしておく
foreach ln in @Lines[DocData] do
begin
ln := Trim(ln); // 前後の空白を除去する
if (ln = '') or (ln=',') then Next;
// 1行テキストを分類解析
if TextPos(RosenName,ln) <> 0 then
begin
// 赤羽駅 東北本線 小山・宇都宮方面 (下り),,
ln := Replace(ln,' ',' ',TRUE); // 全角空白を半角空白
Caption := '件名,'+(ln - ',');
DestInfo := CatStr(',','時刻',CSV(ln,1),CSV(ln,0),CSV(ln,2)); // 運転日は後で追加
MapURL := 'Mapion,'+CSV(ln,0);
Next;
end;
case StrBegIndex(ln,'時,','列車種別','行き先','変更・注意') of
1: begin // 時, 平日 or 土曜・休日
DestInfo := DestInfo + ','+ CSV(ln,1);
end;
2,4: begin // 列車種別・列車名 :,無印=普通 快=快速 通快=通勤快速 ラ=ラビット,
ln := ShiftCSV(ln,1);
foreach val in @CSV[ln] do // 凡例をCSVでスキャンする
begin
if TextPos('=',val) = 0 then Next;
split('=',val,略語,車種);
KindList := KindList + "#%略語%−%車種%,"; // 凡例を組み立てる
end;
end;
3: begin // 行き先・経由 :,無印=宇都宮 金=小金井 磯=黒磯,
ln := ShiftCSV(ln,1);
foreach val in @CSV[ln] do // 凡例をCSVでスキャンする
begin
if TextPos('=',val) = 0 then Next;
split('=',val,略語,行先);
DestList := DestList + "{%略語%}−%行先%,"; // 凡例を組み立てる
end;
end;
else if IsDigit(CSV(ln,0)) then // 先頭が数字なら時刻表
begin
ln := Replace(ln,' ','',TRUE); // 全角空白を消去
TimeValue := TimeValue + ln + "\n"; // 後で略語を置換する
end;
end;
end;
// 出来上がった時刻テーブルと略語を使って置換する
TimeTable := '';
foreach ln in @Lines[TimeValue] do
begin
ln := Replace(ln,' ','_',TRUE); // 空白をマーク
ln := ExtractCSV(ln,ss); // まずは時刻を取出し
ln := ShiftCSV(ln,1); //RST 余分なカラムの読み飛ばし
n := Str2Int(ss); // 時刻を取り出す
TimeTable := TimeTable+((n>=24)?n-24:n)+ ' '; // 24時以降の補正をして時刻追加
// 種別・行先と時刻の2つで1ペア
while CSVCount(ln) > 0 do // 時刻データがある間
begin
ln := ExtractCSV(ln,ns,val); // 種別_行先 時刻 記号 の順
Separate(val,9:num,*:ss); // 注意記号は数字の後につくので
split('_',ns,種別,行先); // 行先と種別を分離
種別 := MakeMark(種別,'<','>',KindList);
行先 := MakeMark(行先,'{','}',DestList);
TimeTable := "%TimeTable% %種別%%行先%%ss%%num% ");
end;
TimeTable := TimeTable+"\n";
end;
Result := CatStr("\n",Caption,MapURL,C_ForbidMemo,DestInfo,TimeTable)+"凡例,"+KindList+DestList+"\n";
end;
//------------------------------------------------------------------
// 到着時刻データの抽出と変換
//------------------------------------------------------------------
function TimeReachConv(Station,DocData):string;
begin
TableNestMode(3,23); // TABLEタグのネスト
Strip(DocData);
DocData := Replace(DocData,' ',' ',TRUE); // 全角空白を半角変換
// 作業変数をクリアする
init('',Result,Kind,MarkList,Arival);
pickup := False;
foreach ln in @Lines[DocData] do
begin
ln := Trim(ln) - RegExpr(',\([0-9]+\)',ln); // 前後の空白を除去する
if ln = '' then Next;
// 1行テキストを分類解析
case StrBegIndex(ln,Station,'列車種別,',',,','列車名','運転日,','駅名,','備考,') of
1: begin // 指定駅からの到着時間をリストアップする準備
ln := ln - ' ';
atime := RegExpr('([0-9]+:[0-9]+)(発|着)',ln); // まず着時刻を使う
発時刻 := dateformat($(0),'hn',2007);
MarkList := "到着,%Kind%,"+$(0)+',';
Arival := '';
pickup := TRUE;
end;
2: begin // 列車種別
Kind := (CSV(ln,2)='')? CSV(ln,1) : CSV(ln,2); // 種別が付いているかも
Kind := Kind-RegExpr('[0-9]+(号|)',Kind); // 列車名
case Kind of
'各停|各駅停車': Kind := '普通';
'^普通(?*)': Kind := $(0); // パターンで( )内に一致した文字列
end;
end;
3..6: Next; // 今のところとりあえず何もしない
7: Break; // Copyright(終り)
else if Pickup then
begin
ln := TrimCSV(ln-' ',3); // 最初の3項目だけ使う、2列ある情報はあきらめる
atime := RegExpr('[0-9]+:[0-9]+(着|発)',ln); // 着時刻を先に抽出
if atime <> '' then // 発着時刻が取得できたら
begin
到着 := dateformat(atime,'hn',2007); // 自動補正されないように年を指定
if 到着 < 発時刻 then 到着 := 到着 + @c_dateseconds; // 24:00を過ぎた
到着 := (到着 - 発時刻) div 60;
eki := CSV(ln,0) - RegExpr('\(*\)',CSV(ln,0));
Arival := Arival + eki+":%到着%,";
end;
end;
end;
end;
if Arival = '' then Result := ''
else Result := MarkList + Arival;
end;
(*------------------------------------------------------------------
時刻表ページのURLから時刻表のテキストを返す
必要ならリンク先のデータも読み込んで変換する
IN: index ノードインデックス
pURL 親ノードのURL
URL 読込むURL
cache キャッシュ有効フラグ
OUT: TEXT 変換した時刻表テキスト
------------------------------------------------------------------*)
function TzConvMain(index,pURL,URL,cache,method,PostStr):string; export;
begin
Result := '';
Result := '';
TagStripSet(':DL:DD:BODY:',TX_NONE,TX_NONE); // 無視するタグ
TagStripSet(':BR:',TX_COMM,TX_NONE); // <BR>はカンマ変換
TagStripSet(':DIV:',TX_COMM,TX_NONE); //RST <DIV>はカンマ変換
TableNestMode(3,23); // TABLEタグのネスト
Get(URL,cache); // 該当駅の路線一覧ページの取得
StName := Trim(WrapStr($_,'<font color="#FFFFFF">','発車時刻表'));
foreach n in @clip[路線別時刻表] do
begin
// if TextPos('成田エクスプレス',ROSENINFO) = 1 then // デバッグ用
// if TextPos(PostStr,ROSENINFO) = 1 then // リストに無い路線もあるので全部変換
begin
foreach ln in @indexlink['',HYPERLINK,URL] do // 平日と土曜・休日のリンク
begin
Get(ln,cache);
// 不要な路線メニューの部分を切り落とす
PageClip('<table width="100%" border="0" cellspacing="0" cellpadding="0">',
'<table cellspacing="0" cellpadding="1" border="0">');
BasePage := $_;
時刻表 := TimePageConv(StName,BasePage); // 時刻表変換して
Station := CSV(TextLine(時刻表,0),1)-'駅'; // 件名から駅情報を取る
Init('',到着時刻);
if index = 2 then { // 到着時刻付き変換
// 平日の列車詳細を取得して各駅の発着時刻から到着時刻を計算する
foreach lnk2 in @indexLink['/[0-9]+/train/'] do {
Get(lnk2,cache);
PageClip('<table width="360" border="0" cellpadding="0" cellspacing="0">',
'<img src="../../../img/spacer.gif" alt="" width="10" height="10"><br>');
reachtime := TimeReachConv(Station,$_);
if reachtime <> '' then
到着時刻 := "%到着時刻%%reachtime%\n";
};
};
// 到着時刻ができていれば到着時刻付き
Result := Result + ((到着時刻 <> '') ?"%到着時刻%-----\n":'') + "%時刻表%\n";
end;
end;
end;
end;
//------------------------------------------------------------------
// デバッグ用のメイン
//------------------------------------------------------------------
begin
TagStripSet(':DL:DD:',TX_NONE,TX_NONE); // 無視するタグ
TagStripSet(':BR:',TX_COMM,TX_NONE); // <BR>はカンマ変換
// 'http://www.jreast-timetable.jp/0803/timetable/tt0034/0034040.html'
end.
Script 駅前探険倶楽部;
# 駅探時刻表 Copyright(C) 2004-2007 by nTak
#
駅名リスト[]:-
<dl class="clearfix">\
\*<dt><span>${ST}</span></dt>\
\*<dd>[<a href="${LNK}">\*</a>]</dd>\
-::
include 'comnlib.inc'; // 共通定数とライブラリ
include 'TConv.inc'; // TrainConv用の定義取込み
(* 定数テーブル *)
const
SiteInfo[6] = (
'駅前探険倶楽部', // 本体に通知する変数:サイト名
0x01, // 本体に通知する変数:同一の時刻表が曜日別になっていたら結合する
(*!!*) 0x010c, // Hi:バージョン Lo:リビジョン 自動更新の指定付き
'Copyright(C) 2004-2007 by nTak',
'http://www.ekitan.com/',
'メモ,データの再配布は禁止です'
);
// スクリプトで使用する定数
RegName[10] = ("北海道","東 北","関 東","東 海","甲信越","北 陸","関 西","中 国","四 国","九 州");
RegList[10] = ("3-1","4-1","0-1","2-1","6-1","5-1","1-1","7-1","8-1","9-1"); // URLの地域コード AN=?
#RST 09.03.20 リンクナビゲーションの変更
SiteURL = "2,%s,2,http://timetable.ekitan.com/train/TimeLineList/%s.shtml";
LinkPat[3] = ('/TimeLineList/[0-9]\-[0-9].shtml','/TimeStationList/[0-9]/[0-9]+\-[0-9].shtml','/TimeStation/[0-9]+\-[0-9]_D[0-9].shtml');
(*------------------------------------------------------------------
自動更新を行う
戻値: TRUE: 更新した
FALSE: 更新失敗または更新ファイルが無い
------------------------------------------------------------------*)
function TzAutoUpdate:boolean;export;
begin
Result := DownloadNewScript(DistURL,SiteInfo[2]); // DistURLは作者のスクリプト配布URL
end;
(*------------------------------------------------------------------
ノードの定義リストを返す
戻値: 定義文字列
リストは次の書式文字列で返す。
[アイコン番号],[名前],[検索有無フラグ],[URL]
------------------------------------------------------------------*)
function TzAttachSite(index):string;export;
begin
case index of
0: Result := FmtStr('2,%s,-1',SiteInfo[0]);
1..10: Result := FmtStr(SiteURL,RegName[index-1],RegList[index-1]);
else Result := '';
end;
end;
(*------------------------------------------------------------------
URLから読み込んでリンクを登録する
IN: index ノードインデックス
node 親ノードのID、URLの登録はこのノードに対して実行
stURL 読込むURL
cache キャッシュ有効フラグ
OUT: FALSE 路線リンクを登録した
TRUE 時刻表ページのURLだった
------------------------------------------------------------------*)
function TzGetPageLinks(index,node,stURL,cache):boolean;export;
begin
Result := False;
Get(stURL,cache);
#RST 09.03.20 リンクナビゲーションの変更
case StrPattern(stURL,LinkPat) of
1: begin // 路線
foreach lnk in @indexLink[LinkPat[1]] do
putlog(node,0:@sysdate,1:$$,2:0,3:lnk,4:ICO_GTRAIN);
end;
2: begin // 駅
#RST ページをGETして解析して登録する必要有り
foreach n in @clip[駅名リスト] do
begin
if ST = '' then Next;
lnk := 'http://timetable.ekitan.com' + LNK;
putlog(node,0:@sysdate,1:ST,2:1,3:lnk,4:ICO_STATION);
end;
end;
3: Result := True; //時刻表ページに到着
end;
end;
//------------------------------------------------------------------
// 時刻表データの抽出と変換
// '09.03.20 デザイン変更に伴う変更、本体はv5.3.4以降が必須
//------------------------------------------------------------------
function 時刻表解析(html):string;
begin
DateStr := WrapStr(html,'<p class="attention">[','現在]</p>',1); // 更新日付を取りだす
Strip(DateStr);
ln := TagWrap('title',html,FALSE); // タイトル情報から路線名等を抽出
Split('|',ln,tmp1,tmp2,ln);
Split(' ',tmp1,StationName,tmp1);
Split(' ',tmp2,RouteName,DestName,WeekName,tmp2);
BaseCaption := "%RouteName% %StationName% %DestName%"; // タイトル生成
MapLink := LINKS('駅周辺の地図',html); // 地図のURL
Caption := "件名,%BaseCaption% %DateStr%";
DestInfo:= "時刻,%RouteName%,%StationName%,%DestName%,%WeekName%\n地図,%MapLink%";
//RST 時刻表部分だけを抽出する
PageClip('<!-- \[timetable\] -->','<!-- /\[legend\] -->',html);
strip(html); // 用が済んだらHTMLタグを除去
html := Replace(html,' ',' ',TRUE); // 全角空白を半角へ置換
Init('',TimeValue,MarkList); // 作業変数の初期化
foreach ln in @Lines[html] do
begin
ln := Trim(ln); // 前後の空白を取り除く
if ln = '' then Next; // 空行なら次へ
if IsDigit(CSV(ln,0)) then // 数字で始まる行は時刻表と見なす
begin
ln := ExtractCSV(ln,ss); // まずは時刻を取出し
TimeValue := TimeValue+ss; // 時刻表に追加しておく
while CSVCount(ln) > 0 do // 時刻データがある間
begin
n := 0;
while not IsDigit(CSV(ln,n)) do Inc(n); // 時刻が出てくるまで
case n of //RST 2しか存在しないと思われる
0: // 時刻データだけ
begin Init('',ds,ns); ln := ExtractCSV(ln,ss); end;
1: // 種別と時刻
begin Init('',ds); ln := ExtractCSV(ln,ns,ss); end;
2: //RST 種別と行先と時刻
ln := ExtractCSV(ln,ns,ds,ss);
else Init('不明',ds,ns); ss := '00';
end;
ns := Replace(ns,':',':',TRUE); // : は予約文字なので全角の:へ置換
// 専用関数で処理を簡略&ちょっとだけ高速化
ss := T5TimeItem(ns,ds,ss); // <種別><行先><発時刻>へ変換
MarkList := T5MarkList(ns,ds,MarkList); // 凡例の作成
TimeValue := TimeValue+' '+ss; // 時刻表に追加する
end;
TimeValue := TimeValue+"\n";
end;
end;
Result := CatStr("\n",Caption,SiteInfo[5],DestInfo,TimeValue+'凡例,'+MarkList)+"\n\n";
end;
(*------------------------------------------------------------------
時刻表ページのURLから時刻表のテキストを返す
必要ならリンク先のデータも読み込んで変換する
IN: index ノードインデックス
pURL 親ノードのURL
URL 読込むURL
cache キャッシュ有効フラグ
OUT: TEXT 変換した時刻表テキスト
------------------------------------------------------------------*)
function TzConvMain(index,pURL,URL,cache):string; export;
//----------------------------------------------------------------
// 親ブロックのローカル変数にはアクセスできないのでcache引数が必要
begin
TagStripSet(':BR:HR:DIV:',0,0); // HTMLタグ除去で無視するタグ
TagStripSet(':SPAN:',TX_SPC,TX_NONE); // 空白に変換
TagStripSet(':LI:',TX_COMM,TX_NONE); //RST <LI>はカンマ変換
Init('',Result,PastURL); // 初期化
Get(URL,cache); // 時刻表のページを取得、多分平日
BasePage := $_; // リンク抽出用に覚えておく
#RST
#何故かカレントページ同じ方面リンクを返さないので最初だけ平日|土曜|休日を個別に処理
foreach wlnk in @ReadLink['(平日|土曜|休日)',BasePage,URL] do
begin
Get(wlnk,cache); // 時刻表のページを取得
html := $_;
Result := Result + 時刻表解析(html); // 所定のフォーマットに変換
end;
foreach dlnk in @ReadLink['*方面',BasePage,URL] do // 方面リンクを読込む
begin
Get(dlnk,cache);
foreach wlnk in @ReadLink['(平日|土曜|休日)'] do
begin
Get(wlnk,cache); // 時刻表のページを取得
html := $_;
Result := Result + 時刻表解析(html); // 所定のフォーマットに変換
end;
end;
end;
//------------------------------------------------------------------
// スクリプトデバッグ用のメイン
// 山手線・渋谷駅
//------------------------------------------------------------------
begin
// TzAutoUpdate;
Get('http://timetable.ekitan.com/train/TimeStation/164-4_D1.shtml',cache); // 時刻表のページを取得、多分平日
foreach dlnk in @ReadLink['*方面'] do // 方面リンクを読込む
begin
Message(dlnk);
end;
end.