前言:挺多以前的都不能用了,12306的反爬策略改了,我写的这个到我发文截止还是能用的。
本案例基于机械工业出版社出版的《Python网络爬虫从入门到精通》相关案例改写。
使用Python版本为3.7,requests版本为2.23.0
目标:抓取指定日期指定出发到达目的地的指定车次信息,如下:
我们目标为抓取2020-06-21日沈阳到鞍山的G8070次列车信息。
整个流程如下:
首先在12306网站中我们进入图示页面,打开开发者控制台,我们发现了如下交互:
查看query,可以看见网站使用get请求的URL,需要我们动态传入的有train_date(日期)、from_station(起始车站)、to_station(终点车站)以及purpose_codes,这里我们使用默认的ADULT。因此我们在生成这个请求URL的时候就要重点关注这三个信息。通关观察可以发现,from_station和to_station使用的是车站编码,因此我们要去获取这个编码表。
找到这个编码表脚本,如下图所示:
点击跳转到详细页面,我们来分析这个编码表。
搜索SYT(我们在get请求中赋值给from_station的编码),如下:
可以看到我们需要的格式为‘地名|英文编码’,因此可以利用正则表达式查找相关信息,正则表达式如下:
pattern = u'([\u4e00-\u9fa5]+)\|([A-Z]+)'#\u4e00-\u9fa5是所有汉字的Unicode编码范围
最后再转化成{城市名:编码}这样的字典,方便后续取用。
在获取完城市编码信息后,我们就可以生成请求获取我们最初目标的数据。
我们点击跳转到这个query详情页面查看返回信息格式,为json数据,如下:我们需要的数据被包裹在data=>result中。我们来分析这个数据格式,数据以|分割,第3个位置为车次编号,第6个位置为出发站编码,第7个位置为到达站编码等等以此类推,我们可以根据这个数据得到我们需要的信息。
最后代码如下:
import requests
import re
#导入Python SSL处理模块 Python 2.7.9 之后版本引入了一个新特性
import ssl
#表示忽略未经核实的SSL证书认证
ssl._create_default_https_context=ssl._create_unverified_context
#本案例基于机械工业出版社《Python网络爬虫从入门到精通》相关案例改写
def get_station():
#12306的城市名和城市代码js文件和URL
url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9143'
r = requests.get(url)
pattern = u'([\u4e00-\u9fa5]+)\|([A-Z]+)'#\u4e00-\u9fa5是所有汉字的Unicode编码范围
result = re.findall(pattern,r.text)#按正则表达式匹配
station=dict