python编程实现12306的一个小爬虫实例


Posted in Python onDecember 27, 2017

本文思路主要来源于实验楼的教程,但是一些具体的一些细节是我自己发现的,比如哪里获得站点对应的3位英文编号,怎么获得这个查询的url

本文用到的库主要有requests(获取url的内容),prettytable(让文本输出美观),argparse(命令行参数解析)

关于这些库怎么使用,可以参见我之前的博文

1、首先打开12306余票查询的界面

https://kyfw.12306.cn/otn/lcxxcx/init

我们想要的信息当然就是在输入了始发站、终点站和日期之后各车次的时间和车票余量,那么我们尝试在始发站使用检查元素,观察一下它是怎么上传始发站的信息的,那么我们不妨随便输入出发地、目的地和信息,使用抓包工具来看看它是怎么发包的(使用浏览器也可以,因为我们只需要查看包的内容,不需要更改包)

2、

python编程实现12306的一个小爬虫实例

在chrome的network中我们可以查看到我们点击之后浏览器发送的所有包(关于http包的知识不熟悉的同学,可以看看《图解http》这本书)

python编程实现12306的一个小爬虫实例

点击查询之后我们马上就会注意到以query开头的这个包,显然这就是一个查询指令,我们看看这个包的url

'https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=2016-10-04&from_station=BJP&to_station=XKS'

然后我们看看它的response

python编程实现12306的一个小爬虫实例

仔细观察就能发现它其实是一串json格式的字符串(要非常有经验。。。。)

3、经过以上这些过程,我们大致就能知道我们需要做的是什么了,我们只需要更改url中的data,fromstaion,tostaion后面的内容,然后用requests获得response,然后解析这一串json字符就行了。

但是我们会发现,日期还好说,对于fromstation和tostaion的代码,我们该怎么办呢?

4、有两种可能,一中可能是这些文件在服务器上,每回改变站点网页都会从服务器请求这个站点的代码,还有一种可能是这个已经下载到本地了,如何判断呢?我们不妨改变一下始发站,然后用抓包软件(或者浏览器)观察我们的浏览器是否向12306发送了包

python编程实现12306的一个小爬虫实例

把北京改成了上海,但是我们发现浏览器并没有发送包

这样我们基本可以肯定这个车站编号信息是存在本地了(已经从服务器下载下来)

5、我们这时候,就需要分析html来发现这个编号信息到底储存在了那里

我们试着检查一下出发地附近的html标签,在‘热门'上面点击检查,我们很容易发现这个标签上面带了一个onclick方法

python编程实现12306的一个小爬虫实例

我们发现这个onclick方法指向了一个js文件,并且名字是‘Stationfor12306',基本我们可以确定这个js文件就是我们需要的站点信息文件了。

6、我们尝试在这个html(12306余票查询界面)里面搜一下stationfor,我们马上就能发现,它就在<head>标签的<script>元素里,并且指向了一个url

python编程实现12306的一个小爬虫实例

进入这个url看看,我们马上就发现站点信息已经被我们找到啦(注意这是一个相对URL,绝对url需要在前面补上https://kyfw.12306.cn/)

python编程实现12306的一个小爬虫实例

关于怎么获取三位数的车站代码,用正则,字符串查询都是可以的啦,由于这里是固定的3位车站代码,我就用简单的字符串查询来提取这个代码了。

7、剩下的工作,基本就是代码实现了,关于具体怎么实现,我把我的代码贴在下面了。

#coding=utf-8 
import requests 
import argparse 
import datetime 
import re 
from prettytable import PrettyTable 
now = datetime.datetime.now() 
 
tomorrow = now+datetime.timedelta(days=1)  
tomorrow = tomorrow.strftime('%Y-%m-%d') 
print tomorrow 
 
argument = argparse.ArgumentParser() 
argument.add_argument('--fromcity','-f',default='hangzhoudong') 
argument.add_argument('--tocity','-t',default='xiamen') 
argument.add_argument('--date','-d',default=tomorrow) 
# argument.add_argument('-d',action='store_true') 
args =argument.parse_args() 
 
from_station = args.fromcity 
to_station = args.tocity 
Date = args.date 
 
stationlist_url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js' 
r = requests.get(stationlist_url, verify=False) 
stationlist = r.content 
 
ToStation = '' 
FromStation = '' 
 
placea = stationlist.find(from_station) 
placeb = stationlist.find(to_station) 
 
for i in range(-4,-1): 
  FromStation += stationlist[placea+i] 
for i in range(-4,-1): 
  ToStation += stationlist[placeb+i] 
 
query_url='https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate='+Date+'&from_station='+FromStation+'&to_station='+ToStation 
r = requests.get(query_url,verify=False) 
 
 
with open('json.txt','w') as fp: 
   fp.write(str(r.json())) 
 
if 'datas' in r.json()["data"]: 
  rj = r.json()["data"]["datas"] 
  pt = PrettyTable() 
 
  header = '车次 车站 到站时间 时长 一等座 二等座 软卧 硬卧 硬座 无座'.split() 
  pt._set_field_names(header) 
 
  for x in rj: 
    ptrow = [] 
    ptrow.append(x["station_train_code"]) 
    ptrow.append('\n'.join([x["from_station_name"],x["to_station_name"]])) 
    ptrow.append('\n'.join([x["start_time"], x["arrive_time"]])) 
    ptrow.append(x["lishi"].replace(':','h')+'m') 
    ptrow.append(x['zy_num']) 
    ptrow.append(x['ze_num']) 
    ptrow.append(x['rw_num']) 
    ptrow.append(x['yw_num']) 
    ptrow.append(x['yz_num']) 
    ptrow.append(x['wz_num']) 
    pt.add_row(ptrow) 
  print pt 
else : 
  print '这两个站点没有直达列车'

总结

以上就是本文关于python编程实现12306的一个小爬虫实例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
用Python和MD5实现网站挂马检测程序
Mar 13 Python
python中MethodType方法介绍与使用示例
Aug 03 Python
深入理解Python分布式爬虫原理
Nov 23 Python
对dataframe进行列相加,行相加的实例
Jun 08 Python
如何使用django的MTV开发模式返回一个网页
Jul 22 Python
django之静态文件 django 2.0 在网页中显示图片的例子
Jul 28 Python
django中使用POST方法获取POST数据
Aug 20 Python
使用Python3 poplib模块删除服务器多天前的邮件实现代码
Apr 24 Python
Python爬虫入门有哪些基础知识点
Jun 02 Python
matplotlib 画双轴子图无法显示x轴的解决方法
Jul 27 Python
使用jupyter notebook运行python和R的步骤
Aug 13 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
Aug 18 Python
python导出chrome书签到markdown文件的实例代码
Dec 27 #Python
Python类的继承和多态代码详解
Dec 27 #Python
快速查询Python文档方法分享
Dec 27 #Python
Java及python正则表达式详解
Dec 27 #Python
python matplotlib画图实例代码分享
Dec 27 #Python
python爬虫使用cookie登录详解
Dec 27 #Python
Python爬虫番外篇之Cookie和Session详解
Dec 27 #Python
You might like
php一个找二层目录的小东东
2012/08/02 PHP
ThinkPHP模板判断输出Empty标签用法详解
2014/06/30 PHP
php获取URL中带#号等特殊符号参数的解决方法
2014/09/02 PHP
php实现登录tplink WR882N获取IP和重启的方法
2016/07/20 PHP
基于jQuery的可用于选项卡及幻灯的切换插件
2011/03/28 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
js获取本机的外网/广域网ip地址完整源码
2013/08/12 Javascript
自己写的Javascript计算时间差函数
2013/10/28 Javascript
跟我学习javascript解决异步编程异常方案
2015/11/23 Javascript
Bootstrap进度条与AJAX后端数据传递结合使用实例详解
2017/04/23 Javascript
vue.js学习之vue-cli定制脚手架详解
2017/07/02 Javascript
webstorm添加vue.js支持的方法教程
2017/07/05 Javascript
jQuery EasyUI window窗口使用实例代码
2017/12/25 jQuery
微信小程序实现自定义加载图标功能
2018/07/19 Javascript
JavaScript封闭函数及常用内置对象示例
2019/05/13 Javascript
js实现无刷新监听URL的变化示例代码详解
2020/06/03 Javascript
vue自定义组件(通过Vue.use()来使用)即install的用法说明
2020/08/11 Javascript
[48:28]完美世界DOTA2联赛循环赛FTD vs Magma第二场 10月30日
2020/10/31 DOTA
利用Python破解验证码实例详解
2016/12/08 Python
Python和Java进行DES加密和解密的实例
2018/01/09 Python
python用opencv批量截取图像指定区域的方法
2019/01/24 Python
PyQtGraph在pyqt中的应用及安装过程
2019/08/04 Python
对Django 中request.get和request.post的区别详解
2019/08/12 Python
Python reversed函数及使用方法解析
2020/03/17 Python
简单了解python shutil模块原理及使用方法
2020/04/28 Python
Python中bisect的用法及示例详解
2020/07/20 Python
Coltorti Boutique官网:来自意大利的设计师品牌买手店
2018/11/09 全球购物
中专生求职自荐信范文
2013/12/22 职场文书
实用求职信范文分享
2013/12/25 职场文书
餐厅销售主管职责范本
2014/02/19 职场文书
医院保洁服务方案
2014/06/11 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
村干部四风问题整改措施
2014/09/30 职场文书
2014年学校卫生工作总结
2014/11/20 职场文书
党员证明模板
2015/06/19 职场文书
党风廉政建设心得体会(2016最新版)
2016/01/22 职场文书