GS-M.ORG游戏服务器状态查询网站开源

大概一年前和朋友弄了GS-M.ORG,一个游戏服务器状态查询网站,后来由于嫌维护麻烦就没继续做下去了,刚好朋友提起,想到备份后就一直没动过,放着也没用,今天就把它开源了。

网站前端使用Bootstrap框架+Bootswatch主题,内置了以前汇诚开源过的HCount、HSign等,多语言系统。支持服务器名称、人数等信息的查询,生成服务器banner、在线人数图片等。服务器信息获取方面主要使用GameQ库,支持上百款游戏服务器。整合了PHPBB论坛,添加服务器必须登录后才可添加(作整理的时候注释了这段,选择性开启)。另外获取服务器数据的查询服务器和网站服务器是分离的。

问题

  1. 服务器信息必须就近获取,例如国内的查询服务器就经常无法获取到国外服务器的信息,不知道是不是延迟导致的。当时的解决方案是部署两台国内、一台拉斯维加斯、一台卢森堡的服务器,后两者分别负责美洲和欧洲的服务器查询。
  2. 后端查询服务器采用的方式并不完善,是根据服务器最后的更新时间进行轮询。每次更新获取15个上一次更新的时候可以连接的服务器,再获取5个上一次更新无法连接的服务器。某些情况下会影响更新速度,或者出现timeout。

下面是Github地址
网站(不含论坛):https://github.com/GS-M-ORG/GS-M.ORG-Website
查询服务器:https://github.com/GS-M-ORG/GS-M.ORG-QueryServer

微信小程序动态input验证

最近写微信小程序,需要使用到动态表单,输入框都要从服务器上加载。这里分享一下解决方案。

let app = getApp()
let ajax = require('../../network/ajax')
Page({
  data: {
    Custom: {},
    lists: []
  },
  onLoad: function () {
    if (app.globalData.CUSTOM) //预先获取了自定义表单信息,有ID, Required两个参数
    {
      var array = new Array();
      for(var i=0;i<app.globalData.CUSTOM.length;i++)
      {
        var array2 = new Array();
        array2['index'] = app.globalData.CUSTOM[i]['ID']
        array2['value'] = ""
        array[i] = array2
      }
      this.setData({
        Custom: app.globalData.CUSTOM,
        lists: array
      })
    }
  },
  bindKeyInput: function (e) {
    let id = e.currentTarget.dataset.id;
    var thedata = new Array();
    thedata['index'] = id
    thedata['value'] = e.detail.value
    this.data.lists[id] = thedata;
    this.setData({
      lists: this.data.lists
    })
  },  
  checkExtraInput()
  {
    console.log(this.data.Custom);
    for(var i=0;i<this.data.lists.length;i++)
    {
      var value = this.data.lists[i].value;
      if (this.data.Custom[i]['Required'] == 1 && value == "") return false;
    }
    return true;
  },
  bindFormSubmit: function (e){
    if (!this.checkExtraInput()) {
      wx.showModal({
        content: '请完成表单后再试!',
        showCancel: false
      });
    }
    else
    {
      var array = new Object();
      for(var i=0;i<this.data.lists.length;i++)
      {
        var array2 = new Object();
        array2.id = this.data.Custom[i]['ID'];
        array2.value = this.data.lists[i].value;
        array[i] = array2;
      }
      console.log(JSON.stringify(array)); //最后转为JSON格式,Post到服务器上
      });
    }
  }
});

腾讯云SCF定时访问页面(Python)

最近用到了腾讯云的无服务器云函数做一个定时通知功能,记录一下。
SCF有免费额度,综合了调用次数、资源使用量、代码运行时长。
由于我的PHP文件每次执行时间较长,为了用这个免费额度→_→,这里设置了3秒超时,后端PHP用ignore_user_abort函数,使得发送请求后可不等待回应,切断请求后仍在后台运行。

# -*- coding: utf8 -*-
import urllib.request
def main_handler(event, context):
    try:
        urllib.request.urlopen("127.0.0.1/yourfile.php",None,3)
    except Exception as e:
        print(e)

用Simple HTML DOM自动查高考分数与录取情况

这个程序原本是做来给自己用的,免去了查成绩的手抖又心跳加速打信息打错等各种问题,页面改动后直接发送邮件到自己的邮箱里,不看也不行→_→哈哈哈
Simple HTML DOM:http://simplehtmldom.sourceforge.net/
我这里用的查询地址是广州招考的,查询没有验证码,没有了验证码识别的问题。

先模拟一次提交,找到提交数据。

用Curl模拟提交

$cookie_file = tempnam("tmp","cookie");
function postData($url, $data)
{
  global $cookie_file;
  $ch = curl_init();
  $timeout = 300;
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  curl_setopt($ch, CURLOPT_COOKIEJAR,  $cookie_file);
  $handles = curl_exec($ch);
  curl_close($ch);
  return $handles;
}
$contents = file_get_contents("http://gaokao.gzzk.cn/mopub_login3.aspx");
$html = str_get_html($contents);
$__VIEWSTATE = $html->find('#__VIEWSTATE',0)->attr['value'];
$__VIEWSTATEGENERATOR = $html->find('#__VIEWSTATEGENERATOR',0)->attr['value'];
$__EVENTVALIDATION = $html->find('#__EVENTVALIDATION',0)->attr['value'];
  $url='http://gaokao.gzzk.cn/mopub_login3.aspx';
$argv = array(
    '__EVENTTARGET' => "LoginButton", 
    '__EVENTARGUMENT' => "",
    '__VIEWSTATE' => $__VIEWSTATE,
    '__VIEWSTATEGENERATOR' => $__VIEWSTATEGENERATOR, 
    '__EVENTVALIDATION' => $__EVENTVALIDATION,
    'text_biaoshi' => "", //考号
    'text_mima' => '' //密码
);
  $rdata = postData($url, $argv);

测试发现还有来源验证。。于是postData函数多加一行设置Referer。

测试成功,还有一层跳转

图中的链接对应结果页。

$html2 = str_get_html($rdata);
$newurl = "http://gaokao.gzzk.cn" . $html2->find('a',0)->attr['href'];
$contents2 = getData($newurl);
![](https://tlingc.ocdn.wuicent.com/2017/07/TIM截图20170722165515.jpg)

成功!再把成绩表格选取出来,并添加MD5验证,如果MD5没有变,则每隔5秒刷新,在页面改动后,把这个选取出来的表格作为邮件正文发送到我的邮箱即可。

$html3 = str_get_html($contents2);
$result = $html3->find('#td_center',0)->innertext;
echo $result; //result -> 成绩表格

完整源码

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<?php
  $cookie_file = tempnam("tmp","cookie");
  function postData($url, $data)
  {
    global $cookie_file;
    $ch = curl_init();
    $timeout = 300;
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_REFERER, "http://gaokao.gzzk.cn/mopub_login3.aspx");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_COOKIEJAR,  $cookie_file);
    $handles = curl_exec($ch);
    curl_close($ch);
    return $handles;
  }
  function getData($url)
  {
    global $cookie_file;
    $ch = curl_init();
    $timeout = 300;
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
    $handles = curl_exec($ch);
    curl_close($ch);
    return $handles;
  }
  include("simple_html_dom.php");
  $contents = file_get_contents("http://gaokao.gzzk.cn/mopub_login3.aspx");
  $html = str_get_html($contents);
  $__VIEWSTATE = $html->find('#__VIEWSTATE',0)->attr['value'];
  $__VIEWSTATEGENERATOR = $html->find('#__VIEWSTATEGENERATOR',0)->attr['value'];
  $__EVENTVALIDATION = $html->find('#__EVENTVALIDATION',0)->attr['value'];
    $url='http://gaokao.gzzk.cn/mopub_login3.aspx';
  $argv = array(
      '__EVENTTARGET' => "LoginButton", 
      '__EVENTARGUMENT' => "",
      '__VIEWSTATE' => $__VIEWSTATE,
      '__VIEWSTATEGENERATOR' => $__VIEWSTATEGENERATOR, 
      '__EVENTVALIDATION' => $__EVENTVALIDATION,
      'text_biaoshi' => "", //考号
      'text_mima' => '' //密码
  );
    $rdata = postData($url, $argv);

    $html2 = str_get_html($rdata);
  $newurl = "http://gaokao.gzzk.cn" . $html2->find('a',0)->attr['href'];
  $contents2 = getData($newurl);
  $html3 = str_get_html($contents2);
  $result = $html3->find('#td_center',0)->innertext;
  echo $result; //result -> 成绩表格
  $originmd5 = ""; //成绩出来前的td_center的MD5
  $currentmd5 = md5($result);
  if($currentmd5 != $originmd5)
  {
    echo "页面发生改动!";
    $tablelist = $html3->find('#table_list',0)->innertext;
    $html4 = str_get_html($tablelist);
    $totalmark = $html4->find('td.mytdfenge1',23)->innertext; //算总分
    //DO STH
  }
  else
  {
    echo '<meta http-equiv="refresh" content="5;url=checker.php">';
  }
?>
</body>
</html>