[闲聊] 读取重生的世界 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