使用scrapy进行12306车票查询
概述
详细
一、环境搭建
1. 安装配置python3.6
示例网站使用的是python 3.6.1
下载地址:https://www.python.org/downloads/release/python-361/
根据自己的系统选择相应的版本
2. 安装Twisted
Windows:
进入http://www.lfd.uci.edu/~gohlk...下载对应twisted
转到下载目录, 命令行执行:pip install Twisted-17.9.0-cp36-cp36m-win_amd64.whl
3. 安装Scrapy
mac或linux:
pip install Scrapy
windows:
pip install pywin32
pip install Scrapy
二、项目结构以及程序实现
上图是使用scrapy startproject spider12306 命令生成的基本模板, 之后使用scrapy genspider search 12307.cn 生成了一个基本爬虫,在此基础上进行自己需要的爬虫改写.
思路:
找到网页接口——进行查询后通过chrome找到查询地址是这样的:
通过这个地址可以看出,查询是通过向https://kyfw.12306.cn/otn/leftTicket发送GET请求来执行查询的。参数一共有4个:
leftTicketDTO.train_date: 日期
leftTicketDTO.from_station: 出发站
leftTicketDTO.to_station: 到达站
purpos_codes:车票类型 ADULT 成人票
现在有一个问题,出发站和到达站用的是缩写,查询返回的结果用的也是缩写,所以我们需要知道英文缩写对应的车站,之后我就找到了这个东西:
有一个名为:station_name 的js文件,其中就记录所有的中文站名以及其缩写。
通过正则等方法将其保存为两个json文件(本人用的是笨办法),键值对分别是:
站点名: 缩写 以及 缩写: 站点名 方便我们将来查询
之后就可以编写爬虫了
1. 根据顺序来我们先设置起始站点为查询站点缩写的js文件
1 2 3 4 5 6 7 8 9 10 11 12 13 | class SearchSpider(scrapy.Spider): name = 'search' allowed_domains = [ '12306.cn' ] # 出发时间 日期如果小于今天 会报错的 train_data = '2018-03-22' # 出发站 from_station = '郑州' # 到 to_station = '杭州' start_urls = [ 'https://kyfw.12306.cn/otn/resources/js' '/framework/station_name.js?station_version=1.9048' ] |
2. 解析并保存结果为json文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | if not os.path.exists( 'stations.json' ): text = response.body.decode( 'utf-8' ) content = re.match( '.+?(@.+)' , text) if content: # 获取所有车站信息 text = content.group( 1 ) # 进行清洗后写入json文件 l = text.split( '|' ) a, b = 1 , 2 stations = {} search = {} while b < len (l): stations[l[a]] = l[b] search[l[b]] = l[a] a + = 5 b + = 5 stations = json.dumps(stations, ensure_ascii = False ) with open ( 'stations.json' , 'w' , encoding = 'utf-8' ) as f: f.write(stations) search = json.dumps(search, ensure_ascii = False ) with open ( 'search.json' , 'w' , encoding = 'utf-8' ) as f: f.write(search) else : (response.body.decode()) |
3. 根据需要查询的内容向查询地址发出get请求并接受查询结果
1 2 3 4 5 6 7 8 9 10 | with open ( 'stations.json' , 'rb' ) as f: station = json.load(f) query_url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?' \ 'leftTicketDTO.train_date={}&' \ 'leftTicketDTO.from_station={}&' \ 'leftTicketDTO.to_station={}&' \ 'purpose_codes=ADULT' . format ( self .train_data, station[ self .from_station], station[ self .to_station]) yield scrapy.Request(query_url, callback = self .query_parse) |
4. 解析查询结果并保存为csv文件(可使用excel打开)
通过观察发现,返回的结果都是用'|'隔开的,貌似只能用下标来定位, 所以采用了下面的方法,如果有更好的方法请联系我,谢谢!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def query_parse( self , response): """解析查询结果""" text = response.body.decode( 'utf-8' ) message_fields = [ '车次' , '始发站' , '终点站' , '出发站' , '到达站' , '出发时间' , '到达时间' , '历时' , '特等座' , '一等座' , '二等座' , '软卧' , '硬卧' , '硬座' , '无座' ] writer = csv.writer( open ( 'ans.csv' , 'w' )) writer.writerow(message_fields) infos = json.loads(text)[ 'data' ][ 'result' ] with open ( 'search.json' , 'rb' ) as f: search = json.load(f) for info in infos: info = info.split( '|' )[ 3 :] if info[ 8 ] = = 'N' : continue row = [info[ 0 ], search[info[ 1 ]], search[info[ 2 ]], search[info[ 3 ]], search[info[ 4 ]], info[ 5 ], info[ 6 ], info[ 7 ], info[ 29 ], info[ 28 ], info[ 27 ], info[ 20 ], info[ 25 ], info[ 26 ], info[ 23 ]] writer.writerow(row) pass |
详细代码在例子包中, 仅供参考.....
运行
进入spider12306文件夹,在装有scrapy的虚拟环境或真实环境中运行
scrapy crawl search
即可, 然后可在运行目录找到 ans.csv 文件 打开后类似上图
注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?