需求介绍:

爬取指定地点的所有全国相关的列车班次详情。将结果写进mysql。

步骤及所遇到的问题:

1.寻取全国站点静态信息   https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9002 一个静态的js文件

2.借助web工具,本人谷歌浏览器F12在12306相关页面找取所需要的接口

3.寻找规律,注意去重写进mysql

直接上代码,看注释:

object TrainSchedulesMain {
def main(args: Array[String]): Unit = {
// val dateStr = "2019-01-07"
if (args == null || args.length < 2) {
System.err.println("args is null or missing")
System.exit(1)
}
val dateStrList = args(0).trim
val station = args(1).trim assert(StringUtils.isNotBlank(dateStrList), "dateStrList is null or empty")
assert(StringUtils.isNotBlank(station), "station is null or empty") // 打印参数
println(args.mkString(" "))
//获取全国所有的站点信息
val allStationsMap = analysisAllStations()
/*
* 1.深圳
* 2.深圳西
* 3.深圳东
* 4.深圳坪山
* 5.深圳北
* 6.福田
*/
// val fromStations = collection.mutable.ListBuffer("深圳", "深圳西", "深圳东", "深圳坪山", "深圳北", "福田")
var dateStr = "";
//出发站集合
val fromStations = collection.mutable.ListBuffer(station.trim)
dateStrList.split(",").foreach(date => {
dateStr = date
fromStations.foreach(r => {
var n = 0
//出发站
val fromStationRequest = allStationsMap.get(r).get
allStationsMap.foreach(d => {
val toStationRequest = d._2 //train code
//根据出发站和到达站请求12306
excuteAnaly(fromStationRequest, toStationRequest)
println(dateStr)
println("进度:" + r)
n += 1
println(n)
}) })
}) def excuteAnaly(fromStationRequest: String, toStationRequest: String) = {
val url1 =
s"""https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=${dateStr}&leftTicketDTO.from_station=${fromStationRequest}&leftTicketDTO.to_station=${toStationRequest}&purpose_codes=ADULT"""
.stripMargin
println("url1: " + url1)
//获取所查询的 出发站-》到达站 的所有班次列车信息
val responseStr = HttpRequest.sendGet(url1)
println("url1Res: " + responseStr)
if (StringUtils.isNotBlank(responseStr) && JSONUtil.isJson(responseStr)) {
val allStationModel = JSONUtil.toJavaBean(responseStr, new AllStationTimes().getClass)
//表示初始站为深圳 目的地为 toStationRequest 是有值
if (allStationModel != null && allStationModel.getHttpstatus == 200 && allStationModel.getData.getResult != null && allStationModel.getData.getResult.size() > 0) {
val resList = allStationModel.getData.getResult
for (item <- 0 until resList.size()) {
val str = resList.get(item)
val indexNumStart = str.indexOf("预订")
if (indexNumStart > -1) {
val arrs = str.substring(indexNumStart).split("\\|") val trainNo = arrs(1)
val trainCode = arrs(2)
val startStation = arrs(3)
val endStation = arrs(4)
val fromStation = arrs(5)
val toStation = arrs(6)
// 并且目的地站必须是终点站才会当做一条 班次 写入msyql[否则是过站,导致重复写入mysql.并且站点还不全]
if (toStation.trim.equals(endStation.trim)) {
val url2 =s"""https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no=${trainNo}&from_station_telecode=${fromStation}&to_station_telecode=${toStation}&depart_date=${dateStr}"""
println("url2: " + url2)
//查询上一步所有班次的详细各个站点顺序信息
val res = HttpRequest.sendGet(url2)
println("url2Res: " + res)
if (StringUtils.isNotBlank(res) && JSONUtil.isJson(res)) {
val trainSchedulesModel = JSONUtil.toJavaBean(res, new TrainSchedules().getClass)
if (trainSchedulesModel != null && trainSchedulesModel.getData.getData.size() > 0) {
val data0 = trainSchedulesModel.getData.getData.get(0) if (!MysqlHandleUtil(MysqlConnect.trainDB).isHasValue(
s"""select *
|
|from train_schedules
|where train_code='${data0.getStation_train_code}'
|and start_station_name='${data0.getStart_station_name}'
|and end_station_name='${data0.getEnd_station_name}'
|and start_time='${data0.getStart_time}'
|and dates='$dateStr'
|"""
.stripMargin)) {
val sql =
s"""insert into
|train_schedules(`train_code`,`start_station_name`,`end_station_name`,`start_time`,`arrive_time`,`dates`,`data`)
|values('${data0.getStation_train_code}','${data0.getStart_station_name}','${data0.getEnd_station_name}','${data0.getStart_time}','${trainSchedulesModel.getData.getData.get(trainSchedulesModel.getData.getData.size() - 1).getArrive_time}','${dateStr}','${JSONUtil.toJsonString(trainSchedulesModel.getData.getData)}')"""
.stripMargin
MysqlHandleUtil(MysqlConnect.trainDB).insertData(sql)
}
}
}
}
}
}
}
}
}
} /**
* 解析全国所有站点(中文名字,编码)
*
* @author XXXX
* @date 17:08
* @param []
* @return scala.collection.mutable.HashMap<java.lang.String,java.lang.String>
*/
def analysisAllStations(): collection.mutable.HashMap[String, String] = {
val hashMap = new mutable.HashMap[String, String]()
val url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9002"
val response = HttpRequest.sendGet(url)
assert(StringUtils.isNotBlank(response), "response is null or empty")
val arrs = response.split("@")
val len = arrs.length
for (item <- 1 until len) {
val ars = arrs(item).split("\\|")
hashMap.put(ars(1), ars(2))
}
hashMap
}
}

  

效果:

scala爬取指定地点的所有列车班次的更多相关文章

  1. Python3网络爬虫之requests动态爬虫:拉钩网

    操作环境: Windows10.Python3.6.Pycharm.谷歌浏览器目标网址: https://www.lagou.com/jobs/list_Python/p-city_0?px=defa ...

  2. Scala进阶之路-I/O流操作之文件处理

    Scala进阶之路-I/O流操作之文件处理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 说起Scala语言操作文件对象其实是很简单的,大部分代码和Java相同. 一.使用Scal ...

  3. requests抓取数据示例

    1:获取豆瓣电影名称及评分 # 抓取豆瓣电影名称及评分 url="https://movie.douban.com/j/search_subjects" start=input(& ...

  4. 一个js爬虫

    1. 第一个demo 2. configs详解——之成员 3. configs详解——之field 4. configs详解——之site, page和console 5. configs详解——之回 ...

  5. 爬虫--Scrapy框架课程介绍

    Scrapy框架课程介绍: 框架的简介和基础使用 持久化存储 代理和cookie 日志等级和请求传参 CrawlSpider 基于redis的分布式爬虫 一scrapy框架的简介和基础使用 a)    ...

  6. scrapy框架简介和基础使用

    概念 为了爬取网站数据而编写的一款应用框架,出名,强大.所谓的框架其实就是一个集成了相应的功能且具有很强通用性的项目模板.(高性能的异步下载,解析,持久化……) 安装 linux mac os:pip ...

  7. 手把手教你使用Python生成图灵智能小伙伴,实现工作助手/闲聊功能

    /1 前言/ 在家闲着,做个小项目,基于Python,实现一个语聊小机器人,分享给大家.项目整体比较简单,官方文档介绍的非常详细,可快速上手. /2 目标/ 将图灵机器人放到桌面,实现工作助手/陪聊功 ...

  8. 假如我来架构12306网站---文章来自csdn(Jackxin Xu IT技术专栏)

    (一)概论 序言:  此文的撰写始于国庆期间,当中由于工作过于繁忙而不断终止撰写,最近在设计另一个电商平台时再次萌发了完善此文并且发布此文的想法,期望自己的绵薄之力能够给予各位同行一些火花,共同推进国 ...

  9. WKWebView实现网页静态资源优先从本地加载

    前言:最近微信的小游戏跳一跳特别的火,顺便也让h5小游戏更加的火热.另外微信小程序,以及支付宝的小程序都是用H5写的.无论是小游戏还是小程序,这些都需要加载更多的资源文件,处理更多的业务.这些都对网页 ...

随机推荐

  1. Oracle PL/SQL Dev工具(破解版)被植入勒索病毒的安全预警及自查通告

    [问题描述] 近日,有项目组遇到了勒索软件攻击:勒索代码隐藏在Oracle PL/SQL Dev软件中(网上下载的破解版),里面的一个文件afterconnet.sql被黑客注入了病毒代码.这个代码会 ...

  2. MySQL经典错误

    本文目录: Top 1:Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行)Top 2:(主从复制报错类型)Top 3:MySQL安装过程中的报错Top 4:数 ...

  3. UltraISO制作U盘启动盘教程

    Step 1: 首先需要安装UltraISO,完成安装后打开软碟通,文件->打开,打开我们的iso镜像 安装包可以百度搜索 Step 2:然后选择我们的U盘 Step 3:然后点击启动-> ...

  4. MSDN版、OEM版、RTM版、VOL版等的区别

    我们常常听说操作系统的MSDN版.OEM版.RTM版.VOL版等等,它们到底是什么意思,有什么不同呢? (一)MSDN (Microsoft Developer Network)版MSDN软件是微软公 ...

  5. Linux 下Discuz论坛的搭建

    Discuz论坛的搭建[基于LNMP环境搭建成功后] ##创建BBS数据库在本地/远程服务器 mysql -uroot -proot create database bbs; show databas ...

  6. Git Hub 使用手册参考

    参考信息 1.http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b0002.http://ww ...

  7. iOS模拟器命令xcrun simctl系列(自动化测试)

    1. 列出安装的可用的模拟器: xcrun instruments -s [如:iPhone 5s (9.0) [00AB3BB6-C5DC-45C7-804F-6B88F57C2AFF] (Simu ...

  8. seek()和tell()在文件里转移

    Seek()方法允许在输入和输出流移动到任意的位置,seek()有好几种形式.包含:seekp() 方法和seekg()方法,p是put的意思,g是get的意思:其中输入流里用seekg()函数,输出 ...

  9. ThinkPHP5入门(三)----模型篇

    一.操作数据库 1.数据库连接配置 数据库默认的相关配置在项目的application\database.php中已经定义好. 只需要在模块的数据库配置文件中配置好当前模块需要连接的数据库的配置参数即 ...

  10. utils.js文件;一些常用方法的备份

    一些常用方法备份: function _(value) { value = '0' + value; return value.substr(value.length - 2); } Date.pro ...