Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
py12306
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
python
py12306
Commits
27a5a13c
Commit
27a5a13c
authored
Jan 07, 2019
by
Jalin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完成自动下单
parent
0e287096
Changes
11
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
472 additions
and
37 deletions
+472
-37
config.py
py12306/config.py
+12
-1
api.py
py12306/helpers/api.py
+6
-0
func.py
py12306/helpers/func.py
+3
-1
order_log.py
py12306/log/order_log.py
+42
-0
query_log.py
py12306/log/query_log.py
+1
-1
user_log.py
py12306/log/user_log.py
+2
-0
order.py
py12306/order/order.py
+316
-21
job.py
py12306/query/job.py
+38
-8
query.py
py12306/query/query.py
+1
-1
job.py
py12306/user/job.py
+34
-0
user.py
py12306/user/user.py
+17
-4
No files found.
py12306/config.py
View file @
27a5a13c
...
...
@@ -24,16 +24,27 @@ AUTO_CODE_ACCOUNT = {
}
SEAT_TYPES
=
{
'特等座'
:
25
,
'商务座'
:
32
,
'一等座'
:
31
,
'二等座'
:
30
,
'特等座'
:
25
,
'软卧'
:
23
,
'硬卧'
:
28
,
'硬座'
:
29
,
'无座'
:
26
,
}
ORDER_SEAT_TYPES
=
{
'特等座'
:
'P'
,
'商务座'
:
9
,
'一等座'
:
'M'
,
'二等座'
:
'O'
,
'软卧'
:
4
,
'硬卧'
:
3
,
'硬座'
:
1
,
'无座'
:
1
,
}
PROJECT_DIR
=
path
.
dirname
(
path
.
dirname
(
path
.
abspath
(
__file__
)))
+
'/'
# Query
...
...
py12306/helpers/api.py
View file @
27a5a13c
...
...
@@ -43,6 +43,12 @@ API_USER_INFO = {
'url'
:
BASE_URL_OF_12306
+
'/otn/modifyUser/initQueryUserInfoApi'
}
API_USER_PASSENGERS
=
BASE_URL_OF_12306
+
'/otn/confirmPassenger/getPassengerDTOs'
API_SUBMIT_ORDER_REQUEST
=
BASE_URL_OF_12306
+
'/otn/leftTicket/submitOrderRequest'
API_CHECK_ORDER_INFO
=
BASE_URL_OF_12306
+
'/otn/confirmPassenger/checkOrderInfo'
API_INITDC_URL
=
BASE_URL_OF_12306
+
'/otn/confirmPassenger/initDc'
# 生成订单时需要先请求这个页面
API_GET_QUEUE_COUNT
=
BASE_URL_OF_12306
+
'/otn/confirmPassenger/getQueueCount'
API_CONFIRM_SINGLE_FOR_QUEUE
=
BASE_URL_OF_12306
+
'/otn/confirmPassenger/confirmSingleForQueue'
API_QUERY_ORDER_WAIT_TIME
=
BASE_URL_OF_12306
+
'/otn/confirmPassenger/queryOrderWaitTime?{}'
# 排队查询
urls
=
{
"auth"
:
{
# 登录接口
...
...
py12306/helpers/func.py
View file @
27a5a13c
...
...
@@ -59,8 +59,10 @@ def get_interval_num(interval, decimal=2):
return
round
(
random
.
uniform
(
interval
.
get
(
'min'
),
interval
.
get
(
'max'
)),
decimal
)
def
stay_second
(
second
):
def
stay_second
(
second
,
call_back
=
None
):
sleep
(
second
)
if
call_back
:
return
call_back
()
def
is_main_thread
():
...
...
py12306/log/order_log.py
0 → 100644
View file @
27a5a13c
from
py12306.log.base
import
BaseLog
from
py12306.helpers.func
import
*
@
singleton
class
OrderLog
(
BaseLog
):
MESSAGE_REQUEST_INIT_DC_PAGE_FAIL
=
'请求初始化订单页面失败'
MESSAGE_SUBMIT_ORDER_REQUEST_FAIL
=
'提交订单失败,错误原因 {}'
MESSAGE_SUBMIT_ORDER_REQUEST_SUCCESS
=
'提交订单成功'
MESSAGE_CHECK_ORDER_INFO_FAIL
=
'检查订单失败,错误原因 {}'
MESSAGE_CHECK_ORDER_INFO_SUCCESS
=
'检查订单成功'
MESSAGE_GET_QUEUE_COUNT_SUCCESS
=
'排队成功,你当前排在第 {} 位, 余票还剩余 {} 张'
MESSAGE_GET_QUEUE_COUNT_FAIL
=
'排队失败,错误原因 {}'
MESSAGE_CONFIRM_SINGLE_FOR_QUEUE_SUCCESS
=
'# 提交订单成功!#'
MESSAGE_CONFIRM_SINGLE_FOR_QUEUE_ERROR
=
'提交订单出错,错误原因 {}'
MESSAGE_CONFIRM_SINGLE_FOR_QUEUE_FAIL
=
'提交订单失败,错误原因 {}'
MESSAGE_QUERY_ORDER_WAIT_TIME_WAITING
=
'排队等待中,预计还需要 {} 秒'
MESSAGE_QUERY_ORDER_WAIT_TIME_FAIL
=
'排队失败,错误原因 {}'
MESSAGE_QUERY_ORDER_WAIT_TIME_INFO
=
'第 {} 次排队,请耐心等待'
MESSAGE_ORDER_SUCCESS_NOTIFICATION_TITLE
=
'车票购买成功!'
MESSAGE_ORDER_SUCCESS_NOTIFICATION_CONTENT
=
'请及时器登录12306,打开
\'
未完成订单
\'
,在30分钟内完成支付!'
@
classmethod
def
print_passenger_did_deleted
(
cls
,
passengers
):
self
=
cls
()
result
=
[
passenger
.
get
(
'name'
)
+
'('
+
passenger
.
get
(
'type_text'
)
+
')'
for
passenger
in
passengers
]
self
.
add_quick_log
(
'# 删减后的乘客列表 {} #'
.
format
(
', '
.
join
(
result
)))
self
.
flush
()
return
self
@
classmethod
def
print_ticket_did_ordered
(
cls
,
order_id
):
self
=
cls
()
self
.
add_quick_log
(
'# 车票购买成功,订单号{} #'
.
format
(
order_id
))
self
.
flush
()
return
self
py12306/log/query_log.py
View file @
27a5a13c
...
...
@@ -63,7 +63,7 @@ class QueryLog(BaseLog):
self
.
add_quick_log
(
'余票数小于乘车人数,当前余票数: {rest_num}, 实际人数 {actual_num}, 删减人车人数到: {take_num}'
.
format
(
rest_num
=
rest_num
,
actual_num
=
job
.
member_num
,
take
=
job
.
member_num_take
))
take
_num
=
job
.
member_num_take
))
self
.
flush
()
return
self
...
...
py12306/log/user_log.py
View file @
27a5a13c
...
...
@@ -17,6 +17,8 @@ class UserLog(BaseLog):
MESSAGE_GET_USER_PASSENGERS_FAIL
=
'获取用户乘客列表失败,错误原因: {} {} 秒后重试'
MESSAGE_USER_PASSENGERS_IS_INVALID
=
'乘客信息校验失败,在账号 {} 中未找到该乘客: {}'
MESSAGE_WAIT_USER_INIT_COMPLETE
=
'未找到可用账号或用户正在初始化,{} 秒重试'
def
__init__
(
self
):
super
()
.
__init__
()
self
.
init_data
()
...
...
py12306/order/order.py
View file @
27a5a13c
This diff is collapsed.
Click to expand it.
py12306/query/job.py
View file @
27a5a13c
...
...
@@ -3,6 +3,7 @@ from py12306.helpers.station import Station
from
py12306.log.query_log
import
QueryLog
from
py12306.helpers.func
import
*
from
py12306.log.user_log
import
UserLog
from
py12306.order.order
import
Order
from
py12306.user.user
import
User
...
...
@@ -12,6 +13,7 @@ class Job:
"""
left_dates
=
[]
left_date
=
None
left_station
=
''
arrive_station
=
''
left_station_code
=
''
...
...
@@ -19,6 +21,8 @@ class Job:
account_key
=
0
allow_seats
=
[]
current_seat
=
None
current_order_seat
=
None
allow_train_numbers
=
[]
members
=
[]
member_num
=
0
...
...
@@ -32,10 +36,12 @@ class Job:
ticket_info
=
{}
INDEX_TICKET_NUM
=
11
INDEX_TRAIN_NUMBER
=
3
INDEX_TRAIN_NO
=
2
INDEX_LEFT_DATE
=
13
INDEX_LEFT_STATION
=
6
# 4 5 始发 终点
INDEX_ARRIVE_STATION
=
7
INDEX_ORDER_TEXT
=
1
# 下单文字
INDEX_SECRET_STR
=
0
def
__init__
(
self
,
info
,
query
):
self
.
left_dates
=
info
.
get
(
'left_dates'
)
...
...
@@ -67,22 +73,20 @@ class Job:
:param job:
:return:
"""
if
not
self
.
passengers
:
User
.
check_members
(
self
.
members
,
self
.
account_key
,
call_back
=
self
.
set_passengers
)
QueryLog
.
print_job_start
()
for
date
in
self
.
left_dates
:
self
.
left_date
=
date
response
=
self
.
query_by_date
(
date
)
self
.
handle_response
(
response
)
self
.
safe_stay
()
if
is_main_thread
():
QueryLog
.
flush
(
sep
=
'
\t
\t
'
)
QueryLog
.
flush
(
sep
=
'
\t
'
)
else
:
QueryLog
.
add_log
(
'
\n
'
)
if
is_main_thread
():
QueryLog
.
add_quick_log
(
''
)
.
flush
()
else
:
QueryLog
.
flush
(
sep
=
'
\t
\t
'
)
QueryLog
.
flush
(
sep
=
'
\t
'
)
def
query_by_date
(
self
,
date
):
"""
...
...
@@ -116,12 +120,14 @@ class Job:
self
.
get_info_of_ticket_num
()))
if
not
self
.
is_has_ticket
(
ticket_info
):
continue
allow_seats
=
self
.
allow_seats
if
self
.
allow_seats
else
list
(
config
.
SEAT_TYPES
.
values
())
# 未设置 则所有可用
allow_seats
=
self
.
allow_seats
if
self
.
allow_seats
else
list
(
config
.
SEAT_TYPES
.
values
())
# 未设置 则所有可用 TODO 合法检测
self
.
handle_seats
(
allow_seats
,
ticket_info
)
def
handle_seats
(
self
,
allow_seats
,
ticket_info
):
for
seat
in
allow_seats
:
# 检查座位是否有票
ticket_of_seat
=
ticket_info
[
get_seat_number_by_name
(
seat
)]
self
.
set_seat
(
seat
)
ticket_of_seat
=
ticket_info
[
self
.
current_seat
]
if
not
self
.
is_has_ticket_by_seat
(
ticket_of_seat
):
# 座位是否有效
continue
QueryLog
.
print_ticket_seat_available
(
left_date
=
self
.
get_info_of_left_date
(),
...
...
@@ -139,7 +145,9 @@ class Job:
QueryLog
.
print_ticket_available
(
left_date
=
self
.
get_info_of_left_date
(),
train_number
=
self
.
get_info_of_train_number
(),
rest_num
=
ticket_of_seat
)
print
(
'检查完成 开始提交订单'
)
self
.
check_passengers
()
order
=
Order
(
user
=
self
.
get_user
(),
query
=
self
)
order
.
order
()
def
get_results
(
self
,
response
):
"""
...
...
@@ -179,6 +187,22 @@ class Job:
UserLog
.
print_user_passenger_init_success
(
passengers
)
self
.
passengers
=
passengers
def
set_seat
(
self
,
seat
):
self
.
current_seat
=
get_seat_number_by_name
(
seat
)
self
.
current_order_seat
=
config
.
ORDER_SEAT_TYPES
[
seat
]
def
get_user
(
self
):
user
=
User
.
get_user
(
self
.
account_key
)
if
not
user
.
check_is_ready
():
# TODO user is not ready
pass
return
user
def
check_passengers
(
self
):
if
not
self
.
passengers
:
User
.
check_members
(
self
.
members
,
self
.
account_key
,
call_back
=
self
.
set_passengers
)
return
True
# 提供一些便利方法
def
get_info_of_left_date
(
self
):
return
self
.
ticket_info
[
self
.
INDEX_LEFT_DATE
]
...
...
@@ -189,6 +213,9 @@ class Job:
def
get_info_of_train_number
(
self
):
return
self
.
ticket_info
[
self
.
INDEX_TRAIN_NUMBER
]
def
get_info_of_train_no
(
self
):
return
self
.
ticket_info
[
self
.
INDEX_TRAIN_NO
]
def
get_info_of_left_station
(
self
):
return
Station
.
get_station_name_by_key
(
self
.
ticket_info
[
self
.
INDEX_LEFT_STATION
])
...
...
@@ -197,3 +224,6 @@ class Job:
def
get_info_of_order_text
(
self
):
return
self
.
ticket_info
[
self
.
INDEX_ORDER_TEXT
]
def
get_info_of_secret_str
(
self
):
return
self
.
ticket_info
[
self
.
INDEX_SECRET_STR
]
py12306/query/query.py
View file @
27a5a13c
...
...
@@ -31,7 +31,7 @@ class Query:
pass
def
start
(
self
):
return
# DEBUG
#
return # DEBUG
self
.
init_jobs
()
QueryLog
.
print_init_jobs
(
jobs
=
self
.
jobs
)
while
True
:
...
...
py12306/user/job.py
View file @
27a5a13c
import
json
import
pickle
import
re
from
os
import
path
from
py12306.config
import
*
...
...
@@ -7,6 +9,7 @@ from py12306.helpers.app import *
from
py12306.helpers.auth_code
import
AuthCode
from
py12306.helpers.func
import
*
from
py12306.helpers.request
import
Request
from
py12306.log.order_log
import
OrderLog
from
py12306.log.user_log
import
UserLog
...
...
@@ -23,6 +26,11 @@ class UserJob:
passengers
=
[]
retry_time
=
5
# Init page
global_repeat_submit_token
=
None
ticket_info_for_passenger_form
=
None
order_request_dto
=
None
def
__init__
(
self
,
info
,
user
):
self
.
session
=
Request
()
self
.
heartbeat
=
user
.
heartbeat
...
...
@@ -229,9 +237,35 @@ class UserJob:
new_member
=
{
'name'
:
passenger
.
get
(
'passenger_name'
),
'id_card'
:
passenger
.
get
(
'passenger_id_no'
),
'id_card_type'
:
passenger
.
get
(
'passenger_id_type_code'
),
'mobile'
:
passenger
.
get
(
'mobile_no'
),
'type'
:
passenger
.
get
(
'passenger_type'
),
'type_text'
:
dict_find_key_by_value
(
UserType
.
dicts
,
int
(
passenger
.
get
(
'passenger_type'
)))
}
results
.
append
(
new_member
)
return
results
def
request_init_dc_page
(
self
):
"""
请求下单页面 拿到 token
:return:
"""
data
=
{
'_json_att'
:
''
}
response
=
self
.
session
.
post
(
API_INITDC_URL
,
data
)
html
=
response
.
text
token
=
re
.
search
(
r'var globalRepeatSubmitToken = \'(.+?)\''
,
html
)
form
=
re
.
search
(
r'var ticketInfoForPassengerForm *= *(\{.+\})'
,
html
)
order
=
re
.
search
(
r'var orderRequestDTO *= *(\{.+\})'
,
html
)
# 系统忙,请稍后重试
if
html
.
find
(
'系统忙,请稍后重试'
)
!=
-
1
:
OrderLog
.
add_quick_log
(
OrderLog
.
MESSAGE_REQUEST_INIT_DC_PAGE_FAIL
)
.
flush
()
# 重试无用,直接跳过
return
False
try
:
self
.
global_repeat_submit_token
=
token
.
groups
()[
0
]
self
.
ticket_info_for_passenger_form
=
json
.
loads
(
form
.
groups
()[
0
]
.
replace
(
"'"
,
'"'
))
self
.
order_request_dto
=
json
.
loads
(
order
.
groups
()[
0
]
.
replace
(
"'"
,
'"'
))
except
:
pass
# TODO Error
return
True
py12306/user/user.py
View file @
27a5a13c
...
...
@@ -9,6 +9,8 @@ class User:
heartbeat
=
60
*
2
users
=
[]
retry_time
=
3
def
__init__
(
self
):
self
.
interval
=
config
.
USER_HEARTBEAT_INTERVAL
...
...
@@ -32,7 +34,15 @@ class User:
self
.
users
.
append
(
user
)
@
classmethod
def
check_members
(
cls
,
members
,
user_key
,
call_back
):
def
get_user
(
cls
,
key
):
self
=
cls
()
for
user
in
self
.
users
:
if
user
.
key
==
key
:
return
user
return
None
@
classmethod
def
check_members
(
cls
,
members
,
key
,
call_back
):
"""
检测乘客信息
:param passengers:
...
...
@@ -42,7 +52,10 @@ class User:
for
user
in
self
.
users
:
assert
isinstance
(
user
,
UserJob
)
if
user
.
key
==
user_
key
and
user
.
check_is_ready
():
if
user
.
key
==
key
and
user
.
check_is_ready
():
passengers
=
user
.
get_passengers_by_members
(
members
)
call_back
(
passengers
)
pass
return
call_back
(
passengers
)
UserLog
.
add_quick_log
(
UserLog
.
MESSAGE_WAIT_USER_INIT_COMPLETE
.
format
(
self
.
retry_time
))
.
flush
()
stay_second
(
self
.
retry_time
)
return
self
.
check_members
(
members
,
key
,
call_back
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment