Android进阶(十三)网络爬虫&json应用
刚开始接触网络爬虫,怎一个“菜”字了得!经过几次的折磨,对其原理以及其中用到的json技术有了大致的了解,故作一总结,供有同样迷惑的朋友参考学习。
自己爬取的网站内容为12306的余票查询模块。利用火狐浏览器为Web开发者置的Web控制台,可得到爬取网页的请求网址,如下图所示:
其中的请求网址即为我们需要爬取的网址。另外,可得知其请求协议采用的是Https协议,采用GET方式访问。爬取源代码如下所示:
public static String queryDate = "2015-04-19"; public static String from_station = "JNK"; public static String to_station = "BJP"; public static void main(String[] args) throws Exception { HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); return true; } }; String url = "https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=" + queryDate + "&from_station=" + from_station + "&to_station=" + to_station; ProtocolUrlValidator.trustAllHttpsCertificates(); HttpsURLConnection.setDefaultHostnameVerifier(hv); String result = WebServiceUtil.invokeByHTTPGET(url, null); Gson gson = new Gson(); Trains trains = gson.fromJson(result, Trains.class); List<Item> items = trains.getData().getItems(); if (trains.getHttpstatus() != 200) { trains.getMessages(); } else { if (items != null && items.size() != 0) for (Item item : items) { System.out.println(item); } } } }
<span style="font-size:14px;">由于使用的协议为Https,故访问之前需要先进行证书的校验。其中蓝色代码块为我们需要访问的网址,涉及到的invokeByHTTPGET(url,null)代码如下所示:</span>
<span style="font-size:18px;">public class WebServiceUtil { /** * 通过SOAP1.1协议调用Web服务 * * @param wsdl WSDL路径 * @param method 方法名 * @param namespace 命名空间 * @param headerParameters 头参数 * @param bodyParameters 体参数 * @param isBodyParametersNS 体参数是否有命名空间 * @return String * @throws Exception */ public static String invokeBySoap11(String wsdl, String method, String namespace, Map<String, String> headerParameters, Map<String, String> bodyParameters, boolean isBodyParametersNS) throws Exception { StringBuffer soapOfResult = null; // 去除 ?wsdl,获取方法列表 int length = wsdl.length(); wsdl = wsdl.substring(0, length - 5); URL url = new URL(wsdl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8"); OutputStream out = conn.getOutputStream(); // 获取soap1.1版本消息 StringBuilder sb = new StringBuilder(); sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "); sb.append("xmlns:ns0=\"" + namespace + "\""); sb.append(">"); if (headerParameters != null) { sb.append("<soap:Header>"); for (Entry<String, String> headerParameter : headerParameters .entrySet()) { sb.append("<ns0:"); sb.append(headerParameter.getKey()); sb.append(">"); sb.append(headerParameter.getValue()); sb.append("</ns0:"); sb.append(headerParameter.getKey()); sb.append(">"); } sb.append("</soap:Header>"); } sb.append("<soap:Body><ns0:"); sb.append(method); sb.append(">"); // 输入参数 if (bodyParameters != null) { for (Entry<String, String> inputParameter : bodyParameters .entrySet()) { if (isBodyParametersNS) { sb.append("<ns0:"); sb.append(inputParameter.getKey()); sb.append(">"); sb.append(inputParameter.getValue()); sb.append("</ns0:"); sb.append(inputParameter.getKey()); sb.append(">"); } else { sb.append("<"); sb.append(inputParameter.getKey()); sb.append(">"); sb.append(inputParameter.getValue()); sb.append("</"); sb.append(inputParameter.getKey()); sb.append(">"); } } } sb.append("</ns0:"); sb.append(method); sb.append("></soap:Body></soap:Envelope>"); //System.out.println(sb.toString()); out.write(sb.toString().getBytes()); int code = conn.getResponseCode(); if (code == 200) { InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; soapOfResult = new StringBuffer(); while ((len = is.read(b)) != -1) { String s = new String(b, 0, len, "UTF-8"); soapOfResult.append(s); } } conn.disconnect(); return soapOfResult == null ? null : soapOfResult.toString(); } /** * 通过SOAP1.2协议调用Web服务 * * @param wsdl * @param method * @param namespace * @param headerParameters * @param bodyParameters * @param isBodyParametersNS * @return * @throws Exception */ public static String invokeBySoap12(String wsdl, String method, String namespace, Map<String, String> headerParameters, Map<String, String> bodyParameters, boolean isBodyParametersNS) throws Exception { StringBuffer soapOfResult = null; // 去除 ?wsdl int length = wsdl.length(); wsdl = wsdl.substring(0, length - 5); URL url = new URL(wsdl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8"); OutputStream out = conn.getOutputStream(); // 获取soap1.1版本消息 StringBuilder sb = new StringBuilder(); sb.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "); sb.append("xmlns:ns0=\"" + namespace + "\""); sb.append(">"); if (headerParameters != null) { sb.append("<soap12:Header>"); for (Entry<String, String> headerParameter : headerParameters .entrySet()) { sb.append("<ns0:"); sb.append(headerParameter.getKey()); sb.append(">"); sb.append(headerParameter.getValue()); sb.append("</ns0:"); sb.append(headerParameter.getKey()); sb.append(">"); } sb.append("</soap12:Header>"); } sb.append("<soap12:Body><ns0:"); sb.append(method); sb.append(">"); // 输入参数 if (bodyParameters != null) { for (Entry<String, String> inputParameter : bodyParameters .entrySet()) { if (isBodyParametersNS) { sb.append("<ns0:"); sb.append(inputParameter.getKey()); sb.append(">"); sb.append(inputParameter.getValue()); sb.append("</ns0:"); sb.append(inputParameter.getKey()); sb.append(">"); } else { sb.append("<"); sb.append(inputParameter.getKey()); sb.append(">"); sb.append(inputParameter.getValue()); sb.append("</"); sb.append(inputParameter.getKey()); sb.append(">"); } } } sb.append("</ns0:"); sb.append(method); sb.append("></soap12:Body></soap12:Envelope>"); System.out.println(sb.toString()); out.write(sb.toString().getBytes()); int code = conn.getResponseCode(); if (code == 200) { InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; soapOfResult = new StringBuffer(); while ((len = is.read(b)) != -1) { String s = new String(b, 0, len, "UTF-8"); soapOfResult.append(s); } } conn.disconnect(); return soapOfResult == null ? null : soapOfResult.toString(); } /** * 通过HTTP POST传参方式调用服务 * * @param urlPath * @param method * @param namespace * @param inputParameters * @return * @throws Exception */ public static String invokeByHTTPPOST(String urlPath, Map<String, String> inputParameters) throws Exception { StringBuffer resultStr = null; URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); // 输入参数 if (inputParameters != null) { for (Entry<String, String> inputParameter : inputParameters .entrySet()) { sb.append(inputParameter.getKey()); sb.append("="); sb.append(inputParameter.getValue()); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); } System.out.println(sb.toString()); OutputStream out = conn.getOutputStream(); out.write(sb.toString().getBytes()); int code = conn.getResponseCode(); if (code == 200) { InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; resultStr = new StringBuffer(); while ((len = is.read(b)) != -1) { String s = new String(b, 0, len, "UTF-8"); resultStr.append(s); } } conn.disconnect(); return resultStr == null ? null : resultStr.toString(); } /** * 通过HTTP GET传参方式调用服务 * * @param urlPath url路径 * @param method 方法名 * @param namespace 命名空间 * @param inputParameters 输入参数 * @return String * @throws Exception */ public static String invokeByHTTPGET(String urlPath, Map<String, String> inputParameters) throws Exception { StringBuilder sb = new StringBuilder(); sb.append(urlPath); // GET参数 if (inputParameters != null) { sb.append("?"); //entrySet()方法 返回此映射中包含的映射关系的 set 视图集合 //Map.Entry表示单个映射关系即一个key+value for (Entry<String, String> inputParameter : inputParameters .entrySet()) { sb.append(inputParameter.getKey()); sb.append("="); sb.append(inputParameter.getValue()); sb.append("&"); } //作用:去除最后一个拼接的'&'字符 sb.deleteCharAt(sb.length() - 1); } System.out.println(sb.toString()); URL url = new URL(sb.toString()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setDoOutput(true); int code = conn.getResponseCode(); StringBuffer resultString = null; if (code == 200) { InputStream is = conn.getInputStream(); byte[] b = new byte[4096]; int len = 0; resultString = new StringBuffer(); while ((len = is.read(b)) != -1) { String s = new String(b, 0, len, "UTF-8"); //System.out.println(len+">>>>"+s); resultString.append(s); } } conn.disconnect(); return resultString == null ? null : resultString.toString(); }</span>
以上代码块涉及到的发送请求方式有通过SOAP1.1协议调用Web服务、通过SOAP1.2协议调用Web服务、
通过HTTP POST传参方式调用服务和通过HTTP GET传参方式调用服务。其具体的请求方式在源代码中以注释方式以详细给出,故此处不再赘述。
在爬取过程中,我们还需要用到json在线校验工具,网址为:点击打开链接。主要利用此工具完成的操作为:验证json格式的正确性,根据json串生成相应的POJO类。如下图所示:
json格式校验
生成POJO类
<span style="font-size:18px;">至此,网络爬虫的过程基本结束。此次实验的返回结果如下图所示:</span>
注:自己对GSon解析json还存在一定的误区。对于json串中的Key,其实是与相应类中的变量名一一对应的,否则,在解析式将会是null!例如,
以上的json串中存在key为data,则在创建POJO时,不可随意更变变量名,若将private List<Item> datas;改写为private List<Item> items;则会使变List<Item> items = trains.getData().getItems();返回null。若自己需要更改变量名的话,可以采用注解的方式解决,例如@SerializedName("datas")private List<Item> items;
Android进阶(十三)网络爬虫&json应用的更多相关文章
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
- 【Android进阶】Gson解析json字符串的简单应用
在客户端与服务器之间进行数据传输,一般采用两种数据格式,一种是xml,一种是json.这两种数据交换形式各有千秋,比如使用json数据格式,数据量会比较小,传输速度快,放便解析,而采用xml数据格式, ...
- python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容
python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容 Beautiful Soup 是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖 ...
- Android 自定义 ListView 显示网络上 JSON 格式歌曲列表
本文内容 环境 项目结构 演示自定义 ListView 显示网络上 JSON 歌曲列表 参考资料 本文最开始看的是一个国人翻译的文章,没有源代码可下载,根据文中提供的代码片段,自己新建的项目(比较可恶 ...
- Android Volley 库通过网络获取 JSON 数据
本文内容 什么是 Volley 库 Volley 能做什么 Volley 架构 环境 演示 Volley 库通过网络获取 JSON 数据 参考资料 Android 关于网络操作一般都会介绍 HttpC ...
- 我的Android进阶之旅------>解决Jackson等第三方转换Json的开发包在开启混淆后转换的实体类数据都是null的bug
1.错误描述 今天测试人员提了一个bug,说使用我们的app出现了闪退的bug,后来通过debug断点调试,发现我们的app转换服务器发送过来的json数据后,都是为null.而之前已经提测快一个月的 ...
- Android网络爬虫程序(基于Jsoup)
摘要:基于 Jsoup 实现一个 Android 的网络爬虫程序,抓取网页的内容并显示出来.写这个程序的主要目的是抓取海投网的宣讲会信息(公司.时间.地点)并在移动端显示,这样就可以随时随地的浏览在学 ...
- python网络爬虫进阶之HTTP原理,爬虫的基本原理,Cookies和代理介绍
目录 一.HTTP基本原理 (一)URI和URL (二)超文本 (三)HTTP和HTTPS (四)HTTP请求过程 (五)请求 1.请求方法 2.请求的网址 3.请求头 4.请求体 (六)响应 1.响 ...
- android基于MVP小说网络爬虫、宝贝社区APP、仿虎扑钉钉应用、滑动阴影效果等源码
Android精选源码 android宝贝社区app源码 android仿Tinder最漂亮的一个滑动效果 android仿滴滴打车开具发票页,ListView粘性Header Android基于MV ...
随机推荐
- python中decode
这 是因为遇到了非法字符--尤其是在某些用C/C++编写的程序中,全角空格往往有多种不同的实现方式,比如\xa3\xa0,或者\xa4\x57,这些 字符,看起来都是全角空格,但它们并不是" ...
- 阿里技术一面,Java研发岗
之前过了个简单的简历面,过了几天后没打来以为凉了,然后昨晚又接到了电话,括号内容是回答说的,理解有限,不一定都对,欢迎纠正-加油每一个牛友们! 阿里一面: 1.学过哪些技术知识呢? 2.说说接口和抽象 ...
- lgp20151222 java中如何将Object类型转换为int类型
if (object instanceof Integer) { Integer.parseInt(object.toString()); } 很简单是不是?我就想提醒下自己,java有个特殊词 ...
- URLconnection
URLconnection 开发中最常用的两种网络请求: 1.标准Java接口(java.NET) --HttpURLConnection,可以实现简单的基于URL请求.响应功能: 2.Apache ...
- mongo索引
索引自动创建和手工创建 db.stu.drop(); db.stu.insert({"name":"张三","sex":"男&qu ...
- React-报错Warning:setState(...)on anunmounted component
一.原因 这种错误一般出现在react组件已经从DOM中移除.我们在react组件中发送一些异步请求的时候,就可能会出现这样的问题.举个例子,我们在componentWillMount中 ...
- 009.Working with SQL Server LocalDB --【在sql server localdb 上操作数据】
Working with SQL Server LocalDB 在sql server localdb 上操作数据 2017-3-7 2 分钟阅读时长 本文内容 1.SQL Server Expres ...
- Win10 下Cmake编译配置 Opencv3.1 + Cuda7.5 + VS2013
折腾了三天终于配置成功了,在此写下编译配置的全部步骤和遇到的很多坑. 整体介绍: OpenCV 中 CUDA 实现的函数还不是太多,使用前要在OpenCV的官网上确认以下你想要的功能是否已经实现,否则 ...
- MySQL 数学函数
MySQL 数学函数 所有的数学函数在发生错误的情况下,均返回 NULL. -元减.改变参数的符号 mysql> SELECT - 2; -> -2 注意,如果这个操作符被用于一个 BIG ...
- Java对象的访问定位
java对象在访问的时候,我们需要通过java虚拟机栈的reference类型的数据去操作具体的对象.由于reference类型在java虚拟机规范中只规定了一个对象的引用,并没有定义这个这个引用应该 ...