制作一个火车票查询余票的爬虫

本文总阅读量

用python写出一个12306查询余票的爬虫

制作一个火车票查询余票的爬虫

PS:因为我要接入网页里面的,所以只做了个大概功能,其余后期做个接口接入到网页
这是代码

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
import re
import requests
from bs4 import BeautifulSoup
from pprint import pprint
import json

url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-09-02&leftTicketDTO.from_station=CBQ&leftTicketDTO.to_station=IZQ&purpose_codes=ADULT'
response = requests.get(url, verify=False)
rowlists = json.loads(response.text)['data']['result']
ticket_info_list = []
for rowlist in rowlists:
row9 = rowlist.split('|')
train_num = row[3]
from_station = row[4]
to_station = row[7]
from_time = row[8]
to_time = row[9]
all_time = row[10]
swz_num = row[32] or '--'
ydz_num = row[31] or '--'
edz_num = row[30] or '--'
gjrw_num = row[21] or '--'
rw_num = row[23] or '--'
dw_num = row[27] or '--'
yw_num = row[28] or '--'
rz_num = row[24] or '--'
yz_num = row[29] or '--'
wz_num = row[26] or '--'
ticket_info = [train_num, from_station, to_station, from_time, to_time, all_time , swz_num, ydz_num, edz_num, gjrw_num, rw_num, dw_num, yw_num, rz_num, yz_num, wz_num]
ticket_info_list.append(ticket_info)
print(ticket_info_list)

这是结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[['G6343', 'CBQ', 'IZQ', '06:10', '08:44', '02:34', '5', '13', '无', '--', '--', '--', '--', '--', '--', '无'],
['G6347', 'CBQ', 'IZQ', '07:00', '09:50', '02:50', '5', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['D7531', 'CBQ', 'GGQ', '08:58', '12:05', '03:07', '--', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['G6319', 'CBQ', 'IZQ', '10:22', '13:10', '02:48', '5', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['D7511', 'CBQ', 'GGQ', '11:05', '14:15', '03:10', '--', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['G6303', 'CBQ', 'IZQ', '11:10', '14:11', '03:01', '4', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['G6307', 'CBQ', 'IZQ', '12:20', '15:12', '02:52', '1', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['D7503', 'CBQ', 'GGQ', '13:04', '16:26', '03:22', '--', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['G6327', 'CBQ', 'IZQ', '13:50', '16:41', '02:51', '4', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['D7523', 'CBQ', 'GGQ', '14:19', '17:34', '03:15', '--', '无', '无', '--', '--', '--', '--', '--', '--', '2'],
['D7507', 'CBQ', 'GGQ', '16:00', '19:16', '03:16', '--', '有', '无', '--', '--', '--', '--', '--', '--', '13'],
['G6339', 'CBQ', 'IZQ', '16:19', '19:22', '03:03', '无', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['D7527', 'CBQ', 'GGQ', '16:53', '20:10', '03:17', '--', '有', '无', '--', '--', '--', '--', '--', '--', '有'],
['G6323', 'CBQ', 'IZQ', '17:10', '20:07', '02:57', '5', '无', '无', '--', '--', '--', '--', '--', '--', '无'],
['G6315', 'CBQ', 'IZQ', '17:45', '20:41', '02:56', '无', '8', '无', '--', '--', '--', '--', '--', '--', '无'],
['D7515', 'RVQ', 'GGQ', '19:01', '22:16', '03:15', '--', '有', '无', '--', '--', '--', '--', '--', '--', '有'],
['G6311', 'CBQ', 'IZQ', '19:12', '22:06', '02:54', '5', '16', '有', '--', '--', '--', '--', '--', '--', '无'],
['D7519', 'CBQ', 'GGQ', '20:15', '23:31', '03:16', '--', '有', '有', '--', '--', '--', '--', '--', '--', '有'],
['G6331', 'CBQ', 'IZQ', '20:46', '23:29', '02:43', '5', '16', '有', '--', '--', '--', '--', '--', '--', '无']]

制作过程

看着代码量挺少的,不过找东西浪费挺多的。。。
首先是链接的url

1
https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-09-02&leftTicketDTO.from_station=CBQ&leftTicketDTO.to_station=IZQ&purpose_codes=ADULT

在12306查询网页上,按下F12,点击netword。输入站点和时间后,点击查询,就能找到这个连接了
enter description here
可以看出有3个重要的值要传入,分别是时间:train_date=2017-09-02,出发站:from_station=CBQ终点站:to_station=IZQ
输入的城市他都会配到生成3个字母,而且没看出什么规律的,所以又得在netword里面翻一翻,最后看到一个叫station_name的,就找到链接了。里面是城市对应城市代码文件,然后又在网页源代码找到这个链接(因为这个文件会升级,所以就找到这个链接,制作一个可以随时生成城市-城市代码的文件)
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import re
import requests
from bs4 import BeautifulSoup
from pprint import pprint
import json

url = 'https://kyfw.12306.cn/otn/leftTicket/init'
response = requests.get(url, verify=False)
soup = BeautifulSoup(response.text, "html.parser")
station_get = soup.find_all("script", {"type":"text/javascript"})[7]
a = re.sub(' ',"",str(station_get))
a = re.sub('"', "" ,a)
b = re.search('otn(.+)type', a).group()
c = b[:-4]
station_html = "https://kyfw.12306.cn/"+c
response = requests.get(station_html, verify=False)
stations = re.findall(u'(\w+)\|([A-Z]+)', response.text)
stations_dict = dict(stations)
with open('stations_dict.json', 'w') as fp:
json.dump(stations_dict,fp=fp,ensure_ascii = False)

这份代码里面的station_get用美丽汤匹配完是一个有包含这些元素的列表,而我要的那个刚好是第8个,就用切片取出来。
由于取出来后我用正则都正则不了,脑子没什么回路,于是就有了a,b,c这3行清洗数据的代码- -(后来也懒得改了)反正这样就匹配出来,然后就拼成一个连接就更get到那份城市-城市代码列表了=。=,之后在用正则就能取出来了,最后保存在json里面。注意一定要加入参数(ensure_ascii = False)不然就是生成\u23s这些东西

这份列表获取完了,可以进行下一步了(虽然我源代码里面没引用到- -。。。不过以后肯定得用到的)
由于12306有证书验证,所以要加(verify = False)
传入url后获取到的json可以看到我们的数据在[‘data’][‘result‘]里面,我们就可以把他取出来,由于取出来后是一个列表,我们就可以用split()来切割,切割完重点就来了 。。。前面站点,出发时间这些还好,后面那些票我得找好久啊,一直数也不是事。而且在网上,票数比较多就显示有,没票就显示无,其他也就显示几十张票,得查很久才能找到这些数据对应在哪里。(还好我比较懒,难得动脑筋-。-)。按下F12后按下面这张图找,如果右边那个框显示的格式不是这样的话,点击两个框中间的{}就可以了~~(还好12306容易找,然后搜索”–”就找到他对应的位置了。。),从图片可以看出什么票型对应在哪个位置,好像最后只有一个动卧我找不到,只能重新搜索,然后刚好哪个车次动卧有显示具体车票就找到了,然后发现网页的值是yb - -
python里面如果值为空显示其他值可以写(or ‘ 你期望的值’),果然python好啊!!!!
enter description here
虽然看似简单,但找链接,匹配正则,最后匹配数据费了许多时间。而且这个还是我半年前曾经看过关于查询火车票的教程,现在还依稀记得才节约点时间-。-(哪个教程我找不到了。。。。。)
好了,抓取数据就这样愉快的捉取完了,至于怎么引用,得看到学到那里啊。。。还有看到潮汕到广州开学那段时间的票空空如也t_t。。。

查看评论