Egの登录oschina:
import requests
from fake_useragent import UserAgent as ua
from hashlib import sha1
s=requests.Session()
s.verify=False #忽略ssl证书
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
#import ssl #ssl证书处理法2之添加信任?
#from requests_toolbelt import SSLAdapter
#s.mount('https://', SSLAdapter(ssl.PROTOCOL_TLSv1))
def loginOschina(userName,pwd):
headers={'User-Agent':ua().random}
indexUrl='https://www.oschina.net/'
data={'email':userName,'pwd':sha1(pwd.encode()).hexdigest()}
s.post(indexUrl+'action/user/hash_login?from=',data,headers=headers)
response=s.get(indexUrl,headers=headers).text
if '个人资料修改' in response and '退出' in response:
print('登录成功')
if __name__ == '__main__':
userName='904477955@qq.com'
pwd='***'
loginOschina(userName,pwd)
****************************************分割线****************************************
Egの登录知乎:
自动识别倒立汉字验证码:https://github.com/muchrooms/zheye
import requests,time
from fake_useragent import UserAgent
from io import BytesIO
from PIL import Image
s = requests.session()
def loginZhihu(phone,pwd):
s.headers={'User-Agent':UserAgent().random} #下文不必每次请求都写1次headers参数了
xsrf=s.get('https://www.zhihu.com/').cookies['_xsrf']
r=int(time.time()*1000)
captchaUrl=f'https://www.zhihu.com/captcha.gif?r={r}&type=login&lang=cn'
captcha=s.get(captchaUrl).content
Image.open(BytesIO(captcha)).show() #BytesIO把二进制内容,转为内存中的文件对象
# 知乎最新的汉字验证码,第1个字的坐标是[23,23],第2个是[46,23],第2个是[69,23]……
captcha=tuple(int(x)*23 for x in input('输入各倒字的序号如1-3,自1始,以-分隔:').split('-'))
if len(captcha)==2: #目前的验证码,大部分时候是两个倒立汉字,偶尔是一个
captcha='{"img_size":[200,44],"input_points":[[%s,23],[%s,23]]}' % captcha
elif len(captcha)==1: #知乎的captcha参数的值,是str,而非{}类型
captcha='{"img_size":[200,44],"input_points":[[%s,23]]}' % captcha
# print(captcha)
data={'_xsrf':xsrf,'phone_num':phone,'password':pwd,'captcha':captcha,'captcha_type':'cn'}
response=s.post('https://www.zhihu.com/login/phone_num',data=data).text
print(response) #r为0表示登录成功,r为1或无r则失败
loginZhihu('1388908**41','登录密码')
****************************************分割线****************************************
Egの登录12306:
import requests,json
from fake_useragent import UserAgent
from io import BytesIO
from PIL import Image
codeImageUrl='https://kyfw.12306.cn/passport/captcha/captcha-image'
codeCheckUrl='https://kyfw.12306.cn/passport/captcha/captcha-check'
loginUrl='https://kyfw.12306.cn/passport/web/login'
def captchaRecognition():
# 把验证码图下到内存,左上角为原点,用截图软件手动获取各匹配图片的横、纵坐标
captcha=s.get(codeImageUrl).content
Image.open(BytesIO(captcha)).show()
axises=input("各匹配图片的横&纵坐标,均以半角逗号分隔:")
codeData={'answer':axises,'login_site':'E','rand':'sjrand'}
codeCheckResult=s.post(codeCheckUrl,codeData).text
if json.loads(codeCheckResult)['result_code'] == '4': # 此处的4是str,下文的0是int
print('验证码通过')
else:
print('验证码错误')
exit()
def login():
user=input('please input your login ID>>>')
pwd=input('please input your login Password>>>')
loginData={'username':user,'password':pwd,'appid':'otn'}
loginResult=s.post(loginUrl,loginData).text
if json.loads(loginResult)['result_code'] == 0:
print('登录成功')
else:
print('登录失败')
if __name__ == '__main__':
s=requests.session()
h={'User-Agent':UserAgent().random,'Referer':'https://kyfw.12306.cn/otn/login/init'}
s.headers=h
# 用verify=False移除SSL认证时,禁用因其产生的安全请求警告
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
s.verify=False # 移除SSL证书验证
captchaRecognition()
login()
****************************************分割线****************************************
Egの12306余票及票价的查询:
E:\py\RestTickets_Prices.py:
'''控制台查余票
Usage:
tickets [-gdtkz] <from> <to> <date>
Options:
-h,--help 显示帮助菜单
-g 高铁
-d 动车
-t 特快
-k 快速
-z 直达
Example:
tickets 深圳 北京 2018-02-09
'''
from docopt import docopt
from colorama import Fore,init
from prettytable import PrettyTable
from fake_useragent import UserAgent
import os,re,json,requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
init(convert=True)
def run():
if not os.path.isfile('E:/各地车站代码.txt'):
codeOfAllStations()
with open('E:/各地车站代码.txt',encoding='utf8') as f:
stations=json.loads(f.read())
rtp=RestTicketsAndPrices(stations)
rtp.restTickets()
def codeOfAllStations(): #获取各地车站的大写英文代码
stationsUrl='https://kyfw.12306.cn/otn/resources/js/framework/station_name.js'
html=requests.get(stationsUrl).text
pattern=re.compile('@.+?\|(.+?)\|(.+?)\|')
stations=dict(pattern.findall(html))
stations.update(dict(zip(stations.values(),stations.keys())))
with open('E:/各地车站代码.txt','w',encoding='utf8') as f:
f.write(json.dumps(stations,ensure_ascii=False,indent='').replace(": ",":"))
class RestTicketsAndPrices:
def __init__(self,stations):
self.stations=stations
def restTickets(self):
arguments=docopt(__doc__)
date = arguments['<date>']
fr=self.stations.get(arguments['<from>'])
to=self.stations.get(arguments['<to>'])
url=f'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={date}&\
leftTicketDTO.from_station={fr}&leftTicketDTO.to_station={to}&purpose_codes=ADULT'
r=requests.get(url,verify=False)
if 'w3.org' in r.text:
print('车站或日期有误,或网络堵塞,重试下。。。')
return
rows=r.json()['data']['result']
self.mySqlTableStyle(rows)
def mySqlTableStyle(self,rows):
pt=PrettyTable('车次,始发,终点,出站,到站,出时,到时,历时,硬卧,硬座,无座,二等,一等'.split(','))
pattern=re.compile('\|+')
fails=0 #没能返回票价的车次数量
for row in rows:
line=pattern.split(row)
prices=self.priceOfTrainSeats(line)
fails+=prices.get('fail',0)
line[4:8]=[self.stations.get(x) for x in line[4:8]]
if line[-2]=='1413': #普铁:硬卧,硬座,无座,--,--;没取软卧和软座
pt.add_row(line[3:11]+[line[22],line[23],line[21],'--','--'])
pt.add_row([' ']*8+[prices['A3'],prices['A1'],prices['WZ'],' ',' '])
elif set(line[-2])==set('OM9'): #高铁:--,--,--,二等,一等;没取特等
pt.add_row(line[3:11]+['--']*3+line[21:23])
pt.add_row([' ']*11+[prices['O'],prices['M']])
else: #动车/城际:--,--,无座,二等,一等;--,--,--,二等,动卧
if set(line[-2])==set('OOM') or (set(line[-2])==set('OF') and len(line[-2])==3):
pt.add_row(line[3:11]+['--']*2+line[20:23])
elif set(line[-2])==set('OF'):
pt.add_row(line[3:11]+['--']*3+line[20:22])
pt.add_row([' ']*10+[prices.get('WZ',' '),prices['O'],prices.get('M',prices['F'])])
for row in pt._rows:
for column in [5,7,9]:
row[column]=Fore.RED+str(row[column])+Fore.RESET
print(pt)
if fails:print(f'网络卡顿,未显示的{fails}个车次的票价请稍后重试')
def priceOfTrainSeats(self,n):
n[13]=f'{n[13][:4]}-{n[13][4:6]}-{n[13][6:]}'
priceUrl=f'https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice?train_no={n[2]}&\
from_station_no={n[16]}&to_station_no={n[17]}&seat_types={n[-2]}&train_date={n[13]}'
h={'User-Agent':UserAgent().random}
try:prices=requests.get(priceUrl,headers=h).json()['data']
#下行代码顺次表示:硬座、软座、硬卧、软卧、特等、无座、二等、一等、动卧
except:prices=dict(zip(['A1','A2','A3','A4','A9','WZ','O','M','F'],[' ']*9),fail=1)
finally:return prices
if __name__ == '__main__':
run()
*********************分割线*********************
E:\py\setup.py:
# 程序运行の法1:Python命令 程序脚本名 各参数
# cmd='python "E:/py/RestTickets_Prices.py" 深圳 北京 2018-02-05'
# import os
# os.system(cmd)
# 程序运行の法2:自定义个可执行命令如tickets 各参数
# 本py放在项目根下,并在此处执行命令:python "本安装脚本的路径名" install
from setuptools import setup,find_packages
setup(
name='TrainTickets', #包名,若上传到pypi,可通过该名来pip install
version='1.0', #只能是数值
keywords=('12306','余票','票价'),
description='cmd中的运行示例:tickets 深圳 北京 2018-02-09',
long_description='出行日出发站至目的站,各车次的各种座位的余票数及票价',
url='',
author='程勇',
author_email='904477955@qq.com',
license='MIT',
platforms='any',
py_modules=['RestTickets_Prices',], #packages=find_packages():ModuleNotFound
include_package_data=False,
install_requires=['docopt','colorama','prettytable','requests','fake_useragent'],
entry_points={'console_scripts':['tickets=RestTickets_Prices:run',]},
) #['exe名1=项目.子包1.模块名1:入口函数1','exe名2=项目.模块名2:入口函数2',]