需求介绍:

爬取指定地点的所有全国相关的列车班次详情。将结果写进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. 如何解决MSSQL中文数据乱码问题

    今天遇到了在数据库中直接写SQL语句,语句中包含中文,但是数据库的表里是包含“?” 的乱码. 我程序代码中,调试时得到的SQL不是乱码,在控制台中也不是乱码.但是在数据库中却出现了乱码. 当用MSSQ ...

  2. oralce的判断语句

    大家对 IF ELSE 语句应该都很熟悉吧,它是用来对过程进行控制的.在 SQL 的世界中 CASE 语句有类似的效果.下面简单的介绍 CASE 语句的用法. CASE 语句的形式 事实上,CASE ...

  3. [翻译] ABPadLockScreen

    ABPadLockScreen ABPadLockScreen aims to provide a universal solution to providing a secure keypad/pi ...

  4. spider-抓取网页内容

    使用urllib2抓取网页内容: import urllib2 from HTMLParser import HTMLParser request = urllib2.Request('http:// ...

  5. Java学习---面向对象的远程方法调用[RMI]

    基础知识 分布式计算是一门计算机科学,它研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分,然后把这些部分分配给许多计算机进行处理,最后把这些计算结果综合起来得到最终的结果. 常见的分 ...

  6. SharePoint问题杂集——要创建计时器作业,必须运行SVC

    问题场景:在SharePoint2010服务器上使用PowerShell部署解决方案时,遇到问题: 解决办法是进入控制面板----管理工具----服务,找到SharePoint 2010 Admini ...

  7. php中的static

    静态成员是一种类变量,可以把它看成时属于整个类而不是属于类的某个实例.与一般的实例变量不同的是,静态成员只保留一个变量值,而这个变量值对所有的实例都是有效的,也就是说,所有的实例共享这个成员. $th ...

  8. 做 fzu oj 1003 简单的枚举

    暴力求解法---简单枚举 定义一个函数(函数的内容大概是包含了题目所给的限制条件),然后主函数就是通过循环进行枚举,枚举出可能的元素,带入函数中进行验证,如果符合函数所给的情况,则为其解.

  9. Web App, Native APP,Hybird App 介绍

    一.Web App 这个主要是采用统一的标准的 HTML,JavaScript.CSS 等 web 技术开发. 用户无需下载,通过不同平台 的浏览器访问来实现跨平台, 同时可以通过浏览器支持充分使用 ...

  10. cogs [HZOI 2015]有标号的二分图计数

    题目分析 n个点的二分染色图计数 很显然的一个式子 \[ \sum_{i=0}^n\binom{n}{i}2^{i(n-i)} \] 很容易把\(2^{i(n-i)}\)拆成卷积形式,前面讲过,不再赘 ...