`
gzhzh
  • 浏览: 25083 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

利用HttpURLConnection进行手机号段归属地数据采集

阅读更多

  公司里需要手机号段归属地资料,手头上没有现成的数据,就自己做了个采集器,连到ip138.com网站上进行采集。这是最终运行界面:

 

 

 

 

  首先在网页上输入至少7位的手机号码段进行查询,通过查看查询页面的HTML,发现将会提交两个参数:mobile=手机号码&action=mobile,然后对结果页面的HTML进行分析,找到关键的两行HTML:

<TD width="130" align="center" noswap>卡号归属地</TD>
<TD width=* align="center" class=tdc2>广东&nbsp;广州</TD>

接下来的事情就是利用HttpURLConnection进行查询请求,并将返回的结果用正则表达式进行提取。程序的功能并不复杂,设计上也就简单地做了两个类,一个负责数据的分析和采集;另一个为Main主程序,负责用AWT构建界面和创建一个后台线程来调用采集类进行手机号段范围的循环提交请求,并将获取的数据写入文本文件。

package com.funper.collector;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * 分析和采集数据
 *
 */
public class CollectAction {
	
	//请求URL
	private static final String REQUEST_URL="http://www.ip138.com:8080/search.asp";
	//请求方法
	private static final String REQUEST_MOTHOD="POST";
	//提取手机号码归属地的正则表达式
	private static final String REGEX_EXP="^<TD width=\\* align=\"center\" class=tdc2>(.*)</TD>$";
	//编译后的正则表达式Pattern对象
	private static final Pattern p=Pattern.compile(REGEX_EXP);
	//连接URL的HttpURLConnection对象
	private HttpURLConnection httpConn=null;
	
	/**
	 * 获取手机号码归属地
	 * @param requestParameter 提交参数
	 * @return String
	 */
	public String getMobileArea(String requestParameter)
	{
		String mobileArea="";
		BufferedReader br=null;
		try
		{
			httpConn=(HttpURLConnection)new URL(REQUEST_URL).openConnection();
			httpConn.setRequestMethod(REQUEST_MOTHOD);
			httpConn.setDoOutput(true);
			httpConn.getOutputStream().write(requestParameter.getBytes());
			httpConn.getOutputStream().flush();
			httpConn.getOutputStream().close();
			
			br=new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
			String lineStr=null;
			while((lineStr=br.readLine())!=null)
			{
				if("<TD width=\"130\" align=\"center\" noswap>卡号归属地</TD>".equals(lineStr.trim()))
				{
					lineStr=br.readLine().trim();
					Matcher m=p.matcher(lineStr);
					if(m.matches())
					{
						mobileArea=m.group(1);
						break;
					}
				}
			}
		}
		catch(IOException e) {
			e.printStackTrace();
		}
		finally
		{
			if(br!=null)
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return mobileArea;
	}
}

 

  主程序在构建界面时代码冗长,只贴执行操作的后台线程内部类代码:

	class ProcessorThread extends Thread
	{
		private boolean runMark=true;
		private BufferedWriter bw=null;
		@Override
		public void run() {
			try {
				bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(savePlaceLabel.getText().substring(5))));
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
			int sNumber=Integer.parseInt(startNumberField.getText());
			int eNumber=Integer.parseInt(endNumberField.getText());
			int readCount=0;
			int writeCount=0;
			CollectAction action=new CollectAction();
			for(;sNumber<=eNumber;sNumber++)
			{
				if(runMark)
				{
					try {
						sleep(300);//每请求一次就短暂睡眠一下,主要是担心请求过于频繁对网站服务器造成影响
					} catch (InterruptedException e) {
						e.printStackTrace();
						showErrorMessage(e.getMessage());
					}
					String area=null;
					try
					{
						area=action.getMobileArea("mobile="+sNumber+"&action=mobile");
						if(area!=null)
						{
							area=area.replaceAll("&nbsp;", " ");
						}
						msgLabel.setText("正在分析号段:"+sNumber+"==" + area);
						//System.out.println(area);
						dataCountLabel.setText(String.valueOf(++readCount));
						bw.write(""+sNumber+","+area);
						bw.write(new char[]{'\r', '\n'});
						bw.flush();
						writeCountLabel.setText(String.valueOf(++writeCount));
					}
					catch(IOException e)
					{
						e.printStackTrace();
						showErrorMessage(e.getMessage());
					}
				}
				else
				{
					--sNumber;
					synchronized(this) {
						try {
							wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
							showErrorMessage(e.getMessage());
						}
					}
				}
			}
			try {
				bw.flush();
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
				showErrorMessage(e.getMessage());
			}
			JOptionPane.showMessageDialog(frame, "采集完毕!", "提示", JOptionPane.INFORMATION_MESSAGE);
		}
		
		public synchronized void stopThread()
		{
			runMark=false;
		}
		
		public synchronized void startThread()
		{
			runMark=true;
			notify();
		}
		
		public boolean getRunMark()
		{
			return runMark;
		}

		//------------------
		
		public void showErrorMessage(String msg)
		{
			JOptionPane.showMessageDialog(frame, msg, "错误", JOptionPane.ERROR_MESSAGE);
		}
	}

 

  OK,现在我的程序正采集着数据,很快就可以交差了:)

4
2
分享到:
评论
8 楼 wy8232255 2012-09-18  
您好,楼主您好,我现在正需要这样的实例程序来完成公司的项目需求,能否把您的代码发到我的邮箱里,我的邮箱是:hashsound@126.com ,吾将感激不尽啊.....
7 楼 gzhzh 2009-07-16  
playfish 写道

楼主做得应该还算不错的哈。。不过我觉得用上httpclient来代替原生的httpurlconnection比较好,封装得比较完全,使用也比较简单。

至于解析,如果懂得正则表达式,那就完美了.不然可以考虑下一些html解析器,Jericho,html parser之类的。

谢谢指教!呵呵,其实做这个东东只是想一次性地获取数据并交差而已,界面甚至是多余的,HTMLParser用在这里也是杀鸡用牛刀了。功能完全是按公司的需求来做的,并没有做成常用工具的需求,如果有那个需求的话,我考虑的就会更全面了。
6 楼 playfish 2009-07-15  

楼主做得应该还算不错的哈。。不过我觉得用上httpclient来代替原生的httpurlconnection比较好,封装得比较完全,使用也比较简单。

至于解析,如果懂得正则表达式,那就完美了.不然可以考虑下一些html解析器,Jericho,html parser之类的。

引用
写的代码死板板的,如果人家把页面改成DIV的,不用table了,你岂不要是修改源码?


呵呵,这种情况第一,不多,第二,碰上了的话,无论如何是不可避免要改代码的。

PS:这种类型的东西我做得好多了。。熟练着。。
5 楼 gzhzh 2009-07-15  
yajie 写道
用动态代理
另外你写的代码死板板的,如果人家把页面改成DIV的,不用table了,你岂不要是修改源码?

谢谢指教!你说说如何能不修改源码就可以适应人家页面的修改?在网页还没使用XML和遵照制定好的标准之前,没人做得到吧?
4 楼 yajie 2009-07-15  
用动态代理
另外你写的代码死板板的,如果人家把页面改成DIV的,不用table了,你岂不要是修改源码?
3 楼 helynfeng 2009-07-14  
额,骗局.
2 楼 gzhzh 2009-07-14  
alexlee002 写道
嘿嘿, 仔细检查一下你的数据, 看看有没有问题。


我几年前写过一个脚本在这网站上抓数据, 发现访问太频繁的时候, 它会给你假数据。

我后来用N多个账号不定时轮番登陆去抓, 而且过一段时间还断网重连(adsl, 换ip),

搞了将近一个星期才抓全。

后来直接去移动网站抓去了, 嘿嘿, 不用担心假数据。

还真担心会这样,不过刚才我随机机取了不少号段去别的网站上手工查询,结果都没有出入,是正确的。如果真如你所说的,就得搞点欺骗才行了
1 楼 alexlee002 2009-07-14  
嘿嘿, 仔细检查一下你的数据, 看看有没有问题。


我几年前写过一个脚本在这网站上抓数据, 发现访问太频繁的时候, 它会给你假数据。

我后来用N多个账号不定时轮番登陆去抓, 而且过一段时间还断网重连(adsl, 换ip),

搞了将近一个星期才抓全。

后来直接去移动网站抓去了, 嘿嘿, 不用担心假数据。

相关推荐

    android 手机号码归属地查询

    通过这个源代码,开发者不仅可以学习到如何在Android上实现手机号码归属地查询,还能了解到网络请求、数据解析、UI设计、权限管理等多个方面的知识,这对于提升Android开发技能非常有帮助。不过,实际使用时应确保...

    java 调用 360 api 接口实现批量查询手机号码归属地

    响应通常包含JSON格式的数据,其中包含了手机号码的归属地信息。使用如`org.json`库解析JSON数据,提取所需信息。 6. **错误处理**:处理可能出现的网络问题、API调用限制、无效响应等错误情况。例如,如果API调用...

    手机号码归属地查询代码示例

    - 用户隐私保护:对用户输入的手机号进行脱敏处理,不要存储原始号码。 - 错误处理:添加异常处理代码,确保程序在请求失败时能优雅地处理。 在实际开发中,可能会涉及到网络权限配置、异步任务处理(如使用...

    Android 手机号码归属地查询

    【Android 手机号码归属地查询】是一个针对Android平台的应用程序开发实例,它允许用户查询手机号码的归属地信息。这个应用通常会结合Web服务(Websevice)技术,从远程服务器获取数据,以实现对全国各个手机号码的...

    Android 输入手机号码(GET网络请求)查询手机号码归属地

    在Android平台上,开发一个能够通过输入手机号码并发送GET网络请求来查询归属地的应用是一项常见的功能。这个功能的实现涉及到多个技术点,包括用户界面设计、网络请求处理、数据解析以及错误处理等。 首先,我们...

    android 基于webservice的手机归属地查询代码

    在Android开发中,有时我们需要实现一个功能,即根据手机号码查询其归属地。这个功能可以通过调用Web服务接口来实现,本示例就是一个基于Webservice的Android手机号码归属地查询程序。下面将详细介绍如何实现这一...

    Android手机号码归属地查询联网加本地

    在Android平台上,实现手机号码归属地查询功能是一个常见的需求,特别是在开发与通信相关的应用程序时。这个功能可以帮助用户识别来电号码的来源,增加应用的实用性和用户体验。以下将详细阐述实现"Android手机号码...

    Android手机号码归属地查询的应用程序

    首先,我们需要理解的是,手机号码归属地查询涉及到的数据通常由电信运营商提供,而这些数据通常通过Web服务接口,如SOAP(Simple Object Access Protocol)来访问。SOAP是一种基于XML的协议,用于在Web上交换结构化...

    Android手机号码归属地_安卓源码.zip

    总的来说,通过分析这个"Android手机号码归属地"的源码,我们可以学习到Android应用的网络通信、数据解析、UI设计、数据存储以及异步处理等多个重要知识点。对于初学者,这是一个很好的实践项目;对于有经验的开发者...

    号码归属地查询

    在信息技术日益发达的今天,手机号码归属地查询是一项常见的功能,它能够帮助我们了解电话号码的来源,对于个人安全防护和商业数据分析都有着重要作用。本文将深入探讨一个基于Java实现的手机号码归属地查询系统,...

    手机号码归属地查询源代码

    总之,开发一个手机号码归属地查询的Android应用涉及到了Android的基础知识、网络编程、数据解析等多个方面。通过合理组织代码、遵循最佳实践,我们可以创建出高效、稳定的查询工具,满足用户的日常需求。

    以实体数据发送xml,号码归属地查询

    服务器端接收到请求后,会解析XML,找到手机号码,然后进行归属地查询。这可能涉及到数据库查询,比如查找该号码对应的运营商、省市区信息等。 查询完成后,服务器会返回一个XML响应,同样包含电话号码的归属地信息...

    Android项目实战--手机卫士12--手机号码归属地查询界面

    在本Android项目实战中,我们将关注的是"手机卫士"应用的一个重要功能模块——"手机号码归属地查询界面"。这个功能通常用于帮助用户识别来电号码的来源,从而提高对未知来电的安全判断。以下是该功能实现涉及的关键...

    安卓Android源码——手机号码归属地.zip

    如果使用在线API查询归属地,开发者需要了解如何在Android中进行网络请求,如使用`HttpURLConnection`、`OkHttp`或者`Volley`等网络库。注意,网络请求应在后台线程中执行,避免阻塞UI线程。 6. **数据缓存**: ...

    Java基于聚合网API做的很基础的手机号归属地查询

    在本项目中,我们主要探讨的是如何利用Java编程语言与聚合网API进行集成,实现一个基础的手机号码归属地查询功能。聚合网提供了一系列的开放接口,开发者可以通过这些接口获取到丰富的数据信息,包括但不限于手机...

    手机归属地查询源代码.rar

    "手机归属地查询源代码.rar"是一个典型的电信数据查询项目,涉及到数据库设计、接口调用、数据处理和用户交互等多个方面。通过理解并分析源代码,我们可以学习到如何构建这样的系统,同时也要关注数据安全和用户隐私...

    Android使用Https查询手机号码归属地

    接口可能采用POST或GET方法,接收手机号码作为参数,返回JSON格式的数据,包含归属地信息,如运营商、区号、城市等。例如,请求URL可能是`https://api.taobao.com/router/rest`,请求参数可能有`method`(接口名)、...

Global site tag (gtag.js) - Google Analytics