- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章教你用python实现12306余票查询由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
我们说先在浏览器中打开开发者工具(f12),尝试一次余票的查询,通过开发者工具查看发出请求的包 。
余票查询界面 。
可以看到红框框中的url就是我们向12306服务器发出的请求,那么具体是什么呢?我们来看看 。
[ https://kyfw.12306.cn/otn/leftticket/queryz?leftticketdto.train_date=2019-01-21&leftticketdto.from_station=cdw&leftticketdto.to_station=szq&purpose_codes=adult](https://kyfw.12306.cn/otn/leftticket/queryz?leftticketdto.train_date=2019-01-21&leftticketdto.from_station=cdw&leftticketdto.to_station=szq&purpose_codes=adult) 。
可以看到发出请求的几个字段:
leftticketdto.train_date:查询的日期 leftticketdto.from_station:查询的出发地 leftticketdto.to_station:查询的目的地 purpose_codes:不太清楚这个字段是用来做什么的,就默认吧 。
可以从我们递交的url请求看出,我们输入的成都,深圳都变成了对应的编号,比如,成都(cdw)、深圳(szq),所以当我们程序进行输入的时候要进行一下处理,12306的一个地方存储着这些城市名与编码对应的文档:
[ https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971](https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971) 。
站点编码对应 。
下面我们就编写一个小程序,将这些城市名与编号提取出来:
1
2
3
4
5
6
7
8
9
10
|
import
re,requests
url
=
"https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971"
response
=
requests.get(url,verify
=
false)
#将车站的名字和编码进行提取
chezhan
=
re.findall(r
'([\u4e00-\u9fa5]+)\|([a-z]+)'
, response.text)
chezhan_code
=
dict
(chezhan)
#进行交换
chezhan_names
=
dict
(
zip
(chezhan_code.values(),chezhan_code.keys()))
#打印出得到的车站字典
print
(chezhan_names)
|
得到的打印结果如下(只截取部分显示):
{‘vap': ‘北京北', ‘bop': ‘北京东', ‘bjp': ‘北京', ‘vnp': ‘北京南', ‘bxp': ‘北京西', ‘izq': ‘广州南', ‘cuw': ‘重庆北', ‘cqw': ‘重庆', ‘crw': ‘重庆南', ‘cxw': ‘重庆西', ‘ggq': ‘广州东', ‘shh': ‘上海', ‘snh': ‘上海南', ‘aoh': ‘上海虹桥', ‘sxh': ‘上海西', ‘tbp': ‘天津北', ‘tjp': ‘天津', ‘tip': ‘天津南', ‘txp': ‘天津西', ‘xja': ‘香港西九龙', ‘cct': ‘长春', ‘cet': ‘长春南', ‘crt': ‘长春西', ‘icw': ‘成都东', ‘cnw': ‘成都南', ‘cdw': ‘成都', ‘csq': ‘长沙', ‘cwq': ‘长沙南',} 。
接下来我们就动手开始程序的主要代码编写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def
main():
date
=
input
(
"请输入时间(如2019-01-22):\n"
)
from_station
=
chezhan_code[
input
(
"请输入起始站点:\n"
)]
to_station
=
chezhan_code[
input
(
"请输入目的站点:\n"
)]
url
=
"https://kyfw.12306.cn/otn/leftticket/queryz?"
headers
=
{
"user-agent"
:
"mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.26 safari/537.36 core/1.63.5702.400 qqbrowser/10.2.1893.400"
}
url
=
url
+
"leftticketdto.train_date="
+
date
+
"&leftticketdto.from_station="
+
from_station
+
"&leftticketdto.to_station="
+
to_station
+
"&purpose_codes=adult"
#print(url) 已经检查过生成的url是正确的
#request请求获取主页
r
=
requests.get(url,headers
=
headers)
r.raise_for_status()
#如果发送了一个错误的请求,会抛出异常
r.encoding
=
r.apparent_encoding
showticket(r.text)
|
用户输入时间、起始站点、目的站点,然后通过get来请求,然后我们对返回的网页信息进行解析。我们现将上面代码的r.text进行打印,看看我们请求之后,返回了什么样的信息,然后决定我们应该如何解析 。
运行结果 。
这样看着不方便,我们粘贴到记事本中,进行详细的分析:
请求返回的结果信息 。
可以与12306显示的信息进行对比,k829是车次,cdw与bjq是出发地和目的地,10:10是出发时间,06:13是到达时间,44:21是历时时间,20190123为查询的日期,剩下的就是一系列票的各种信息.
下面就是对这些返回的信息进行解析,其实这也是python爬虫的关键,就是解析!!! 。
我们先把信息转化为json格式,可以看到都是用“|”隔开的,那么我们就用split函数分割出来,下面是主要功能代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
def
showticket(html):
html
=
json.loads(html)
table
=
prettytable([
" 车次 "
,
"出发车站"
,
"到达车站"
,
"出发时间"
,
"到达时间"
,
" 历时 "
,
"商务座"
,
" 一等座"
,
"二等座"
,
"高级软卧"
,
"软卧"
,
"动卧"
,
"硬卧"
,
"软座"
,
"硬座"
,
"无座"
,
"其他"
,
"备注"
])
for
i
in
html[
'data'
][
'result'
]:
name
=
[
"station_train_code"
,
"from_station_name"
,
"to_station_name"
,
"start_time"
,
"arrive_time"
,
"lishi"
,
"swz_num"
,
"zy_num"
,
"ze_num"
,
"dw_num"
,
"gr_num"
,
"rw_num"
,
"yw_num"
,
"rz_num"
,
"yz_num"
,
"wz_num"
,
"qt_num"
,
"note_num"
]
data
=
{
"station_train_code"
: '',
"from_station_name"
: '',
"to_station_name"
: '',
"start_time"
: '',
"arrive_time"
: '',
"lishi"
: '',
"swz_num"
: '',
"zy_num"
: '',
"ze_num"
: '',
"dw_num"
: '',
"gr_num"
: '',
"rw_num"
: '',
"yw_num"
: '',
"rz_num"
: '',
"yz_num"
: '',
"wz_num"
: '',
"qt_num"
: '',
"note_num"
: ''
}
#将各项信息提取并赋值
item
=
i.split(
'|'
)
#使用“|”进行分割
data[
"station_train_code"
]
=
item[
3
]
#获取车次信息,在3号位置
data[
"from_station_name"
]
=
item[
6
]
#始发站信息在6号位置
data[
"to_station_name"
]
=
item[
7
]
#终点站信息在7号位置
data[
"start_time"
]
=
item[
8
]
#出发时间在8号位置
data[
"arrive_time"
]
=
item[
9
]
#抵达时间在9号位置
data[
"lishi"
]
=
item[
10
]
#经历时间在10号位置
data[
"swz_num"
]
=
item[
32
]
or
item[
25
]
#特别注意,商务座在32或25位置
data[
"zy_num"
]
=
item[
31
]
#一等座信息在31号位置
data[
"ze_num"
]
=
item[
30
]
#二等座信息在30号位置
data[
"gr_num"
]
=
item[
21
]
#高级软卧信息在21号位置
data[
"rw_num"
]
=
item[
23
]
#软卧信息在23号位置
data[
"dw_num"
]
=
item[
27
]
#动卧信息在27号位置
data[
"yw_num"
]
=
item[
28
]
#硬卧信息在28号位置
data[
"rz_num"
]
=
item[
24
]
#软座信息在24号位置
data[
"yz_num"
]
=
item[
29
]
#硬座信息在29号位置
data[
"wz_num"
]
=
item[
26
]
#无座信息在26号位置
data[
"qt_num"
]
=
item[
22
]
#其他信息在22号位置
data[
"note_num"
]
=
item[
1
]
#备注信息在1号位置
color
=
colored()
data[
"note_num"
]
=
color.white(item[
1
])
#如果没有信息,那么就用“-”代替
for
pos
in
name:
if
data[pos]
=
=
"":
data[pos]
=
"-"
tickets
=
[]
cont
=
[]
cont.append(data)
for
x
in
cont:
tmp
=
[]
for
y
in
name:
if
y
=
=
"from_station_name"
:
s
=
color.green(chezhan_names[data[
"from_station_name"
]])
tmp.append(s)
elif
y
=
=
"to_station_name"
:
s
=
color.red(chezhan_names[data[
"to_station_name"
]])
tmp.append(s)
elif
y
=
=
"start_time"
:
s
=
color.green(data[
"start_time"
])
tmp.append(s)
elif
y
=
=
"arrive_time"
:
s
=
color.red(data[
"arrive_time"
])
tmp.append(s)
elif
y
=
=
"station_train_code"
:
s
=
color.yellow(data[
"station_train_code"
])
tmp.append(s)
else
:
tmp.append(data[y])
tickets.append(tmp)
for
ticket
in
tickets:
table.add_row(ticket)
print
(table)
|
那么我们程序就成功啦!!! 。
运行结果 。
但是在编译器里面prettytable的格子没有对齐,不要担心,我们到终端运行一下脚本,就可以看到很好看的输出啦:
终端运行结果 。
完成!!!下面是完整代码 。
main.py 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# -*- coding: utf-8 -*-
import
re,requests,datetime,time,json
from
prettytable
import
prettytable
from
colorama
import
init,fore
from
stationinfo
import
chezhan_code,chezhan_names
init(autoreset
=
false)
class
colored(
object
):
def
yeah(
self
,s):
return
fore.lightcyan_ex
+
s
+
fore.reset
def
green(
self
,s):
return
fore.lightgreen_ex
+
s
+
fore.reset
def
yellow(
self
,s):
return
fore.lightyellow_ex
+
s
+
fore.reset
def
white(
self
,s):
return
fore.lightwhite_ex
+
s
+
fore.reset
def
blue(
self
,s):
return
fore.lightblue_ex
+
s
+
fore.reset
def
showticket(html):
html
=
json.loads(html)
table
=
prettytable([
" 车次 "
,
"出发车站"
,
"到达车站"
,
"出发时间"
,
"到达时间"
,
" 历时 "
,
"商务座"
,
" 一等座"
,
"二等座"
,
"高级软卧"
,
"软卧"
,
"动卧"
,
"硬卧"
,
"软座"
,
"硬座"
,
"无座"
,
"其他"
,
"备注"
])
for
i
in
html[
'data'
][
'result'
]:
name
=
[
"station_train_code"
,
"from_station_name"
,
"to_station_name"
,
"start_time"
,
"arrive_time"
,
"lishi"
,
"swz_num"
,
"zy_num"
,
"ze_num"
,
"dw_num"
,
"gr_num"
,
"rw_num"
,
"yw_num"
,
"rz_num"
,
"yz_num"
,
"wz_num"
,
"qt_num"
,
"note_num"
]
data
=
{
"station_train_code"
: '',
"from_station_name"
: '',
"to_station_name"
: '',
"start_time"
: '',
"arrive_time"
: '',
"lishi"
: '',
"swz_num"
: '',
"zy_num"
: '',
"ze_num"
: '',
"dw_num"
: '',
"gr_num"
: '',
"rw_num"
: '',
"yw_num"
: '',
"rz_num"
: '',
"yz_num"
: '',
"wz_num"
: '',
"qt_num"
: '',
"note_num"
: ''
}
#将各项信息提取并赋值
item
=
i.split(
'|'
)
#使用“|”进行分割
data[
"station_train_code"
]
=
item[
3
]
#获取车次信息,在3号位置
data[
"from_station_name"
]
=
item[
6
]
#始发站信息在6号位置
data[
"to_station_name"
]
=
item[
7
]
#终点站信息在7号位置
data[
"start_time"
]
=
item[
8
]
#出发时间在8号位置
data[
"arrive_time"
]
=
item[
9
]
#抵达时间在9号位置
data[
"lishi"
]
=
item[
10
]
#经历时间在10号位置
data[
"swz_num"
]
=
item[
32
]
or
item[
25
]
#特别注意,商务座在32或25位置
data[
"zy_num"
]
=
item[
31
]
#一等座信息在31号位置
data[
"ze_num"
]
=
item[
30
]
#二等座信息在30号位置
data[
"gr_num"
]
=
item[
21
]
#高级软卧信息在21号位置
data[
"rw_num"
]
=
item[
23
]
#软卧信息在23号位置
data[
"dw_num"
]
=
item[
27
]
#动卧信息在27号位置
data[
"yw_num"
]
=
item[
28
]
#硬卧信息在28号位置
data[
"rz_num"
]
=
item[
24
]
#软座信息在24号位置
data[
"yz_num"
]
=
item[
29
]
#硬座信息在29号位置
data[
"wz_num"
]
=
item[
26
]
#无座信息在26号位置
data[
"qt_num"
]
=
item[
22
]
#其他信息在22号位置
data[
"note_num"
]
=
item[
1
]
#备注信息在1号位置
color
=
colored()
data[
"note_num"
]
=
color.white(item[
1
])
#如果没有信息,那么就用“-”代替
for
pos
in
name:
if
data[pos]
=
=
"":
data[pos]
=
"-"
tickets
=
[]
cont
=
[]
cont.append(data)
for
x
in
cont:
tmp
=
[]
for
y
in
name:
if
y
=
=
"from_station_name"
:
s
=
color.green(chezhan_names[data[
"from_station_name"
]])
tmp.append(s)
elif
y
=
=
"to_station_name"
:
s
=
color.yeah(chezhan_names[data[
"to_station_name"
]])
tmp.append(s)
elif
y
=
=
"start_time"
:
s
=
color.green(data[
"start_time"
])
tmp.append(s)
elif
y
=
=
"arrive_time"
:
s
=
color.yeah(data[
"arrive_time"
])
tmp.append(s)
elif
y
=
=
"station_train_code"
:
s
=
color.yellow(data[
"station_train_code"
])
tmp.append(s)
else
:
tmp.append(data[y])
tickets.append(tmp)
for
ticket
in
tickets:
table.add_row(ticket)
print
(table)
def
main():
date
=
input
(
"请输入时间:\n"
)
from_station
=
chezhan_code[
input
(
"请输入起始站点:\n"
)]
to_station
=
chezhan_code[
input
(
"请输入目的站点:\n"
)]
url
=
"https://kyfw.12306.cn/otn/leftticket/queryz?"
headers
=
{
"user-agent"
:
"mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.26 safari/537.36 core/1.63.5702.400 qqbrowser/10.2.1893.400"
}
url
=
url
+
"leftticketdto.train_date="
+
date
+
"&leftticketdto.from_station="
+
from_station
+
"&leftticketdto.to_station="
+
to_station
+
"&purpose_codes=adult"
#print(url) 已经检查过生成的url是正确的
#request请求获取主页
r
=
requests.get(url,headers
=
headers)
r.raise_for_status()
#如果发送了一个错误的请求,会抛出异常
r.encoding
=
r.apparent_encoding
showticket(r.text)
#print(r.text)
main()
|
stationinfo.py 。
1
2
3
4
5
6
7
8
|
import
re,requests
url
=
"https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971"
response
=
requests.get(url,verify
=
false)
#将车站的名字和编码进行提取
chezhan
=
re.findall(r
'([\u4e00-\u9fa5]+)\|([a-z]+)'
, response.text)
chezhan_code
=
dict
(chezhan)
chezhan_names
=
dict
(
zip
(chezhan_code.values(),chezhan_code.keys()))
#print(chezhan_names)
|
到此这篇关于教你用python实现12306余票查询的文章就介绍到这了,更多相关python实现12306余票查询内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/weixin_51463905/article/details/117821678 。
最后此篇关于教你用python实现12306余票查询的文章就讲到这里了,如果你想了解更多关于教你用python实现12306余票查询的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是一名优秀的程序员,十分优秀!