了解到已经有大佬们整理和制作了同行程的查询网站,能够帮助到更多人解决问题,这里感谢一下这些无私奉献的大佬们。我这里的爬取并没有恶意的意思,正如我提到的,我是希望能够将多个平台的功能整理出API,然后能够让更多人整合这么多个平台的功能,然后再次整合成网站甚至制作成小程序,虽然我也会做小程序。
爬取的地址:http://2019ncov.nosugartech.com/search.html 或者 http://2019ncov.nosugartech.com
抓包可以利用抓包工具或者直接浏览器F12看请求数据 ,这里我就直接省略跳过去了,想了解的可以自己搜索教程,我用的抓包工具是fiddler。
请求地址:http://2019ncov.nosugartech.com/search.html
这里发现当我请求这个页面的抓包数据如图所示,我们可以清楚的看到请求的url有这些,我们可以猜测到这个网站的前端是用了Layui框架,然后所有的数据在一个data.json里面,然后我试着输入日期和车次搜索了一下,发现没有新的请求,所以可以猜测到数据应该没有和数据库交互,数据都是放在data.json文件里面,然后页面的展示表格和搜索展示是用了layui的表格组件,这样可以保证搜索的人即使再多,也不会出现崩溃,关于网站的架构模式这篇文章不是重点,我也就不继续分析和猜测了。
这样也降低了我们的爬取难度,我们只要直接请求这个http://2019ncov.nosugartech.com/data.json?439072文件就可以拿到所有的数据了,然后不管你是每次都请求这个data.json,还是将数据入库或redis缓存里,然后每隔一定时间请求一次data.json都可以,看你想怎么弄。(这次感谢这些大佬们默默的整理这些数据,整理数据是繁琐的,但也是重中之重)
很多人会问这个问号后面的439072是什么东东,我们直接查看源代码,可以看到这个只是一个防止浏览器有缓存的一个版本号,
/**
* 新型冠状病毒肺炎确诊患者同行程查询工具
* @return
*/
public static String getSameTripData(){
String url="http://2019ncov.nosugartech.com/data.json?"+Math.floor(new Date().getTime()/1000/3600);
//模拟请求
HttpPojo httpPojo = new HttpPojo();
httpPojo.setHttpHost("2019ncov.nosugartech.com");
httpPojo.setHttpAccept("application/json, text/javascript, */*; q=0.01");
httpPojo.setHttpConnection("keep-alive");
httpPojo.setHttpUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
httpPojo.setHttpReferer("http://2019ncov.nosugartech.com/search.html");
httpPojo.setHttpOrigin("http://2019ncov.nosugartech.com/search.html");
Map paramObj = new HashMap();
String htmlResult = httpSendGet(url, paramObj, httpPojo); //整个html页面
System.out.println(htmlResult);
//遍历入库或者存redis等操作
/*JSONObject dataJo = JSONObject.parseObject(htmlResult);
String data = dataJo.getString("data");//拿到所有数据
JSONArray array = JSONArray.parseArray(data);
for (int i = 0; i < array.size(); i++) {
JSONObject tripJo = JSONObject.parseObject(array.getString(i));
String t_no = tripJo.getString("t_no");
System.out.println("t_no:"+t_no);
//入库操作
}*/
return htmlResult;
}
运行效果:可以自行复制打印出来的结果在 在线json格式化网站解析一下看看:http://www.bejson.com/count.html
数据就不复制出来了,因为数据实在是太多,csdn博客会提示字数太多,发布不了,所以大家自己运行获取结果哈
{
"id": 946,
"t_date": "2020-01-28",
"t_start": "2020/01/28 13:30:00",
"t_end": "2020/01/28 23:59:59",
"t_type": 5,
"t_no": "淮北市1路公交车",
"t_memo": "1月31日确诊",
"t_no_sub": "",
"t_pos_start": "淮北淮海路",
"t_pos_end": "淮北市人民医院",
"source": "http://wjw.huaibei.gov.cn/xxfb/tzgg/55971291.html",
"who": "淮北市卫生健康委员会",
"verified": 1,
"created_at": "2020/02/02 21:19:11",
"updated_at": "2020/02/02 21:35:21"
}, {
"id": 855,
"t_date": "2020-01-27",
"t_start": "2020/01/27 00:00:00",
"t_end": "2020/01/27 23:59:59",
"t_type": 1,
"t_no": "JD5859",
"t_memo": "",
"t_no_sub": "",
"t_pos_start": "北京",
"t_pos_end": "南昌",
"source": "https://mp.weixin.qq.com/s/HYcnAc-G5GpgEGFJSPsZBg",
"who": "人民日报",
"verified": 1,
"created_at": "2020/02/01 20:30:19",
"updated_at": "2020/02/01 21:41:15"
}
t_type 表示交通工具、交通类型
t_type == 1 飞机
t_type == 2 火车
t_type == 3 地铁
t_type == 4 长途客车/大巴
t_type == 5 公交车
t_type == 6 出租车
t_type == 7 轮船
t_type == 8 其它公共场所
't_type': '交通类型'
't_date': '日期'
't_no': '车次/车牌/航班号/场所名称'
't_no_sub': '车厢'
't_pos_start': '出发站'
't_pos_end': '到达站'
't_memo': '车次附加描述'
't_start': '开始时间'
't_end': '结束时间'
'source': '线索来源'
'created_at': '提交时间'
'remark': '事件备注'
至此,同行程查询工具的数据已经爬取完毕了,如何搜索,一定要将数据存库或者放redis缓存中,然后写一个查询接口,就可以进行搜索时间+车次+地区的功能了,
下面放一下爬取要用到的工具类和完整代码
用到的工具类,请戳链接:https://blog.csdn.net/qq_27471405/article/details/104140618
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.common.apiV2.beans.HttpPojo;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by yjl on 2020-02-01.
*/
@Service("WuhanService")
public class WuhanService {
public static void main(String[] args) {
getSameTripData();
}
/**
* 新型冠状病毒肺炎确诊患者同行程查询工具
* @return
*/
public static String getSameTripData(){
String url="http://2019ncov.nosugartech.com/data.json?"+Math.floor(new Date().getTime()/1000/3600);
//模拟请求
HttpPojo httpPojo = new HttpPojo();
httpPojo.setHttpHost("2019ncov.nosugartech.com");
httpPojo.setHttpAccept("application/json, text/javascript, */*; q=0.01");
httpPojo.setHttpConnection("keep-alive");
httpPojo.setHttpUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
httpPojo.setHttpReferer("http://2019ncov.nosugartech.com/search.html");
httpPojo.setHttpOrigin("http://2019ncov.nosugartech.com/search.html");
Map paramObj = new HashMap();
String htmlResult = httpSendGet(url, paramObj, httpPojo); //整个html页面
System.out.println(htmlResult);
//遍历入库或者存redis等操作
/*JSONObject dataJo = JSONObject.parseObject(htmlResult);
String data = dataJo.getString("data");//拿到所有数据
JSONArray array = JSONArray.parseArray(data);
for (int i = 0; i < array.size(); i++) {
JSONObject tripJo = JSONObject.parseObject(array.getString(i));
String t_no = tripJo.getString("t_no");
System.out.println("t_no:"+t_no);
//入库操作
}*/
return htmlResult;
}
/**
* http请求
* @param url
* @param paramObj
* @param httpPojo
* @return
*/
private static String httpSendGet(String url, Map paramObj, HttpPojo httpPojo){
String result = "";
String urlName = url + "?" + parseParam(paramObj);
BufferedReader in=null;
try {
URL realURL = new URL(urlName);
URLConnection conn = realURL.openConnection();
//伪造ip访问
String ip = randIP();
System.out.println("目前伪造的ip:"+ip);
conn.setRequestProperty("X-Forwarded-For", ip);
conn.setRequestProperty("HTTP_X_FORWARDED_FOR", ip);
conn.setRequestProperty("HTTP_CLIENT_IP", ip);
conn.setRequestProperty("REMOTE_ADDR", ip);
conn.setRequestProperty("Host", httpPojo.getHttpHost());
conn.setRequestProperty("accept", httpPojo.getHttpAccept());
conn.setRequestProperty("connection", httpPojo.getHttpConnection());
conn.setRequestProperty("user-agent", httpPojo.getHttpUserAgent());
conn.setRequestProperty("Referer",httpPojo.getHttpReferer()); //伪造访问来源
conn.setRequestProperty("Origin", httpPojo.getHttpOrigin()); //伪造访问域名
conn.connect();
Map<String, List<String>> map = conn.getHeaderFields();
for (String s : map.keySet()) {
//System.out.println(s + "-->" + map.get(s));
}
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += "\n" + line;
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (in!=null){
try {
in.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
return result;
}
/**
* 解析map
* @param paramObj
* @return
*/
public static String parseParam(Map paramObj){
String param="";
if (paramObj!=null&&!paramObj.isEmpty()){
for (Object key:paramObj.keySet()){
String value = paramObj.get(key).toString();
param+=(key+"="+value+"&");
}
}
return param;
}
/**
* 伪造ip地址
* @return
*/
public static String randIP() {
Random random = new Random(System.currentTimeMillis());
return (random.nextInt(255) + 1) + "." + (random.nextInt(255) + 1)
+ "." + (random.nextInt(255) + 1) + "."
+ (random.nextInt(255) + 1);
}
}