揭开邮电局EMS快递单查询原理

揭开邮局EMS快递单查询原理
     现在都是流行网上购物了,大家一定关心自己购买东西快递现在已经发到什么地方了,现在想查一查。当然现在有很多提供这种服务,我今天就给大家实现一个无需打开浏览器就可以实现EMS快递查询,简单讲述其原理。以下是我简单画的流程图(随便用office画,很山賽,哈哈):好了,我们开始源码吧:

(1)EMS网站

揭开邮电局EMS快递单查询原理
(2)流程图

揭开邮电局EMS快递单查询原理

(3)结果图:
揭开邮电局EMS快递单查询原理

揭开邮电局EMS快递单查询原理


/**
* 查询EMS快递状态
* @author  luodongfu

*  我把我实现的代码全部贴出来,哈哈。
*/

public class GetEms
{
public static void main(String[] args)
{

//我这里使用WebClient 来抓去
  WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_7);
  webClient.setActiveXNative(true);
  webClient.setJavaScriptEnabled(true);
  HtmlPage loginPage = null;
  try
  {

//打开ems邮局网站
   loginPage = webClient
     .getPage("http://www.ems.com.cn/qcgzOutQueryAction.do?reqCode=gotoSearch");
  } catch (Exception e1)
  {
   e1.printStackTrace();
  }
  if (loginPage == null)
  {
   return;
  }



//找到查询页面的表单以及其中的
  HtmlForm loginForm = loginPage.getFormByName("form1");

//找到快递单输入框
  HtmlTextInput mailNum = loginForm.getInputByName("mailNum");

//找到快递单验证码输入框,这个ems很狡诈,每天这个F346F82440A3AAC78473802都会变,

所以最好加一个判断如果出错的话就直接抓去页面这个值。我这里就写死了,呵呵
  HtmlTextInput codestr = loginForm.getInputByName("F346F82440A3AAC78473802");
  HtmlImage p = null;



//找到验证码图片
  DomNodeList<HtmlElement> ps = loginPage.getElementsByTagName("img");
  boolean success = false;
  File f = null;

//遍历查询图片,如果找到该图片则保存到D盘111.png文件
  for (HtmlElement ht : ps)
  {
   if (ht instanceof HtmlImage)
   {
    HtmlImage img = (HtmlImage) ht;
    String alt = img.getAltAttribute();
    if (alt != null && alt.contains("不清?点击换图"))
    {
     f = new File("D:\\111.png");
     if (f.isFile() && f.exists())
     {
      f.delete();
     }



//保存图片
     try
     {
      img.saveAs(f);
      success = true;
     } catch (Exception e)
     {
      e.printStackTrace();
     }
     System.out.println("识别码图片文件写入磁盘OK");
     if (success)
     {
      break;
     }
    }
   }
  }



//如果图片保存成功,则弹出图片显示

  if (success)
  {
   try
   {
    Runtime.getRuntime().exec(
      "cmd.exe   /c   start   " + f.getCanonicalPath());
   } catch (IOException e2)
   {
    e2.printStackTrace();
   }



//提示输入验证码

   BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
   String str = null;
   System.out.println("请将你看到的识别码输入:");
   try
   {
    str = br.readLine();
   } catch (IOException e)
   {
    e.printStackTrace();
   }
   if (str != null && !str.trim().equals(""))
   {
    str = str.trim();
    codestr.setValueAttribute(str);



//这里是邮局EMS快递单,我这里写死,你可以做一个提示用户输入
    mailNum.setValueAttribute("EF706866075CS");




    System.out.println("你输入的识别码是:" + str);
    HtmlImageInput button = (HtmlImageInput) loginForm.getInputByName("optijiaot");
    try
    {
     Page rsp = button.click();//模拟用户点击提交数据
     if (rsp instanceof HtmlPage)
     {
      loginPage = (HtmlPage) rsp;
      success = true;
     }
    } catch (Exception e)
    {
     success = false;
     e.printStackTrace();
    }

//如果查询成功,则开始解析结果
    if (success)
    {

//解析返回的结果,ems这个表格table 做的很垃圾,一个table 里面包含一个table 很多,而且table.

// id 一个都没有,他娘的什么鸟人编html的程序。这里我解析部分省略了,呵呵
     parseTable(loginPage.asXml());
   
  }

}









//删除空格

public static String replaceBlank(String tt)
{
    Pattern p = Pattern.compile("\\s*|\t|\r|\n");
    Matcher m = p.matcher(tt);
    if(m.find())
    {
     String after = m.replaceAll("");
     return after;
    }
    return null;

}
}




好了结果出来了:



识别码图片文件写入磁盘OK
请将你看到的识别码输入:
R72C
你输入的识别码是:R72C


    2010-05-06   10:11:34   武义县    到达处理中心,来自武义县邮政局速递公司  
    2010-05-06   12:15:48   武义县    离开处理中心,发往金华市邮政局分拣*  
    2010-05-06   13:57:36   金华市    到达处理中心,来自武义县  
    2010-05-06   18:55:07   金华市    离开处理中心,发往北京市  
    2010-05-10   12:57:15   北京邮政陆路速递邮件处理中心    到达处理中心,来自金华市  
    2010-05-10   16:54:08   北京邮政陆路速递邮件处理中心    离开处理中心,发往北京邮政速递世纪城分公司香山营投部  
    2010-05-11   07:15:35   北京邮政速递世纪城分公司香山营投部    到达处理中心,来自北京市  
    2010-05-11   07:45:59   北京邮政速递世纪城分公司香山营投部    安排投递  
    2010-05-11   09:20:00   北京邮政速递世纪城分公司香山营投部    妥投  
您的邮件于2010-05-11 09:20:00(北京邮政速递世纪城分公司香山营投部)已妥投投递结果:董波代收




最后注意以下的F346F82440A3AAC78473802东东:

最好从其页面抓去,不然为出错,哈哈。我懒,所以我就写死了。

HtmlTextInput codestr = loginForm.getInputByName("F346F82440A3AAC78473802");
1 楼 zl4393753 2011-09-18  
“验证码输入框动态名称”的问题我也找了好久。。。本来不愿意抓取查询页面,然后解析的。。。可惜现在貌似没有办法了。。
2 楼 max_dong 2012-05-26  
这是可是公司的机密啊,怎么可以随便发出来呢!