刚开始接触网络爬虫,怎一个“菜”字了得!经过几次的折磨,对其原理以及其中用到的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 when() done() then()

    jQuery.when(deferreds) 参数deferreds,一个或多个延时对象或JS对象,我们初略的认为它就是一个或多个异步请求. 例如:$.when($.ajax("page1. ...

  2. c# 虚拟路径转化为物理路径

    string strPhycicsPath= Server.MapPath(path);

  3. drool-6.5的自学demo

    先丢代码地址 https://gitee.com/a247292980/drools 再丢pom.xml <project xmlns="http://maven.apache.org ...

  4. javascript装饰器模式

    装饰器模式 什么是装饰器 原名decorator 被翻译为装饰器 可以理解为装饰 修饰 包装等意 现实中的作用 一间房子通过装饰可以变得更华丽,功能更多 类似一部手机可以单独使用 但是很多人都愿意家个 ...

  5. Jupyter notebook 输出含中文的pdf 方法

    我电脑 OS 是 Ubuntu14.04, 可用的最简单方法是: 打开终端,输入 sudo find / -name article.tplx 用以查找 article.tplx 文件位置,我电脑的结 ...

  6. Ajax相关——get请求和post请求的区别

    一.完整的URL由以下几部分组成: scheme:通信协议,常用的有:http/ftp. host:主机,服务器(计算机)域名或IP地址 port:端口,整数,可选,省略时使用默认端口,http的默认 ...

  7. python中删除某个元素的3种方法

    python中关于删除list中的某个元素,一般有三种方法:remove.pop.del 1.remove: 删除单个元素,删除首个符合条件的元素,按值删除 举例说明: >>> st ...

  8. 转:linux/unix命令行终端的光标及字符控制快捷键

    from:http://linux.chinaunix.net/techdoc/system/2007/11/23/973027.shtml 在使用linux/unix的命令行终端时,有时候会碰到键盘 ...

  9. java连接sqlserver2008

    java连接sqlserver2008时应有sqljdbc4.jar驱动包.连接的示例代码如下: import java.sql.*; public class ConnectSQL { public ...

  10. Python强大的可变参数传递机制

    今天模拟定义map函数.写着写着就发现Python可变长度参数的机制真是灵活而强大. 假设有一个元组t,包含n个成员: t=(arg1,...,argn) 而一个函数f恰好能接受n个参数: f(arg ...