Python爬虫学习(利用requests库查询12306官网车票信息)

2023-11-09 12:20

本文主要是介绍Python爬虫学习(利用requests库查询12306官网车票信息),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 分析流程
  • 接口信息
    • 获取站点中文对应的英文字母(1)
    • 查询车票信息(2)
    • 查询车票价格信息(3)
  • 实现
  • 运行

分析流程

12306上获取相关车票信息,输入的查询数据流向:

  1. 用户进入官网时,前端向接口1发送GET请求得到站点中文对应英文字母信息
  2. 用户在查询页面输入或选择出发地、目的地及相关参参数(包括出发日期、票的种类等),得到用户的出行信息
  3. 利用步骤1得到的数据与用户出行的站点信息匹配,得到站点对应英文字母
  4. 利用站点对应字母构造请求参数向接口2提交,获取车票信息
  5. 可利用某一车票信息构造请求参数向接口3提交得到其相应车票的价格

接口信息

获取站点中文对应的英文字母(1)

  • 接口:https://www.12306.cn/index/script/core/common/station_name_v10036.js
    url
    得到的数据格式如下
    在这里插入图片描述

查询车票信息(2)

  • 接口:https://kyfw.12306.cn/otn/leftTicket/query (GET)url
    参数依次是:时间、出发地、目的地、成人(ADULT)或学生(0X00),其中出发、目的地是以大写英文代替(含义在下面返回数据的map字段下)(亦有相关接口获取地方的英文含义,后续给出)

  • 利用Postman工具测试
    向上图中那个Resquest URL发起GET请求,得到数据,我们发现在result字段下的数据做一下处理就可以得到车票的相关信息
    postman
    详细

查询车票价格信息(3)

  • 接口:https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice (GET)
    url
    参数值在车票信息result字段下
  • 原理同理(不做重复)

实现

import requests
from datetime import datetime
import osclass Ticket_inquiry():def __init__(self):self.headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}self.train_info = \['train_no', 'train_number', 'station_begin', 'station_end', 'begin', 'end', 'begin_time', 'end_time', 'duration', 'is_nextday','no_seat', 'hard_seat'] # 整理官网得到相关信息self.ticket_info_index = \[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 26, 29] #官网得到相关信息的索引位置self.begin = '' # 每次查询的出发地self.end = '' # 目的地self.ticket_info = None # 从官网获取的信息self.now_datetime = '' # 当前时间 格式: '2019-01-01'self.ticket_datetime = '' # 查询车票时间self.query_ans = list() # 查询结果self.stations = dict() # 得到的站点所对应的大写字母self.stations_file_path = 'D:\\stations.txt' # 得到的站点所对应的大写字母的信息的保存路径self.open_stations()def create_datetime(self, count=0):year = datetime.now().yearmonth = datetime.now().monthday = datetime.now().dayticket_day = int(day) + countf = '{0:4}-{1:{3}2}-{2:{3}2}' # 格式:2019-01-01self.now_datetime = f.format(year, month, day, '0')self.ticket_datetime = f.format(year, month, ticket_day, '0')def get_ticket_info(self, begin='', end='', date=0, isadult=True):self.ticket_info = Noneself.create_datetime(date)url = 'https://kyfw.12306.cn/otn/leftTicket/query' # 接口if isadult:purpose_codes = 'ADULT'else:purpose_codes = '0X00'params = {'leftTicketDTO.train_date':self.ticket_datetime,'leftTicketDTO.from_station':begin,'leftTicketDTO.to_station':end,'purpose_codes':purpose_codes} # 所需参数try:r = requests.get(url, params=params, headers=self.headers)r.raise_for_status()# r.encoding = r.apparent_encodingif r.status_code == 200:self.ticket_info = r.json() # 转换为json数据else:print('Server error!')except:print('Request ticket_info error!')finally:return self.ticket_infodef get_ticket_price(self, train_no='', from_station_no='', to_station_no='', seat_types='', train_date=''): # 获取价格信息url = 'https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice' # 接口params = \{'train_no':train_no, 'from_station_no':from_station_no, 'to_station_no':to_station_no, 'seat_types':seat_types, 'train_date':train_date} try:r = requests.get(url, params=params, headers=self.headers)r.raise_for_status()if r.status_code == 200:return r.json()else:print('Server error!')except:print('Resquet praice_info error!')return Nonedef organize_ticket_info(self): # 整理得到的信息if self.ticket_info is not None:results = self.ticket_info['data']['result']if results is not None:stations = self.ticket_info['data']['map']speed_num = 0for result in results:speed_num += 1print('\r正在查询..{:.1f}%'.format(100*speed_num/len(results)), end='')ans = dict()result_list = result.split('|')count = 0for train in self.train_info:ans[train] = result_list[self.ticket_info_index[count]]count += 1data = self.get_ticket_price(result_list[2], result_list[16], result_list[17], result_list[35], self.ticket_datetime) # 获取价格信息, 日期:13try:data = data['data']price_info = dict()price_info['no_seat'] = data['WZ']price_info['hard_seat'] = data['A1']price_info['hard_sleeper'] = data['A3']price_info['soft_sleeper'] = data['A4']except:passans['price_info'] = price_infoself.query_ans.append(ans)# print(self.query_ans)self.save_stations(stations)return self.query_ansdef print_ticket_info(self):os.system('cls')t = self.query_ansif t:print('\n%s - %s\n---' % (self.begin, self.end))for train_info in self.query_ans:try:print('车次:%-5s %s开-%s到 价格:%s(硬座)、%s(硬卧)'\% (train_info['train_number'], train_info['begin_time'], train_info['end_time'], \train_info['price_info']['hard_seat'], train_info['price_info']['hard_sleeper']))except:passprint('---\n')else:print('无票!\n')self.query_ans = []def save_stations(self, stations={}):if stations is not None:stations_chinese = dict()for key, val in stations.items():stations_chinese[val] = keyself.stations.update(stations_chinese)with open(self.stations_file_path, 'w') as file_object:file_object.write(str(self.stations))def open_stations(self):try:with open(self.stations_file_path, 'r') as file_object:stations_str = file_object.read()if stations_str is not None:self.stations = eval(stations_str)return self.stationsexcept:passdef use_chinese_query(self, begin='', end='', date=0):self.open_stations()try:self.begin = str(begin)self.end = str(end)begin = self.stations[self.begin]end = self.stations[self.end]if begin and end:self.get_ticket_info(begin, end , int(date))return Trueexcept:return False	if __name__ == '__main__':ticket = Ticket_inquiry()while True:begin = input('请输入出发地:')end = input('请输入目的地:')date = input('几天后出发(0:今天):')if not ticket.use_chinese_query(begin, end, date):ticket.get_ticket_info(str(begin).upper(), str(end).upper(), int(date))ticket.organize_ticket_info()ticket.print_ticket_info()

运行

运行结果
注:这里输入出发地、目的地需要先用代表车站的英文字母查一遍,程序会将其英文字母所对应车站以字典形式以更新的形式存放在文件中,以后才可用这里面有的中文作为查询条件查询
字典

这篇关于Python爬虫学习(利用requests库查询12306官网车票信息)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/376051

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

Python安装时常见报错以及解决方案

《Python安装时常见报错以及解决方案》:本文主要介绍在安装Python、配置环境变量、使用pip以及运行Python脚本时常见的错误及其解决方案,文中介绍的非常详细,需要的朋友可以参考下... 目录一、安装 python 时常见报错及解决方案(一)安装包下载失败(二)权限不足二、配置环境变量时常见报错及