刚开始接触网络爬虫,怎一个“菜”字了得!经过几次的折磨,对其原理以及其中用到的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应用的更多相关文章

  1. python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容

    python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...

  2. 【Android进阶】Gson解析json字符串的简单应用

    在客户端与服务器之间进行数据传输,一般采用两种数据格式,一种是xml,一种是json.这两种数据交换形式各有千秋,比如使用json数据格式,数据量会比较小,传输速度快,放便解析,而采用xml数据格式, ...

  3. python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容

    python3.4学习笔记(十七) 网络爬虫使用Beautifulsoup4抓取内容 Beautiful Soup 是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖 ...

  4. Android 自定义 ListView 显示网络上 JSON 格式歌曲列表

    本文内容 环境 项目结构 演示自定义 ListView 显示网络上 JSON 歌曲列表 参考资料 本文最开始看的是一个国人翻译的文章,没有源代码可下载,根据文中提供的代码片段,自己新建的项目(比较可恶 ...

  5. Android Volley 库通过网络获取 JSON 数据

    本文内容 什么是 Volley 库 Volley 能做什么 Volley 架构 环境 演示 Volley 库通过网络获取 JSON 数据 参考资料 Android 关于网络操作一般都会介绍 HttpC ...

  6. 我的Android进阶之旅------>解决Jackson等第三方转换Json的开发包在开启混淆后转换的实体类数据都是null的bug

    1.错误描述 今天测试人员提了一个bug,说使用我们的app出现了闪退的bug,后来通过debug断点调试,发现我们的app转换服务器发送过来的json数据后,都是为null.而之前已经提测快一个月的 ...

  7. Android网络爬虫程序(基于Jsoup)

    摘要:基于 Jsoup 实现一个 Android 的网络爬虫程序,抓取网页的内容并显示出来.写这个程序的主要目的是抓取海投网的宣讲会信息(公司.时间.地点)并在移动端显示,这样就可以随时随地的浏览在学 ...

  8. python网络爬虫进阶之HTTP原理,爬虫的基本原理,Cookies和代理介绍

    目录 一.HTTP基本原理 (一)URI和URL (二)超文本 (三)HTTP和HTTPS (四)HTTP请求过程 (五)请求 1.请求方法 2.请求的网址 3.请求头 4.请求体 (六)响应 1.响 ...

  9. android基于MVP小说网络爬虫、宝贝社区APP、仿虎扑钉钉应用、滑动阴影效果等源码

    Android精选源码 android宝贝社区app源码 android仿Tinder最漂亮的一个滑动效果 android仿滴滴打车开具发票页,ListView粘性Header Android基于MV ...

随机推荐

  1. jquery easyui datagrid设置行样式 不可删除某行

    rowStyler: function (index,row) { if (parseInt(row.ksrs) > 0) { return 'color:red'; } }, onLoadSu ...

  2. 博客迁移,新地址:bfsan.github.io

    博客的新内容会在新地址发布(暂时),后期可能会考虑做一个整合同步.

  3. java.sql.SQLException: **** [SQLServer]对象名 "XXXX"无效

    原因:进到数据库里面,但是没有选择数据库. 方法:检查数据源配置,这玩意容易看出.难得是多数据库操作时,切换数据源!

  4. Python中strip()、lstrip()、rstrip()用法详解

    Python中有三个去除头尾字符.空白符的函数,它们依次为: strip: 用来去除头尾字符.空白符(包括\n.\r.\t.' ',即:换行.回车.制表符.空格)lstrip:用来去除开头字符.空白符 ...

  5. Oracle中的4大空值处理函数用法举例

    nvl(exp1,exp2):                           如果exp1为空,则返回exp2:否则返回exp1nvl2(exp1,exp2,exp3):             ...

  6. 关于Application_End 与 Application_Start事件触发情况的测试(待续)

    测试项目搭建 定义一个简单的Mvc项目,有如下文件: (1) public class Startup { public void Configuration(IAppBuilder app) { a ...

  7. 用tensorlayer导入Slim模型迁移学习

    上一篇博客[用tensorflow迁移学习猫狗分类]笔者讲到用tensorlayer的[VGG16模型]迁移学习图像分类,那麽问题来了,tensorlayer没提供的模型怎么办呢?别担心,tensor ...

  8. 码农代理免费代理ip端口字段js加密破解

    起因 之前挖过爬取免费代理ip的坑,一个比较帅的同事热心发我有免费代理ip的网站,遂研究了下:https://proxy.coderbusy.com/. 解密 因为之前爬过类似的网站有了些经验,大概知 ...

  9. 谈谈Circuit Breaker在.NET Core中的简单应用

    前言 由于微服务的盛行,不少公司都将原来细粒度比较大的服务拆分成多个小的服务,让每个小服务做好自己的事即可. 经过拆分之后,就避免不了服务之间的相互调用问题!如果调用没有处理好,就有可能造成整个系统的 ...

  10. Go 语言结构

    Go Hello World 实例 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 & 表达式 注释 接下来让我们来看下简单的代码,该代码输出了"Hello ...