最近想去了解一下抢票软件的实现过程,于是开始在晚上搜集资料。通过对很多资料的的综合分析发现绝大多数都是通过httpclient来实现网络连接的。因此作为实现抢票软件的第一步,有必要详细了解一下httpclient库的相关知识。
不管是网络爬虫还是抢票软件首先需要做的就是能够获取的网页的代码,只有这样才能进行后续的查找和筛选工作。httpclient最基本的连接过程就是通过httpclient执行httpGet或者httpPost方法,等到网站返回至保存到httpResponse中,在从中提取httpEntity从而获得网页数据。
import java.io.*;
import java.util.regex.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
public class my12306Test {
public static void main(String[] args)throws Exception
{
// TODO Auto-generated method stub
connection();
}
/*
* 此方法用来实现对于网页数据的下载并存储在本地;
* 解决的问题:
* 1、连接网站下载网页前端代码;
* 2、不同网站的代码使用不同的编码方式,需要在读取时使用相应的字符编码格式;
* 3、在读取编码格式时,需要用到从网页的代码中利用正则表达式抓取charest这个编码格式属性的信息;
* */
public static void connection()throws Exception
{
//建立httpclient对象连接
HttpClient client = new DefaultHttpClient();
//使用get方法访问相关网站
HttpGet get =new HttpGet("http://www.taobao.com");
//执行get方法,获取网站响应;
HttpResponse response = client.execute(get);
//得到网站响应实体并读取信息
HttpEntity entity = response.getEntity();
InputStream input = entity.getContent();
//BasicHeader getHeader =(BasicHeader) entity.getContentEncoding();
//显示网站响应头的信息
System.out.println(response.getStatusLine().getStatusCode());
System.out.println("Response content length: " + entity.getContentLength());
System.out.println("content-type:" +entity.getContentType().getValue());
System.out.println("getMehod::"+get.getMethod());//显示请求的方法名
System.out.println("getCountry::"+response.getLocale().getDefault());//getDisplayCountry());
/*
* 1、读取网站代码,输入流信息用于getCharest函数提取字符编码信息
* 2、利用getCharest函数从网站的头或者代码中获取网站字符编码规则
* */
BufferedReader bufrBuf = new BufferedReader(new InputStreamReader(input));
BufferedWriter bufw = new BufferedWriter(new FileWriter("bufJD.html"));
String charest = getChrest(bufrBuf,entity.getContentType().getValue());
//若果得到的是UTF编码,则还需要规范其的名称
if(charest.equals("utf"))
{
System.out.println("out:"+charest);
charest="utf-8";
}
//System.out.println("out::"+charest);
//这个输入流用于读取并用于后面将其存入外部存储中,这里用到了返回的编码信息,已保证中文不会出现乱码的情况。
BufferedReader bufr =new BufferedReader(new InputStreamReader(input,charest));
String buf =null;
while((buf=bufr.readLine())!=null)
{
bufw.write(buf);
bufw.newLine();
//System.out.println(buf);
}
//bufw.close();
//bufr.close();
}
/*
* 在写入12306网站时遇到了一个问题,就是sohu等网站使用的是zh-cn方式进行编码,而12306则采用的是UTF-8作为编码方式,因此必须在写入前将指出其的编码方式。
* 目前的代码使用的还是手动在代码上进行修改,需要专门写一个函数能够自动识别网页的编码方式并返回响应的编码方式;
* */
public static String getChrest(BufferedReader bufr,String Head)throws Exception
{
BufferedWriter bufw = new BufferedWriter(new FileWriter("buf1.html"));
//如果Head代码中拥有字符编码信息,则提取出来,这样就可以提前返回,不用读取后面的entity信息。
/*
* 在head中,只有字符编码信息才有=,因此利用这个规律判断是否有字符编码信息,并且将其分割,取最后一个就是编码规则。
* */
if(Head.contains("="))
{
String[] headString=Head.split("=");
for(int i=0;i<headString.length;i++)
System.out.println("regex::"+headString[i]);
return headString[headString.length-1];
}
else
{
/*
* 如果head中没有包含编码信息,则需要在整个代码中去寻找。由于字符编码在charest属性中被标注,因此
* 1、利用正则表达式找charest来找出字符。
* 2、取出字符后,利用“=”对字符进行分割,去最后一个,从而得到字符编码规则。
* */
String buf =null;
String regx = "[c][h][a][r][s][e][t]=\\w+";
Pattern p =Pattern.compile(regx);
String charest=null;
boolean flag=false;
int row =0;
while((buf=bufr.readLine())!=null)
{
++row;
if(flag)
{
break;
}
Matcher m = p.matcher(buf);
while(m.find())
{
charest = m.group();
//System.out.println("row:"+row+charest);
flag=true;
}
bufw.write(buf);
bufw.newLine();
}
bufw.close();
//bufr.close();
//System.out.println(charest);
//用正则表达式找出charest
String charestRegex="=";
String[] chr=charest.split(charestRegex);
for(int i=0;i<chr.length;i++)
{
System.out.println(chr[i]);
}
return chr[chr.length-1];
}
}
}