python 12306查询不到车次_Python3.x 抓取12306车次信息,表格详情显示,让你学会思路,分析网站特点,爬取数据。12306车票查看器!...
我的例子都比较适合新手,那种老司机请绕道,谢谢!
ps
前言
最近学习Python,所以呢?跟大家一样,都是看看官网,看看教程,然后就准备搞一个小东西来试试,那么我使用的例子是实验楼中的12306火车票查询例子。但是那个是2.7版本的,并且那个实验楼的ubuntu系统老是一些包装不上,没办法就在我电脑上搞好了。
结果展示:
我在window上运行的结果
下面这一段说明我是抄的,哈哈,因为我自己再怎么写还不是同样的内容。
让我们先给这个小应用起个名字吧,既然及查询票务信息,那就tickets,其实 大家随意了,需要发布就需要起一个更好的名字,不然只要自己玩儿的懂,但是要有程序的特点,所以还是tickets相关的吧。方便阅读和自己记忆。
我们希望用户只要输入出发站,到达站以及日期就让就能获得想要的信息,比如要查看10月31号贵阳-遵义西的火车余票, 我们只需输入:
python3.5 lnlr.py 贵阳 遵义西 2017-10-31
注意:上面的日期(包括后面的)是笔者写文章时确定的日期,当你在做这个项目的时候可能要根据当前时间做适当调整。
转化为程序语言就是:
python3.5 lnlr.py from to date
另外,火车有各种类型,高铁、动车、特快、快速和直达,我们希望可以提供选项只查询特定的一种或几种的火车,所以,我们应该有下面这些选项:
-g 高铁
-d 动车
-t 特快
-k 快速
-z 直达
这几个选项应该能被组合使用,所以,最终我们的接口应该是这个样子的:
python3.5 lnlr.py [options] from to date
接口已经确定好了,剩下的就是实现它了。
环境
Centos 7 linux 系统
Python3.5.2
使用到的库
docopt------>命令行解释器(把我玩儿死)
colorama--->一个文本着色器
requests --->爬虫必备,http请求库
prettytable->表格显示
安装库
未安装之前
Linux上面目前的库
安装库:
pip3.5 install requests colorama docopt prettytble
安装之后
安装完成之后的库列表
ok,我们环境有了,库有了,那么应该干啥呢?
爬虫个人分析:
制定爬取内容
选取目标
准备环境,上面就提前说了,因为这个本来就是在搞爬虫,所以...
分析该网站的html结构,得到url
爬取数据
分析数据
封装数据(组装数据),弄成自己想要的样子
coding......
那么我们开始吧
第一步
当然是打开12306的官网了,然后进行一个余票查询,当然首先你得按一下f12,打开控制台面板哦。
我是查询的是:贵阳--遵义西 10-31号的车票
f12之后,查票页面
我先埋下一个伏笔:
我看到的贵阳-遵义 10-31的车次一共是11个班次。
第二步
首先在控制台找到Network按钮,点击。然后选择XHR ---》找到请求到后台的接口,
请求接口
那么我们先看一个三个接口的请求和返回的数据:
1.https://ad.12306.cn/sdk/webservice/rest/appService/getAdAppInfo.json?placementNo=0004&clientType=2&billMaterialsId=28e783cd2ec048ee8575cc3e502292c2
查看返回的结果:
貌似没有什么有用的信息。
第三个接口返回的数据
哈哈,在里面我看到了贵阳,遵义,那么大胆的猜测这个接口有可能就是我们需要的。
我们继续点开看看有什么东西,这些数据都是以json的格式传递过来的。
展开结果
到这里我相信,聪明的人已经知道了这个就是我们所需要的接口了,而这些数据就绝对是车次信息的数据。
由上面的我f12查看到的数据是11条,那么你们就没有点小激动么?
说明这个接口就是我们所需要的接口无误。那么现在我们就要得到它的url咯。
靠,双十一快到了,被女朋友抓去看了一会儿衣服,可能今天就不写了,明天接着写。
那么这样:我就明天开始分析url,然后就coding
请求的接口URL:
https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-10-31&leftTicketDTO.from_station=GIW&leftTicketDTO.to_station=ZIW&purpose_codes=ADULT
分析:
1. 查看请求方式 POST/GET(常用的),这里使用的是GET请求
2. 肯定带有参数了,并且GET请求是拼接到url之后的,我们查询的时候是输入了起始地点,目的地点,出发时间。那么url上也应该带有这三个。
3. 得到参数名称:leftTicketDTO.train_date=2017-10-31,leftTicketDTO.from_station=GIW,leftTicketDTO.to_station=ZIW
还有一个参数:purpose_codes=ADULT 根据ADULT的意思(成人,成年)大胆猜测这就是学生票和成人票。
4.得到了四个参数,但是我们还不知道其中有两个GIW,ZIW是什么意思。
因为我输入的是中文,但是出现的是字母代号。做过前后台交互的同学应该觉得这种是很常见的。目的是避免了中文传输导致的问题。
分析参数的获取
leftTicketDTO.train_date=2017-10-31 时间
leftTicketDTO.from_station=GIW 出发地
leftTicketDTO.to_station=ZIW 目的地
同学们请注意:我们输入的是中文,出来的是地点代码,说明中间有一层转换,那么在常规的网站中,只有两种三种方式能这样处理?
将这个地点-地点代码字典写入js中,这个地方有可能,因为国内的地点太多,需要手动维护。
将地点-地点代码字典写入本地文件文件,做好缓存,每次读取文件,然后使用。
从远端服务器进行获取,在这里也没必要,因为每次都要去请求后台,增加服务器的压力,这个是没必要的,因为这个字典的话是基本不会变化的。
ok经过上面的分析,我们就能很清楚的知道这个字典绝对是从js获取的,那么我们就也一样的使用发f12来检查到资源,找到该页面所引用的所有js,然后进行分析。
该页面所加载的js文件
上图中的矩形中的就是当前页面中的所有js,当然每个js的作用我就不一一的说了,各位需要帮助的可以email(leihfein@gmail.com)我,或者在下面留言。
那么我直接查看各个的内容,发现有一个是:
包含了地点,地点代码js
浏览器中输入该URL看到的结果
我们还可以来一个测试:
我在查询的时候是输入了,贵阳-遵义,搜索一下看看吧。
搜索
同学们,看到这个你们觉得爽不爽,说明这个文件就是我们所需要的。
ok,到这里,编码前期准备工作,所有的都昨晚了,我从一步一步的分析,然后截图。给大家思路,方法,步骤。希望大家能够更明白,更多的是学习到其中的分析思路哈。
codingwars
首先爬取地点-代码code字典。
#!/usr/bin/env python3
# coding: utf-8
import requests
import re
from pprint import pprint
"""
获取到地点-地点code字典
"""
def get_station():
url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9028'
response = requests.get(url,verify=False)
station = re.findall(u'([\u4e00-\u95fa5]+)\|([A-Z]+)',response.text)
pprint(dict(station),indent=4)
if __name__=="__main__":
get_station()
在最后,我是使用pprint输出到屏幕的,大家可以进行拷贝,或者是使用Linux的重定向进行输出到别的文件 。
python3.5 get_station_code.py > stations.py
并且需要在stations.py文件中增加一个名字哦,因为输出来时也没有名字的。见下图
在windows中就只能拷贝了,
新增一个stations字典名称
好的,到这里我们的地点-地点代码就得到了,那么我们就应该写那个爬取车次信息的py了。
处理输出的代码:
from prettytable import PrettyTable
from stations import stations
from colorama import init, Fore
"""
处理爬取出来的车次信息,并进行表格输出
"""
init()
class TrickCollection(object):
def __init__(self, available_trains, options):
self.header = ('车次 车站 时间 历时 特等座 一等 二等 高级软卧 软卧 动卧 硬卧 '
+ '软座 硬座 无座 备注').split()
self.available_trains = available_trains
self.options = options
# 将历时转化为小时和分钟的形式
def get_duration(self, raw_train):
duration = raw_train[10].replace(':', '小时') + '分'
if duration.startswith('00'):
return duration[4:]
if duration.startswith('0'):
return duration[1:]
return duration
# 返回每个车次的基本信息
def trains(self):
for raw_train in self.available_trains:
# 列车号
train_no = raw_train[3]
# 得到什么列车并小写
initial = train_no[0].lower()
# 反转station所对应的字典
stations_re = dict(zip(stations.values(), stations.keys()))
if not self.options or initial in self.options:
# 将车次的信息保存到列表中
# train 出发地
begin_station = stations_re.get(raw_train[4])
# train 目的地
end_station = stations_re.get(raw_train[5])
# your 出发地
from_station = stations_re.get(raw_train[6])
# your 目的地
to_station = stations_re.get(raw_train[7])
# 判断是起始还是经过
begin_flag = self.__check_equals(begin_station, from_station)
end_flag = self.__check_equals(end_station, to_station)
train = [
train_no,
'\n'.join([begin_flag + ' ' + self.__get_color(Fore.GREEN, from_station),
end_flag + ' ' + self.__get_color(Fore.RED, to_station)]),
'\n'.join([self.__get_color(Fore.GREEN, raw_train[8]),
self.__get_color(Fore.RED, raw_train[9])]),
# 时间
self.get_duration(raw_train),
# 历时
raw_train[32],
# 特等座
self.__show_color(raw_train[31]),
# 一等
self.__show_color(raw_train[30]),
# 二等
self.__show_color(raw_train[22]),
# 高级软卧
self.__show_color(raw_train[23]),
# 软卧
self.__show_color(raw_train[33]),
# 硬卧
self.__show_color(raw_train[28]),
# 软座
self.__show_color(raw_train[24]),
# 硬座
self.__show_color(raw_train[29]),
# 无座
self.__show_color(raw_train[26]),
# 备注
self.__show_color(raw_train[1])
]
# 更改不运行车次的时间和历时
if raw_train[14] == 'null':
train[2] = '--\n--'
train[3] = '--'
# 将空字符串转化为‘--’
for i, item in enumerate(train):
if not item:
train[i] = '--'
yield train
def __check_equals(self, from_station, to_station):
"""
检查是否是始、过
检查你的起始站是否为该车次的起始站
检查你的终止站是否为该车次的终止站
:param from_station: 出发位置
:param to_station: 结束位置
:return: 决定了是使用‘始' 还是 ’过‘
"""
if from_station == to_station:
return '始'
else:
return '过'
def __get_color(self, color, content):
"""
返回颜色内容组合,并且清除该内容之后的颜色
:param color: 传递的颜色
:param content: 内容
:return: 返回值为拼接上颜色
"""
return color + content + Fore.RESET
def __show_color(self, content):
"""
对内容进行颜色显示,并且只显示有,其余不上色
:param content: 需要颜色显示的内容
:return: 返回设置结果
"""
if content == '有':
return Fore.GREEN + content + Fore.RESET
else:
return content
def pretty_print(self):
"""
显示内容
:return:
"""
pt = PrettyTable()
pt._set_field_names(self.header)
for train in self.trains():
pt.add_row(train)
print(pt)
成果展示:
但是我在远端上使用xshell没有颜色,这个是什么鬼。最后发现是自己设置xshell而已。
好的,下面就是我们的程序执行的结果。
如果程序输入的地点在字典中查询不到,那么就不能查票。所以我们需要随时更新stations.py文件(地点-code字典表)
成果展示
ok,到这里的话,我们的所有的爬虫就抓取成功,并且输出成我们想要的结果了。我准备下一步就是搞那个抢票。试试吧。
代码在后面我会给出github地址的。
总结
在本次实验中,我所遇到的问题简单说一下:
optdoc的使用,这个是我遇到的最大的坑,(usage 下面命令之后必须空一行)
在Linux上的缩进问题
3.就是对python还不是特别的熟。
github地址
阅读到本教程的童鞋,喜欢请点个喜欢,不求赞赏,只求喜欢,顶上去。现在网上很多都是以前的接口的例子,已经跑不起来了,所以我希望让更多的人看到,能帮助更多还在py的起步阶段,又没有人练手项目的人。
python 12306查询不到车次_Python3.x 抓取12306车次信息,表格详情显示,让你学会思路,分析网站特点,爬取数据。12306车票查看器!...相关推荐
- python爬取网易云音乐_Python 从零开始爬虫(七)——实战:网易云音乐评论爬取(附加密算法)...
前言 某宝评论区已经成功爬取了,jd的也是差不多的方法,说实话也没什么好玩的,我是看上它们分析简单,又没加密才拿来试手的.如果真的要看些有趣的评论的话,我会选择网易云音乐,里面汇聚了哲学家,小说家,s ...
- Python实践 - 网络爬虫笔记 - 2、从网站上爬取公开信息
Python实践笔记 - 2.从网站上爬取公开信息 张板书的Python的实践笔记,包括笔记与DeBug的经历. 为了完成一个比较麻烦的实习任务,尝试着做了这样一个爬虫项目. 任务要求之一是要检索安徽 ...
- python简单网站爬虫-爬取北京7天最高、最低气温
python简单网站爬虫-爬取北京7天最高.最低气温 前置操作: 1.待爬取网站: 北京天气的网址: http://www.weather.com.cn/weather1d/101010100.sht ...
- python自动爬取更新电影网站_python爬取电影网站信息
一.爬取前提 1)本地安装了mysql数据库 5.6版本 2)安装了Python 2.7 二.爬取内容 电影名称.电影简介.电影图片.电影下载链接 三.爬取逻辑 1)进入电影网列表页, 针对列表的ht ...
- python爬虫实践篇--------飞猪网站资料爬取
一.什么是网页的http请求? Get请求:地址栏上明文显示了请求信息,即请求地址中带有符号 ? 的地址.请求速度快,但不安全 例如: 请求参数 wd 表示查询字段: pn表示页数,即pn=0 --& ...
- python爬虫系列(5.3-动态网站的爬取的策略)
一.认识动态网站 所谓的动态网站,是使用ajax加载出来的网页,我们打开网页的时候可以正常显示内容,但是我们在显示网页源代码的时候,里面却找不到该节点. 二.常见动态网站的抓取方式 1.直接分析aja ...
- python登录网站后爬取数据_用 Python 登录主流网站,我们的数据爬取少不了它
不论是自然语言处理还是计算机视觉,做机器学习算法总会存在数据不足的情况,而这个时候就需要我们用爬虫获取一些额外数据.这个项目介绍了如何用 Python 登录各大网站,并用简单的爬虫获取一些有用数据,目 ...
- python爬虫反爬机制_浅谈爬虫及绕过网站反爬取机制之Python深度应用
我们中公优就业的老师希望能给那些面临困境的朋友们带来一点帮助!(相关阅读推荐:Python学习就看这里!) 爬虫是什么呢,简单而片面的说,爬虫就是由计算机自动与服务器交互获取数据的工具.爬虫的最基本就 ...
- python爬取系统_python应用:爬虫框架Scrapy系统学习第四篇——scrapy爬取笔趣阁小说...
使用cmd创建一个scrapy项目: scrapy startproject project_name (project_name 必须以字母开头,只能包含字母.数字以及下划线) 项目目录层级如下: ...
最新文章
- 对称加密(4) NET对称加密实践
- mysql去掉秒杀场景_秒杀场景下mysql减库存逻辑优化
- vscode使用sftp同步服务器文件
- hbase 查询固定条数_HBase原理深入
- Flask中路由系统以及蓝图的使用
- 接口自动化持续集成实战
- 加速下载 玩转土豆网FLV视频四招
- 浅谈软件开发的四大要素
- 淘宝/天猫优惠券获取API 接口
- 2021年国内外离线下载服务全面评测与总结
- java海贼王秘宝传说下载_我的世界1.7.10海贼王整合包
- 来自Jeff和Joel对Stack Overflow网站建设的教训(摘选)
- 企业信息化整体架构图
- 并查集的使用,臭虫同性恋问题
- C++中吸取C的二等公民
- 天空之门手游怎么用电脑玩 天空之门手游模拟器教程
- @property python知乎_使用Mxnet进行图像深度学习训练工具 InsightFace - 使用篇, 如何一键刷分LFW 99.80%, MegaFace 98%....
- 微信企业号开发三:主动调用模式之发送news消息
- 企业网站需要一个专职的SEO吗?
- 可以直接在屏幕上面涂画的pointofix安装及汉化
热门文章
- 未来已来:探寻2019智博会上的前沿科技
- 《公路工程适应自动驾驶附属设施总体技术规范(征求意见稿)》公开征求意见...
- 干货!2019年你确定要错过这份优秀Web字体清单吗?
- 论文阅读 [TPAMI-2022] Incremental Density-Based Clustering on Multicore Processors
- 体育场馆智能化系统满足了哪些需求?
- python利用server酱推送IP地址
- 数据库中的Schema(模式)和View(视图)
- Spring Cloud微服务全家桶主要组件及简要介绍
- 2023美赛数学建模思路 - 案例:线性回归
- c语言判断正整数位数 请用strengh,C语言程序设计-4、12章习题解答.doc