diff --git a/README.md b/README.md index ee008a48ddb699eda8d8230bad495fb852ad2622..3bc16317bed4597b10ed1b5fa89c04258c2bfbce 100755 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ #### 依赖库 - 依赖若快 若快注册地址:http://www.ruokuai.com/client/index?6726 推荐用若快,请注册个人账号 ``` - PS: 现在登录可以不不用验证码了, + PS: 现在登录有一定几率不用验证码了, ``` - - 项目依赖包 requirements.txt + - 项目依赖包查看 requirements.txt - 安装方法-Windows: - 安装方法-Linux: - root用户(避免多python环境产生问题): python2 -m pip install -i https://pypi.tuna.tsinghua.e -r requirements.txt @@ -107,5 +107,5 @@ #### 如果觉得项目还不错,可以考虑打赏一波 - - ![image](https://github.com/testerSunshine/12306/blob/master/uml/wx.jpeg?imageMogr2/auto-orient/strip) ![image](https://github.com/testerSunshine/12306/blob/master/uml/zfb.jpeg?imageMogr2/auto-orient/strip) + ![image](https://github.com/testerSunshine/12306/blob/master/uml/wx.jpeg?imageMogr2/auto-orient/strip) diff --git a/UnitTest/TestAll.py b/UnitTest/TestAll.py index 3cc59ac49b3e70637d98d2b85545eed5cad67286..103cf270a937b37e02cf426be6d7e9665c7eec25 100644 --- a/UnitTest/TestAll.py +++ b/UnitTest/TestAll.py @@ -45,7 +45,7 @@ class testAll(unittest.TestCase): 实测pushbear是否可用 :return: """ - sendPushBear("pushbear 微信通知测试一下") + sendPushBear(u"pushbear 微信通知测试一下") # def testConfig(self): # """ diff --git a/config/urlConf.py b/config/urlConf.py index 1ec985d714d5ccae0e4d6da5e03e6ca89b789d34..40ce594a634ec86a8d754fba946e9df78aaa268a 100755 --- a/config/urlConf.py +++ b/config/urlConf.py @@ -7,7 +7,19 @@ urls = { "auth": { # 登录接口 "req_url": "/passport/web/auth/uamtk", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", + "Host": "kyfw.12306.cn", + "Content-Type": 1, + "re_try": 10, + "re_time": 1, + "s_time": 0.1, + "is_logger": True, + "is_json": True, + }, + "uamtk-static": { # 登录接口 + "req_url": "/passport/web/auth/uamtk-static", + "req_type": "get", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", "Host": "kyfw.12306.cn", "Content-Type": 1, "re_try": 10, @@ -19,7 +31,7 @@ urls = { "login": { # 登录接口 "req_url": "/passport/web/login", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/login/init", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", "Host": "kyfw.12306.cn", "Content-Type": 1, "re_try": 10, @@ -32,7 +44,7 @@ urls = { "left_ticket_init": { # 登录接口 "req_url": "/otn/leftTicket/init", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/login/init", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", "Host": "kyfw.12306.cn", "Content-Type": 1, "re_try": 10, @@ -45,7 +57,7 @@ urls = { "getCodeImg": { # 登录验证码 "req_url": "/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}", "req_type": "get", - "Referer": "https://kyfw.12306.cn/otn/login/init", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", "Host": "kyfw.12306.cn", "Content-Type": 1, "re_try": 10, @@ -55,17 +67,42 @@ urls = { "is_json": False, "not_decode": True, }, + "getCodeImg1": { # 登录验证码 + "req_url": "/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&{0}&callback=jQuery19108016482864806321_1554298927290&_=1554298927293", + "req_type": "get", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", + "Host": "kyfw.12306.cn", + "Content-Type": 1, + "re_try": 10, + "re_time": 1, + "s_time": 0.1, + "is_logger": True, + "is_json": False, + "not_decode": True, + }, "codeCheck": { # 验证码校验 "req_url": "/passport/captcha/captcha-check", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/login/init", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", "Host": "kyfw.12306.cn", "Content-Type": 1, "re_try": 10, "re_time": 1, "s_time": 0.1, "is_logger": True, - "is_json": True, + "is_json": False, + }, + "codeCheck1": { # 验证码校验 + "req_url": "/passport/captcha/captcha-check?callback=jQuery19108016482864806321_1554298927290&answer={0}&rand=sjrand&login_site=E&_={1}", + "req_type": "get", + "Referer": "https://kyfw.12306.cn/otn/resources/login.html", + "Host": "kyfw.12306.cn", + "Content-Type": 1, + "re_try": 10, + "re_time": 1, + "s_time": 0.1, + "is_logger": True, + "is_json": False, }, "loginInit": { # 登录页面 "req_url": "/otn/login/init", @@ -90,6 +127,29 @@ urls = { "is_test_cdn": True, "is_json": False, }, + "loginInitCdn1": { # 登录页面 + "req_url": "/otn/resources/login.html", + "req_type": "get", + "Referer": "https://kyfw.12306.cn/otn/view/index.html", + "Host": "kyfw.12306.cn", + "re_try": 1, + "re_time": 1, + "s_time": 0.1, + "is_logger": False, + "is_test_cdn": False, + "is_json": False, + }, + "getDevicesId": { # 获取用户信息 + "req_url": "/otn/HttpZF/logdevice?algID=sV3XbAmeRg&hashCode=9JGmYn7tyQpz7ARsg5hs0afNuPy3NlZXSCye9VHEJII&FMQw=0&q4f3=zh-CN&VPIf=1&custID=133&VEek=unknown&dzuS=0&yD16=1&EOQP=1acda25d532249b0b1635671927a47e0&jp76=69f27b80c0ec8437d2a1f4278674e7fb&hAqN=MacIntel&platform=WEB&ks0Q=e848b8c6800147e416e6663782ca3789&TeRS=831x1440&tOHY=24xx900x1440&Fvje=i1l1o1s1&q5aJ=-8&wNLf=99115dfb07133750ba677d055874de87&0aew=Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_13_4)%20AppleWebKit/605.1.15%20(KHTML,%20like%20Gecko)%20Version/11.1%20Safari/605.1.15&E3gR=3492a53db5709ba4cade22e8fe879dc1×tamp=1554304524960", + "req_type": "get", + "Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/", + "Host": "kyfw.12306.cn", + "re_try": 10, + "re_time": 1, + "s_time": 0.01, + "is_logger": True, + "is_json": False, + }, "getUserInfo": { # 获取用户信息 "req_url": "/otn/index/initMy12306", "req_type": "get", diff --git a/damatuCode/ruokuai.py b/damatuCode/ruokuai.py index 09509e79295294ec00f3152a722be59ef1c5bb77..5864735b67a45fa5d740e47c4fe4be803fd911b3 100644 --- a/damatuCode/ruokuai.py +++ b/damatuCode/ruokuai.py @@ -1,4 +1,6 @@ # coding:utf-8 +import base64 + import requests from hashlib import md5 @@ -40,6 +42,23 @@ class RClient(object): print(r) return r.json() + def rk_create_base64(self, im, im_type, timeout=60): + """ + base64验证码识别 + im: 图片字节 + im_type: 题目类型 + :return: + """ + params = { + 'typeid': im_type, + 'timeout': timeout, + 'image': im, + } + params.update(self.base_params) + r = requests.post('http://api.ruokuai.com/create.json', data=params, headers=self.headers) + print(r) + return r.json() + def rk_report_error(self, im_id): """ im_id:报错题目的ID diff --git a/init/login.py b/init/login.py index eef5967728587bd11f440de68dd641a6e7a5abdb..deaccbb0c36047e7b1657a5a22256a291cb07b1c 100755 --- a/init/login.py +++ b/init/login.py @@ -1,8 +1,12 @@ # -*- coding=utf-8 -*- +import copy +import random +import time +from collections import OrderedDict from time import sleep from config.ticketConf import _get_yaml -from inter.GetPassCodeNewOrderAndLogin import getPassCodeNewOrderAndLogin +from inter.GetPassCodeNewOrderAndLogin import getPassCodeNewOrderAndLogin, getPassCodeNewOrderAndLogin1 from inter.GetRandCode import getRandCode from inter.LoginAysnSuggest import loginAysnSuggest from inter.LoginConf import loginConf @@ -17,25 +21,41 @@ class GoLogin: self.is_auto_code = is_auto_code self.auto_code_type = auto_code_type + # def auth(self): + # """ + # 认证 + # :return: + # """ + # authUrl = self.session.urls["auth"] + # authData = {"appid": "otn"} + # tk = self.session.httpClint.send(authUrl, authData) + # return tk + def auth(self): - """认证""" - authUrl = self.session.urls["auth"] - authData = {"appid": "otn"} - tk = self.session.httpClint.send(authUrl, authData) - return tk + """ + :return: + """ + self.session.httpClint.send(self.session.urls["loginInitCdn1"]) + uamtkStaticUrl = self.session.urls["uamtk-static"] + uamtkStaticData = {"appid": "otn"} + return self.session.httpClint.send(uamtkStaticUrl, uamtkStaticData) def codeCheck(self): """ 验证码校验 :return: """ - codeCheck = self.session.urls["codeCheck"] - codeCheckData = { - "answer": self.randCode, - "rand": "sjrand", - "login_site": "E" - } - fresult = self.session.httpClint.send(codeCheck, codeCheckData) + # codeCheck = self.session.urls["codeCheck"] + # codeCheckData = { + # "answer": self.randCode, + # "rand": "sjrand", + # "login_site": "E" + # } + # fresult = self.session.httpClint.send(codeCheck, codeCheckData) + codeCheckUrl = copy.deepcopy(self.session.urls["codeCheck1"]) + codeCheckUrl["req_url"] = codeCheckUrl["req_url"].format(self.randCode, int(time.time() * 1000)) + fresult = self.session.httpClint.send(codeCheckUrl) + fresult = eval(fresult.split("(")[1].split(")")[0]) if "result_code" in fresult and fresult["result_code"] == "4": print (u"验证码通过,开始登录..") return True @@ -53,12 +73,14 @@ class GoLogin: :return: 权限校验码 """ logurl = self.session.urls["login"] - logData = { - "username": user, - "password": passwd, - "appid": "otn" - } - tresult = self.session.httpClint.send(logurl, logData) + + loginData = OrderedDict() + loginData["username"] = user, + loginData["password"] = passwd, + loginData["appid"] = "otn", + loginData["answer"] = self.randCode, + + tresult = self.session.httpClint.send(logurl, loginData) if 'result_code' in tresult and tresult["result_code"] == 0: print (u"登录成功") tk = self.auth() @@ -116,7 +138,15 @@ class GoLogin: login_num = 0 while True: if loginConf(self.session): - result = getPassCodeNewOrderAndLogin(session=self.session, imgType="login") + # result = getPassCodeNewOrderAndLogin(session=self.session, imgType="login") + self.auth() + + devicesIdRsp = self.session.httpClint.send(self.session.urls.get("getDevicesId")) + devicesId = eval(devicesIdRsp.split("(")[1].split(")")[0].replace("'", ""))["dfp"] + if devicesId: + self.session.httpClint.set_cookies(RAIL_DEVICEID=devicesId) + + result = getPassCodeNewOrderAndLogin1(session=self.session, imgType="login") if not result: continue self.randCode = getRandCode(self.is_auto_code, self.auto_code_type, result) diff --git a/inter/GetPassCodeNewOrderAndLogin.py b/inter/GetPassCodeNewOrderAndLogin.py index b57166f29db80918b59af789b0234e8c2137d1f6..3c93f961870b7067577b9734d10b826b5f7b7bf9 100644 --- a/inter/GetPassCodeNewOrderAndLogin.py +++ b/inter/GetPassCodeNewOrderAndLogin.py @@ -1,7 +1,6 @@ # coding=utf-8 import copy import random -import time def getPassCodeNewOrderAndLogin(session, imgType): @@ -35,3 +34,41 @@ def getPassCodeNewOrderAndLogin(session, imgType): return result except OSError: print(u"验证码下载失败,可能ip被封,确认请手动请求: {0}".format(codeImgUrl)) + + +def getPassCodeNewOrderAndLogin1(session, imgType): + """ + 获取验证码2 + :param session: + :param imgType: + :return: + """ + if imgType == "login": + codeImgUrl = copy.deepcopy(session.urls["getCodeImg1"]) + codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random()) + else: + codeImgUrl = copy.deepcopy(session.urls["codeImgByOrder"]) + codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random()) + print(u"下载验证码...") + img_path = './tkcode.png' + codeImgUrlRsp = session.httpClint.send(codeImgUrl) + result = eval(codeImgUrlRsp.split("(")[1].split(")")[0]).get("image") + try: + if isinstance(result, dict): + print(u"下载验证码失败, 请手动检查是否ip被封,或者重试,请求地址:https://kyfw.12306.cn{}".format(codeImgUrl.get("req_url"))) + return False + else: + print(u"下载验证码成功") + try: + with open(img_path, 'wb', encoding="utf-8") as img: + img.write(result) + except Exception: + with open(img_path, 'wb') as img: + img.write(result) + return result + except OSError: + print(u"验证码下载失败,可能ip被封,确认请手动请求: {0}".format(codeImgUrl)) + + +if __name__ == '__main__': + pass diff --git a/inter/GetRandCode.py b/inter/GetRandCode.py index 56601746305da8c7f1665e9117dbc3cc329eab87..a3be94a932c462a787ca4e746cc55e3ff91d89ee 100644 --- a/inter/GetRandCode.py +++ b/inter/GetRandCode.py @@ -23,7 +23,8 @@ def getRandCode(is_auto_code, auto_code_type, result): if auto_code_type == 2: rc = RClient(_get_yaml()["auto_code_account"]["user"], _get_yaml()["auto_code_account"]["pwd"]) # im = open('./tkcode', 'rb').read() - Result = rc.rk_create(result, 6113) + # Result = rc.rk_create(result, 6113) + Result = rc.rk_create_base64(result, 6113) if "Result" in Result: return codexy(Ofset=",".join(list(Result["Result"])), is_raw_input=False) else: diff --git a/myUrllib/MySocketUtils.py b/myUrllib/MySocketUtils.py index a43d0de9351c6da3fbb2ad9be1a45344b5fc95d3..b61b69e9249598a31942e72ab49b7c5f17c63bf5 100644 --- a/myUrllib/MySocketUtils.py +++ b/myUrllib/MySocketUtils.py @@ -22,7 +22,7 @@ import re # "Content-Length: 9\r\n"\ # "Cookie: _passport_session=a459aba69761497eb31de76c27795e999613; _passport_ct=9116b2cb0bf443e1a01d22ac8c1ae449t5007; route=9036359bb8a8a461c164a04f8f50b252; BIGipServerpool_passport=200081930.50215.0000; BIGipServerotn=484704778.64545.0000\r\n\n"\ # "appid=otn\r\n" -# # s.sendall(get_str.format("https://kyfw.12306.cn/otn/login/init")) +# # s.sendall(get_str.format("https://kyfw.12306.cn/otn/resources/login.html")) # s.sendall(post_str.format("https://kyfw.12306.cn/passport/web/auth/uamtk")) from config.urlConf import urls diff --git a/myUrllib/httpUtils.py b/myUrllib/httpUtils.py index 2a2c40317b043318daf7ea66681913f1f5de96e8..265f1c7dfc069fc48b7eae9841ea4ed52529bf09 100755 --- a/myUrllib/httpUtils.py +++ b/myUrllib/httpUtils.py @@ -16,6 +16,8 @@ def _set_header_default(): header_dict[ "User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) 12306-electron/1.0.1 Chrome/59.0.3071.115 Electron/1.8.4 Safari/537.36" header_dict["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8" + header_dict["Origin"] = "https://kyfw.12306.cn" + header_dict["Connection"] = "keep-alive" return header_dict