[閒聊] 讀取重生的世界 mudlist 網頁的 php 檔

作者: laechan (揮淚斬馬雲)   2018-01-04 16:26:12
今天抽空寫了,順便學更多的 php 語法,然後同樣土法煉鋼去寫,
以下是執行結果:
> ./get_mudlist.php
2018-01-04 http://www.revivalworld.org/mud/taiwanmudlist
萬王之王 telnet://kk.muds.idv.tw:4000 325
金庸修真錄 telnet://jy.mud.com.tw:6666 248
小貓的世界 telnet://122.117.3.161:5555 154
聖殿英雄傳說 telnet://sanc.myvnc.com:4002 109
重生的世界 telnet://mud.revivalworld.org:4000 74
三國歪傳 telnet://mud.csie.org:3838 42
人在江湖 telnet://katok.no-ip.org:5555 21
狂想空間 telnet://fs.twkang.net:5555 19
五星物語 telnet://140.96.180.33:5000 16
時空幻境 telnet://td.muds.net:5000 11
笑傲江湖 telnet://wulin.game-host.org:5050 0
迴風追夢 telnet://60.199.248.181:4000 0
渾沌幻世 telnet://roc.csie.org:5555 0
虛幻時空 telnet://it.muds.net:7000 0
亂世群雄 telnet://220.133.58.190:8888 0
四度空間 telnet://void7777.no-ip.org:7777 0
夢幻七域 telnet://140.124.181.189:7000 0
龍域傳奇 telnet://dragonrealms.co:3000 0
東方故事 telnet://es.muds.net:8000 0
失落的國度 telnet://doommud.twbbs.org:4000 0
亞雷恩傳奇 telnet://arion.allowed.org:6000 0
風之大陸 telnet://54.215.169.231:4040 0
風雲再起 telnet://122.117.3.161:8000 0
霹靂爭雄錄 telnet://220.133.224.86:9999 0
再戰江湖 telnet://61.216.166.227:5678 0
瑪爾斯群英傳 telnet://218.161.10.205:8888 0
失落的亞特蘭提斯 telnet://thelostatlantis.com:1234 0
人數由多到小排序。程式碼如下:
#!/usr/bin/php -q
<?php
// 以下幾行的寫法都跟 get_news.php 一樣, 就是讀網頁然後編碼
$fh= file_get_contents('https://www.revivalworld.org/mud/taiwanmudlist');
$encode=mb_convert_encoding($fh,'BIG5','UTF-8');
// 重點就在於拆解字串的選擇
$tmps=explode("_blank'><font color=",$encode);
$date = new DateTime();
$msg = $date->format('Y-m-d').
" http://www.revivalworld.org/mud/taiwanmudlist\n";
$mark=0;
// 開始做 foreach
foreach($tmps as $tmp)
{
// 兩種字串不處理, 同 get_news
if($mark==0)
{
$mark=1;
continue;
}
if(strlen($tmp)>1000) continue;
/*
讀出來的字串大概長成以下, 亮字分別代表 mud中文名、mud英文名、
mud連線ip、mud人數。人數資訊是最難讀的。
000000>五星物語</font><br><font color=999999>The Five Star Stories</font>
</td><td bgcolor=ffffef style='font-size:15px;border-bottom:1px solid #fff'>
<a href='telnet://140.96.180.33:5000'><font color=000000>140.96.180.33</font>
</td><td bgcolor=ffffef align=center style='border-bottom:1px solid #fff'>5000
</td><td bgcolor=005f00 align=center style='color:#5f5; border-bottom:1px
solid #fff'>○</td><td bgcolor=ffffef align=center style='border-bottom:1px
solid #fff'>16</td><td bgcolor=ffffef align=center style='border-bottom:1px
solid #fff'>01/04/2018 13:38</td></tr><tr><td bgcolor=efefdf
style='border-bottom:1px solid #fff;padding:3px;'><a href=
'http://www.revivalworld.org/online/rw/mrtg/mnlmudlist/void7777.no-ip.org_7777/
void7777.no-ip.org_7777.html' target='
*/
// 先對上面那樣的字串做一些前期過濾,字串會短一點也較好處理
// 做完下面三個 replace 後,mud中文名 就會顯示在 $tmp 最前面的位置
// 而且中文名跟英文名之間會以 ## 連接
$tmp=str_replace("000000>","",$tmp);
$tmp=str_replace("999999>","",$tmp);
$tmp=str_replace("</font><br><font color=","##",$tmp);
// 取出 中文名##英文名
$p=strpos($tmp,"</font>");
$name=substr($tmp,0,$p);
// 對 ## 做拆解
$tmps1=explode("##",$name);
// 令 chi_name=中文名, eng_name=英文名
$chi_name=$tmps1[0];
$eng_name=$tmps1[1];
// 然後再對 $tmp 做過濾,先把 中文名##英文名 從 $tmp replace 掉
// 再做必要的其它 replace
$tmp=str_replace($name,"",$tmp);
$tmp=str_replace("</font></td><td bgcolor=ffffef style='font-size:15px;border-bottom:1px solid #fff'><a href='","",$tmp);
$tmp=str_replace("</font></td><td bgcolor=efefdf style='font-size:15px;border-bottom:1px solid #fff'><a href='","",$tmp);
// 這時 連線ip 就會顯示在 $tmp 最前面的位置
// 令 $ip = 連線ip
$p=strpos($tmp,"'");
$ip=substr($tmp,0,$p);
// 再把 ip 從 $tmp replace 掉
$tmp=str_replace($ip,"",$tmp);
// 剩下的字串還是很長, 但包含人數的字串大約在 250~350 的位置
$tmp=substr($tmp,250,350);
// 人數會包在 >人數</td> 這樣的字串內
// 取出人數時會取到兩種, 一種是直接為字串數字, 如 "103"
// 一種為 <font ...>103</font> 這種的, 其字串長度會 >4
$p1=strpos($tmp,">");
$p2=strpos($tmp,"</td>");
$num=substr($tmp,$p1+1,$p2-$p1-1);
// 人數不為 0 及正整數的情況 $num 長度會>4, 實際顯示為 N/A
// 這時就讓 $num 為 0 (因為讀不到人數)
if(strlen($num)>4) $num="0";
// 這個相當於 mudlist[eng_name]=({chi_name,ip,num});
// 也就是 key 值是每一個 mud 的英文名, 其內容則為一個陣列
// 該陣列裡頭存了 ({中文名, 連線ip, 目前在線人數}) 的資料
$mudlist[$eng_name]=array($chi_name,$ip,$num);
}
// 這個相當於 eng_names=keys(mudlist) 讀出所有 key 值
$eng_names=array_keys($mudlist);
// 這個相當於 s=sizeof(eng_names);
$s=sizeof($eng_names);
// 土法煉鋼: 氣泡排序法
for($i=0;$i<$s;$i++)
{
for($j=0;$j<$s;$j++)
{
// 這個相當於 n1=atoi(mudlist[eng_names[i]][2]); 把字串變成整數
$n1=(int)$mudlist[$eng_names[$i]][2];
$n2=(int)$mudlist[$eng_names[$j]][2];
// 變成整數就能比大小
if($n1>$n2)
{
$k=$eng_names[$i];
$eng_names[$i]=$eng_names[$j];
$eng_names[$j]=$k;
}
}
}
// 做格式化輸出,google到的語法是 %幾=第幾變數, 再加上後面的$什麼格式
// 後者跟 sanc 使用的一樣, 主要是前面加 %幾 這樣而已, 有三個變數時就
// 給三個變數
foreach($eng_names as $eng_name)
$msg.=sprintf("%1$-16s %2$-36s %3$4s\n",
$mudlist[$eng_name][0],$mudlist[$eng_name][1],$mudlist[$eng_name][2]);
// 最後輸出存成檔案 mudlist
$file = "/home/xxx/mudlist";
file_put_contents($file, $msg);
?>
目前設定 get_mudlist 每隔 30 分鐘會去抓一次資料來 update。
暫時就寫到這裡,等以後有空再來寫別的,例如說發票跟樂透等,
屬於「不是一定要第一時間知道最新資訊」的那種就可以寫,至於
一定要知道最新資訊的例如匯率(變動頻繁)就不寫。
一、更熟悉使用 str_replace、substr、sprintf 等字串處理函數
的使用。
二、第一次使用像是 mapping 的變數,還 ok。
三、排序理論上應該有專門的處理函數,但是在未知的情況下也可
以先用土法煉鋼的做法,用氣泡排序法來處理。
四、陣列的累加例如 tmps+=({tmp}) 這樣子的,目前還試不太出來
,有空會練習看看。目前有轉彎用法就是先用 mapping 去存東
西,再用 array_keys 就能讀出一個累加的字串。
五、學 mud coding 還是很有用的,至少在土法煉鋼上面來說,從
tmi2-mudlib 過渡到 php 幾乎可以用勢如破竹來形容,因為都
可以在 php 上找到相同或相近的語法,等於我在 mud coding
上的基礎,全都可以用在 php 腳本檔的撰寫上。
Laechan

Links booklink

Contact Us: admin [ a t ] ucptt.com