├── .gitignore ├── README.md └── pyfetion.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.mdb 2 | *.ldb 3 | *.sln 4 | *.config 5 | Debug/ 6 | Release/ 7 | obj/ 8 | config.inc.php 9 | .idea/* 10 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## pyfetion 2 | 3 | With pyfetion you can send sms to your fetion friends(include yourself) in an easy way. 4 | 5 | All API refers to 6 | 7 | https://code.google.com/p/php-fetion/source/browse/trunk/lib/PHPFetion.php 8 | 9 | ### How to use 10 | 11 | **Notice** 12 | 13 | - Make sure your file encoding is utf-8. 14 | 15 | - Friends list is removed because each request needs different token. 16 | 17 | ``` 18 | yourmob = "136XXXXXXXX" 19 | password = '123456' 20 | 21 | send_to = '138XXXXXXXX' 22 | msg = 'SMS just for test!' 23 | 24 | m = Fetion(yourmob, password) 25 | 26 | # DEBUG 27 | 28 | m = Fetion(yourmob, password, 1) 29 | 30 | try: 31 | print m.send_msg(send_to, msg) 32 | except FetionError, e: 33 | print e 34 | ``` 35 | -------------------------------------------------------------------------------- /pyfetion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | """ 6 | @version: v0.1 7 | @author: phpergao 8 | @license: Apache Licence 9 | @contact: endoffight@gmail.com 10 | @site: http://www.phpgao.com 11 | @software: PyCharm 12 | @file: fetion.py 13 | @time: 15-1-27 下午8:55 14 | python调用飞信发送短信 15 | """ 16 | 17 | import urllib2 18 | import urllib 19 | import cookielib 20 | import re 21 | 22 | 23 | class FetionError(Exception): 24 | def __init__(self, code=0): 25 | self.code = code 26 | 27 | def __str__(self): 28 | errors = { 29 | 0: 'Unknown error', 30 | 404: 'Wrong mobile number', 31 | 301: 'Login error', 32 | 403: 'Get token error', 33 | 400: 'Error happens while requesting', 34 | 401: 'Error happens while sending to myself', 35 | 402: 'Error happens while sending to others' 36 | } 37 | return errors[self.code] 38 | 39 | 40 | class Fetion(): 41 | def __init__(self, mob, password, debug=False): 42 | self.base_url = 'http://f.10086.cn' 43 | self.mob = mob 44 | self.password = password 45 | self.cookie = '' 46 | self.debug = debug 47 | self.do_login() 48 | 49 | def __getattr__(self, attr): 50 | urls = { 51 | 'login_url': '/huc/user/space/login.do', 52 | 'check_login_url': '/im/login/cklogin.action', 53 | 'send_to_me_url': '/im/user/sendMsgToMyselfs.action', 54 | 'send_to_other_url': '/im/chat/sendMsg.action?touserid=', 55 | 'get_uid_url': '/im/index/searchOtherInfoList.action', 56 | 'csrftoken_url': '/im/chat/toinputMsg.action?touserid=', 57 | } 58 | return urls[attr] 59 | 60 | def do_login(self): 61 | post_data = { 62 | 'mobilenum': self.mob, 63 | 'password': self.password, 64 | "m": "submit", 65 | "fr": "space", 66 | "backurl": "http://f.10086.cn/" 67 | } 68 | self.send(self.login_url, post_data) 69 | self.do_check_login() 70 | 71 | def do_check_login(self): 72 | self.send(self.check_login_url) 73 | 74 | def send_msg(self, mob, msg): 75 | if mob == self.mob: 76 | return self.send_to_myself(msg) 77 | else: 78 | return self.send_to_other(mob, msg) 79 | 80 | def send_to_myself(self, msg): 81 | msg = {'msg': msg} 82 | xml = self.send(self.send_to_me_url, msg) 83 | if re.search(r'(短信发送成功)', xml) is None: 84 | raise FetionError(401) 85 | return True 86 | 87 | def send_to_other(self, mob, msg): 88 | uid = self.get_uid(mob) 89 | csrf_token = self.getcsrftoken(uid) 90 | uri = self.send_to_other_url + uid 91 | msg = {'msg': msg, 'csrfToken': csrf_token} 92 | xml = self.send(uri, msg) 93 | if re.search(r'(发送消息成功)', xml) is None: 94 | raise FetionError(402) 95 | return True 96 | 97 | def get_uid(self, mob): 98 | data = {'searchText': mob} 99 | xml = self.send(self.get_uid_url, data) 100 | match = re.search(r'toinputMsg\.action\?touserid=(?P\d+)', xml) 101 | if match: 102 | return match.group('uid') 103 | else: 104 | raise FetionError(404) 105 | 106 | def getcsrftoken(self, uid): 107 | uri = self.csrftoken_url + uid 108 | xml = self.send(uri) 109 | match = re.search(r'name="csrfToken"\svalue="(?P\w+)"', xml, re.M) 110 | if match: 111 | return match.group('token') 112 | else: 113 | raise FetionError(403) 114 | 115 | def send(self, uri, data=''): 116 | url = self.base_url + str(uri) 117 | req = urllib2.Request(url) 118 | # cookie enabled 119 | if self.cookie == '': 120 | self.cookie = cookielib.CookieJar() 121 | 122 | cookie_handler = urllib2.HTTPCookieProcessor(self.cookie) 123 | 124 | if self.debug: 125 | http_handler = urllib2.HTTPHandler(debuglevel=1) 126 | opener = urllib2.build_opener(cookie_handler, http_handler) 127 | else: 128 | opener = urllib2.build_opener(cookie_handler) 129 | 130 | req.add_header('User-Agent', 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/31.0') 131 | req.add_header('Content-Type', 'application/x-www-form-urlencoded') 132 | req.add_header('Cache-Control', 'no-cache') 133 | req.add_header('Accept', '*/*') 134 | req.add_header('Connection', 'close') 135 | # post data 136 | if data: 137 | post_data = urllib.urlencode(data) 138 | req.add_data(post_data) 139 | req.add_header('Content-Length', len(post_data)) 140 | try: 141 | response = opener.open(req) 142 | except urllib2.URLError, error: 143 | raise FetionError(400) 144 | exit() 145 | return response.read() 146 | 147 | 148 | if __name__ == '__main__': 149 | 150 | yourmob = "136XXXXXXXX" 151 | password = '123456' 152 | 153 | send_to = '138XXXXXXXX' 154 | message = '测试短信,请无视' 155 | 156 | m = Fetion(yourmob, password) 157 | try: 158 | print m.send_msg(send_to, message) 159 | except FetionError, e: 160 | print e --------------------------------------------------------------------------------