随着互联网用户群的逐渐增多,很多时候要求用户身份认证,全国公民身份证号码查询服务中心对外提供接口供公司调用查询,貌似费用有点贵,1元1位,贵公司财大气粗是可以玩玩。接口文档:http://wenku.baidu.com/view/8abc2feb19e8b8f67c1cb93e.html,没有在官网找到,这是百度文库的说明。
      为了更好的节约成本,需要对姓名和身份证号码做基本验证,之前我也写过php版的身份证号码校验位算法(http://www.quou.cn/archives/501),如下:

def checkCardid(cardid):
    '''检查身份证号码校验位'''
    factor = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2] #前17位的权重
    c = [1,0,'X',9,8,7,6,5,4,3,2] #模11后的对应校验码
    if not _CARD_RE_.match(cardid):
        return False
    res = 0
    for i in range(17):
        res += int(cardid[i])*factor[i]
    if int(cardid[-1]) != c[res % 11]:
        return False
    return True
def checkTrueName(name):
    '''检查用户名'''
    if not name:
        return False
    rname = re.compile('[\x80-\xff]{4,30}') #用户名最长15个字
    if not rname.match(name):
        return False
    return True

      如果这都通过了,接下来调用国家提供的接口检查,不废话,贴代码:

def checkAuthCard(truename, cardid, encode='gbk'):
    '''检查用户身份信息'''
    url = 'http://app.nciic.org.cn/nciic_ws/services/NciicServices?wsdl'
    serverid = 'your serverid'
    license = 'your license'
    c = suds.client.Client(url)
    #创建xml对象
   condition = createCondition(truename, cardid, serverid).decode('gbk')
    res = c.service.nciicCheck(license, condition)
    return decodeResult(res)
def createCondition(truename, cardid, serverid, encoding='gbk'):
    '''创建请求xml条件'''
    impl = getDOMImplementation()
    idom = impl.createDocument(None, 'ROWS', None)
    top = idom.documentElement
    info = idom.createElement('INFO')
    sbm = idom.createElement('SBM')
    sbm.appendChild(idom.createTextNode(serverid))
    info.appendChild(sbm)
    row = idom.createElement('ROW')
    gmsfhm = idom.createElement('GMSFHM')
    gmsfhm.appendChild(idom.createTextNode('公民身份号码'.decode('gbk')))
    xm = idom.createElement('XM')
    xm.appendChild(idom.createTextNode('姓名'.decode('gbk')))
    row.appendChild(gmsfhm)
    row.appendChild(xm)
    orow = idom.createElement('ROW')
    orow.setAttribute('FSD', '518000')
    orow.setAttribute('YWLX', 'cx')
    ogmsfhm = idom.createElement('GMSFHM')
    ogmsfhm.appendChild(idom.createTextNode(cardid))
    oxm = idom.createElement('XM')
    oxm.appendChild(idom.createTextNode(truename.decode(encoding)))
    orow.appendChild(ogmsfhm)
    orow.appendChild(oxm)
    top.appendChild(info)
    top.appendChild(row)
    top.appendChild(orow)
    return idom.toxml(encoding = 'gb2312')
def decodeResult(res):
    '''验证结果解码'''
    result = {'code' : -1000, 'msg' : 'some error!', 'data' : ''}
    ixml = MiniXml.parseString(res)
    err = ixml.list('/RESPONSE/ROWS/ROW/')
    if err: #检查接口是否出错
         result['code'] = -642
        result['msg'] = err['ErrorMsg']
        return result
    xmres = ixml.get('/ROWS/ROW/OUTPUT/ITEM/result_xm').decode('utf-8').encode('gbk') #姓名结果
    sfhres = ixml.get('/ROWS/ROW/OUTPUT/ITEM/result_gmsfhm').decode('utf-8').encode('gbk') #身份号码结果
    xpres = ixml.get('/ROWS/ROW/OUTPUT/ITEM/xp').decode('utf-8').encode('gbk') #相片
    cres = {'status' : 0, 'remark' : '姓名检查结果:%s,身份号码检查结果:%s' % (xmres, sfhres), 'xphone' : xpres}
    if xmres == '一致' and sfhres == '一致':
        cres['status'] = 1
    result['code'] = 200
    result['msg'] = 'success!'
    result['data'] = json.write(cres)
    return result

文中出现MiniXml模块,即是上篇文中中分享的好用的xml解析模块,到此为止。

      好久没有写过文章了,因为业务需求我一直扩展星哥之前写的一个XmlConfig模块,但改到后面,发现改变了原本的模块意图,最后被星哥批评一顿,重新整理了一下整个模块,弄一个xml解析模块类,自己用着很好用,贴出来跟大家共享,为了更好用,减少属性和值之间的纠葛,先贴代码,再给示例,版权归星哥(http://t.qq.com/firemeteor )所有。

import re
from xml.dom import minidom
class MiniXml:
    def __init__(self):
        self._dom_ = None
        self._data_ = None
    def parseXml(self, encoding):
        d = self.domToDict(self._dom_, encoding, None)
        self._data_=self.loadData(d, '', None)
    def loadFile(self, fname):
        f = open(fname, 'r')
        s = f.read()
        f.close()
        self.loadString(s)
        return self
    def loadString(self, string):
        if string[:5] == '', 1)
            m = re.search(r'encoding=\W([\w\-]+)\W', ss[0])
            if m:
                string = ss[1].decode(m.group(1)).encode('utf8')
            else:
                string = ss[1]
        self._dom_ = minidom.parseString(string)
        return self
    def domToDict(self, node, encoding='utf8', data=None):
        if data == None:
            data = {}
        if node.nodeType == node.DOCUMENT_NODE:
            self.domToDict(node.firstChild, encoding, data)
            return data
        d = {}
        if node.hasChildNodes():
            for i in node.childNodes:
                if i.nodeType == i.TEXT_NODE:
                    if d.has_key(''):
                        d[''] += i.nodeValue.encode(encoding)
                    else:
                        d[''] = i.nodeValue.encode(encoding)
                elif i.nodeType == i.ELEMENT_NODE:
                    self.domToDict(i, encoding, d)
        if node.hasAttributes():
            d[''] = dict([(i[0].encode(encoding), i[1].encode(encoding))
                                    for i in node.attributes.items()])
        if not node.hasAttributes() and not node.hasChildNodes():
            d[''] = ''
        key = node.nodeName.encode(encoding)
        if data.has_key(key):
            if type(data[key]) != list:
                data[key] = [data[key]]
            data[key].append(d)
        else:
            data[key] = d
    def loadData(self, d, p, data=None):
        if data == None:
            data = {}
        if type(d) == list:
            for dd in d:
                if type(dd) == dict:
                    self.loadData(dd, p, data)
            return None
        cs = []
        if d.has_key(''):
            cs.append(d.pop('').strip())
        if d.has_key(''):
            cs.append(d.pop(''))
        for c in cs:
            if data.has_key(p):
                if type(data[p]) != list:
                    data[p] = [data[p]]
                data[p].append(c)
            else:
                data[p] = c
        for k, v in d.items():
            self.loadData(v, p + '/' + k, data)
        return data
    def get(self, path, df=None):
        return self._data_.get(path, df)
    def list(self, path):
        pos = len(path)
        return dict([(i[pos:], self._data_[i]) for i in self._data_ if i.find(path) == 0])
    def end(self):
        self._dom_.unlink()
def parseFile(fname, encoding = 'utf8'):
    _i = MiniXml()
    _i.loadFile(fname).parseXml(encoding)
    _i.end()
    return _i
def parseString(string, encoding = 'utf8'):
    _i = MiniXml()
    _i.loadString(string).parseXml(encoding)
    _i.end()
    return _i

      下面再来一个应用示例,如果有更高的需求完全可以扩展,很容易更改代码,也没有几行。

res = ''
ixml = MiniXml.parseString(res)
print ixml.get('/t/a/b') #[{'x': '1', 'xx': '2'}, {'x': '1'}]
print ixml.list('/t/k/') #{'c': {'x': '1', 'xx': '2'}, 'e': '', 'd': {'hh': 'xxx'}}
17 / 05 / 2011 buling

好久没整理过东西了,之前本来打算写一下PHP模块实现方式。整理5.3的时候我也写了,其实也没有很多内容,很晚了,睡觉。
1、引入 __DIR__ magic常量 定位脚本的目录

    echo __DIR__."|".dirname(__FILE__);

2、允许从2个值的or/and表达式快速的获取一个非空的值

    echo (1 ?: 0) ."|". ("" ?: 0)."|". var_export(array() ?: array(1), true);

3、类添加__callStatic方法,等价于 __call(),但它是为调用静态方法准备的。下面来看示例:

    class xxx{
        function __call($func, $args){
            echo "function name:".$func;
            echo "
"; echo "args:".var_export($args, true); } static function __callStatic($func, $args){ echo "static function name:".$func; echo "
"; echo "static args:".var_export($args, true); } } $x = new xxx(); $x->testfunc("oo"); echo "
"; xxx::teststatic("xx");

4、动态的调用静态的方法

    class xx{
        static function test(){
            echo __METHOD__;
        }
    }
    $c = "xx";
    $m = "test";
    $c::$m();

5、延迟静态绑定(静态处理从编译时延迟到执行时)

class A{
    static function whoami(){
        echo __CLASS__;
    }
    static function say1(){
        self::whoami();
    }
    static function say2(){
        static::whoami();
    }
}
class B extends A{
    static function whoami(){
        echo __CLASS__;
    }
}
class C extends A{
    static function whoami(){
        echo __CLASS__;
    }
}
B::say1();
C::say2();

6、MySQLInd (高速的专门为PHP设计的MySQL调用库接口)
7、INI Magic
8、扩展的 OpenSSL 函数
9、SPL(Standard PHP Library) 优化
10、时间处理进行扩展了和添加

    $date = strtotime("11-05-17 00:00:00");
    echo date("Y-m-d", $date)."|";
    $date = date_create_from_format("y-m-d", "11-05-17");
    echo $date->format("Y-m-d");

11、垃圾回收器(为复杂和长时间运行脚本的执行结束周期释放内存的清理)

     gc_enable(); // 允许垃圾回收
    var_dump(gc_enabled()); // true
    var_dump(gc_collect_cycles()); // 某个元素的清理
    gc_disable(); // 禁止垃圾回收

12、NOWDOC(不对HEREDOC进行转译)

    $fubar = "xxx";
    $xbar = <<

13、匿名函数体验

    $ofun = create_function('$a, $b', 'return $a*$b;'); //不要忘了分号,传统方法
    echo $ofun(2, 5);
    $nfun = function ($a, $b){
        return $a*$b;
    };//不要忘了分号,现代方法
    echo $nfun(3, 5);

14、闭包体验

    $arr = array(1, 2, 3, 5, 6, 7);
    $res = array_filter($arr, function($v) { return $v >4; });
    var_dump($res);
    function countnum(){
        $num = 0;
        $testt = function() use(&$num){
            ++$num;
            echo $num;
        };
        return $testt;
    }
    $t = countnum();
    $t();
    $t();

15、命名空间

    namespace xxx; //第一个namespace需要在所有输出之前
    function t(){
        return __NAMESPACE__;
    }
    namespace xxx;
    function t(){
        return __NAMESPACE__;
    }
    echo \xx\t()."|";
    echo \xxx\t();