使用hadoop实现ip地理位置统计~ip归属地和运营商

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/40585565

更多相关hadoop内容访问:http://blog.csdn.net/xiaojimanman/article/category/2640707

对于博客 http://blog.csdn.net/xiaojimanman/article/details/40372189 中的计算结果 key-value (ip,出现次数),统计下各个地区运营商下的IP个数,通过这个计算结果,可以分析出用户的地理位置分布情况,为决策提供数据支持。

需求分析:

根据IP归属地,对IP进行分组求和,将结果输出到文件中。

数据格式:

此次的数据格式相对比较简单,就是博客 http://blog.csdn.net/xiaojimanman/article/details/40372189 的结果数据,一行数据格式为:

ip地址空格分隔符出现次数 例: 192.168.1.1 25

需求分析:

在实现mapreduce程序之前,需要考虑的一个问题就是IP地址和归属地之间的转换问题。我这里采用的是百度的阿拉丁接口,接口获取方法,在百度首页输入"IP",就会出现阿拉丁界面。如下图所示:

通过对该部分的网络请求分析,获取地址 http://opendata.baidu.com/api.php?query=122.49.34.58&co=&resource_id=6006&t=1414563340538&ie=utf8&oe=gbk&format=json&tn=baidu&_=1414563341538 可以获取IP的归属地,该接口返回的数据格式如下图所示:

可以通过HttpClient模拟浏览器访问该地址,分析返回结果,获取该IP地址对应的归属地。如果自己有IP库,这一步就会简单很多。

IP个归属地中间的对应关系解决了,就需要设计mapreduce的实现问题。

map的输入就是一行原始记录,首先需要对记录进行拆分,取得IP地址,在通过上面提到的接口,查询该IP的归属地;map的输出结果是key为IP归属地,value为出现次数,一行记录就是1 。输出结果如下图所示:

reduce就需要对同一个key下的记录求和即可,输出结果是key为IP归属地,value为出现次数,如下图所示:

这一篇博客在mapreduce方面和上两篇没有太大的区别,所以这里也不再详细的阐述了,这一篇主要的目的就是在mapreduce程序中使用第三方的接口。需求分析就到此为止,下面就看具体的代码实现。

代码实现:

ip归属地查询代码

/**
 * @Description: ip归属地查询
 */
package com.lulei.crawl.ip;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;

import org.apache.commons.httpclient.HttpException;

import com.lulei.crawl.CrawlBase;
import com.lulei.util.DoRegex;

/**
 * @author lulei
 * 这里继承了自己的封装类,在类CrawlBase中实现了网络数据的获取,并将网页源代码存储在pageSourceCode中
 */
public class IPInfo extends CrawlBase{
	private String ip;
	private String location;
	//第三方接口地址
	private static String ipUrl = "http://opendata.baidu.com/api.php?query=%ip%&co=&resource_id=6006&t=%t1%&ie=utf8&oe=gbk&format=json&tn=baidu&_=%t2%";
	private static long timeDifference = 1000L;
	private static HashMap<String, String> params;
	private static String locationRegex = "\"location\":\"(.*?)\"";

	//伪装浏览器
	static {
		params = new HashMap<String, String>();
		params.put("Referer", "http://www.baidu.com");
		params.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36");
	}

	public IPInfo(String ip) throws HttpException, IOException {
		long t1 = new Date().getTime();
		long t2 = t1 + timeDifference;
		this.ip = ip;
		//组装请求地址
		String url = ipUrl.replaceAll("%ip%", ip)
									 .replaceAll("%t1%", t1 + "")
									 .replaceAll("%t2%", t2 + "");
		//获取网页源代码,具体的实现,这里就不详细的介绍,自己可以写简单的HttpClient实现此功能
		readPageByGet(url, "utf-8", params);
		//解析源代码,获取归属地
		setLocation();
	}

	/**
	 * @author lulei
	 * 解析源代码,获取归属地
	 */
	private void setLocation() {
		this.location = DoRegex.getFirstString(getPageSourceCode(), locationRegex, 1);
	}

	public String getIp() {
		return ip;
	}
	public String getLocation() {
		return location;
	}

	/**
	 * @param args
	 * @throws IOException
	 * @throws HttpException
	 */
	public static void main(String[] args) throws HttpException, IOException {
		// TODO Auto-generated method stub
		String ip = "122.49.34.58";
		IPInfo ipinfo = new IPInfo(ip);
		System.out.println("ip:" +ip );
		System.out.println("归属地:" + ipinfo.getLocation());
	}
}

对一行记录的分析类

 /**
 *@Description: 一行记录分析
 */
package com.mapreduce.log;  

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;

import com.lulei.crawl.ip.IPInfo;

public class LogLine {
	private String ip;
	private String location;
	private boolean right = true;
	private IntWritable one = new IntWritable(1);

	public LogLine(String textLine) {
		//检验一行日志数据是否符合要求,如不符合,将其标识为不可用
		if (textLine == null || "".equals(textLine)) {
			this.right = false;
			return;
		}
		String []strs = textLine.split(" ");
		if (strs.length < 2) {
			this.right = false;
			return;
		}
		//ip地址在第一个位置
		this.ip = strs[0];
		setLocation();
	}

	private void setLocation() {
		try {
			IPInfo ipInfo = new IPInfo(this.ip);
			this.location = ipInfo.getLocation();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//如果出现网络错误,将此IP的归属地设置成“未知”
			this.location = "未知";
		}
	}

	/**
	 * @return
	 * @Author:lulei
	 * @Description: map输出key
	 */
	public Text getMapKey() {
		return new Text(this.location);
	}

	/**
	 * @return
	 * @Author:lulei
	 * @Description: map输出value
	 */
	public IntWritable getMapValue() {
		return this.one;
	}

	public boolean isRight() {
		return right;
	}

}

mapreduce程序实现类

 /**
 *@Description: IP归属地统计mapreduce实现
 */
package com.mapreduce.log;  

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class IPLocationMapReduce extends Configured implements Tool{

	/**
	 *@Description: IP归属地统计map
	 *@Author:lulei
	 *@Version:1.1.0
	 */
	public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {

		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
			LogLine logLine = new LogLine(value.toString());
			if (logLine.isRight()) {
				context.write(logLine.getMapKey(), logLine.getMapValue());
			}
		}

	}

	/**
	 *@Description: IP归属地统计reduce
	 *@Author:lulei
	 *@Version:1.1.0
	 */
	public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {

		@Override
		protected void reduce(Text key, Iterable<IntWritable> values, Context context)
				throws IOException, InterruptedException {
			int sum = 0;
			//对values进行求和操作
			for (IntWritable value : values) {
				sum += value.get();
			}
			context.write(key, new IntWritable(sum));
		}

	}

	@Override
	public int run(String[] arg0) throws Exception {
		Configuration conf = new Configuration();
		@SuppressWarnings("deprecation")
		Job job = new Job(conf);
		job.setJobName("ipcount");
		job.setInputFormatClass(TextInputFormat.class);

		//将输出设置为TextOutputFormat
		job.setOutputFormatClass(TextOutputFormat.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);

		//Mapper Combiner Reducer
		job.setMapperClass(Map.class);
		job.setCombinerClass(Reduce.class);
		job.setReducerClass(Reduce.class);

		//输入 输出路径
		FileInputFormat.addInputPath(job, new Path(arg0[0]));
		FileOutputFormat.setOutputPath(job, new Path(arg0[1]));

		job.waitForCompletion(true);

		return job.isSuccessful() ? 0 : 1;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//这里没有对输入的参数做验证
		try {
			int res = ToolRunner.run(new Configuration(), new IPLocationMapReduce(), args);
			System.exit(res);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

上传运行:

打包、上传、运行这些步骤这里就不再详细介绍,具体可以参照博客 http://blog.csdn.net/xiaojimanman/article/details/40184581 最后一部分。

对于自己写的数据的输出结果如下图所示:

到此一个完整的mapreduce程序就完成了,关于hadoop的学习,自己还将继续~

时间: 2024-10-09 16:23:57

使用hadoop实现ip地理位置统计~ip归属地和运营商的相关文章

Hadoop(Pig)统计IP地理位置

很常见的分析需求:日志中记录有访客IP(国内),现在要根据IP地址得出访客的地理位置,精确到市县一级,数据量平均是每天15G,需要统计日.周.月的结果. 最后的实现方式是,先找到IP地理位置数据库,包含每个ip段对应的地址:1.1.0.0,1.1.0.255,福建省然后把它转成具体每个IP对应的地址,即:1.1.0.1,福建省.这样在Pig中用JOIN的方式,就可以获得这个IP实际对应的地址了. IP Database 12年成立的中国广告协会互动网络分会IP地理信息标准委员会(简称IPB)已经

使用hadoop实现IP个数统计~并将结果写入数据库

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/40372189 hadoop源代码中的WordCount事例中实现了单词统计,但是输出到HDFS文件,线上程序想使用其计算结果还要再次写个程序,所以自己就研究一下关于MapReduce的输出问题,下面就通过一个简单的例子说明下如何将MapReduce的计算结果输出到数据库中. 需求描述: 分析网络服务器上的Apache日志,统计每个IP访问资源的次数,并将结果写入到mysql数据

Python基于nginx访问日志并统计IP访问量

如果想看看Nginx有多少IP访问量,有哪些国家访问,并显示IP地址的归属地分布,python可以结合使用高春辉老师ipip.net[免费版 IP 地址数据库],Shell可以使用nali,我这边主要使用python语言来实现需求,并将查询结果以邮件形式发送,也是为了学习和回顾python语言.很感谢高春辉老师提供的免费版IP地址数据库. 一.Ningx日志如下: 41.42.97.104 - - [26/Feb/2015:03:35:40 -0500] "GET /root/ HTTP/1.1

php利用淘宝IP库获取用户ip地理位置

利用淘宝IP库获取用户ip地理位置 我们查ip的时候都是利用ip138查询的,不过那个有时候是不准确的,还不如自己引用淘宝的ip库来查询,这样准确度还高一些.不多说了,介绍一下: 淘宝IP地址库 淘宝公布了他们的IP库http://ip.taobao.com/,还有REST API接口,不过每个用户的访问频率需小于10qps,访问方    式:http://ip.taobao.com/service/getIpInfo.php?ip=[ip地址字串],返回内容以json格式的.具有IP查询,IP

老男孩教育每日一题-2017年4月26日-通过访问日志access.log统计IP和每个地址访问的次数

通过访问日志access.log统计IP和每个地址访问的次数 101.226.61.184 - - [22/Nov/2015:11:02:00 +0800] "GET /mobile/sea-modules/gallery/zepto/1.1.3/zepto.js HTTP/1.1" 200 24662 "http://m.oldboyedu.com/mobile/theme/oldboyedu/home/index.html" "Mozilla/5.0 

web day21 web过滤器Filter,应用案例统计IP,解决全站乱码,粗粒度权限控制,页面静态化

JavaWeb三大组件 1. 都需要在web.xml中进行配置 Servlet Listener(2个感知监听器不需要配置) Filter 过滤器 它会在一组资源(jsp.servlet..css..html等等)的前面执行! 它可以让请求得到目标资源,也可以不让请求达到! * 过滤器有拦截请求的能力! 登录: 允许它访问AServlet.BServlet.CServlet ------------------------------- 过滤器如何编写 1. 写一个类实现Filter接口 2.

由统计ip出现次数展开的...

新来个intern,跟着某同事做devops,看其对于shell有点疑惑,于是列举了个简单的应用给他,统计IP出现次数 . TCP    192.168.0.97:1052      60.28.216.15:80        CLOSE_WAIT TCP    192.168.0.97:1436      219.133.60.243:8000    CLOSE_WAIT TCP    192.168.0.97:1624      72.14.235.101:443      CLOSE_W

域名查询IP及公网IP地址地理位置查询

#!/bin/bash printf "本脚本包含ip地理位置查询及已知域名查询IP \n" printf "###################################### \n" printf "/tmp/dns.txt 需要查询的域名列表目录 \n" printf "/tmp/dns_ip.txt 存放查询后的域名及IP对应目录 \n" printf "#######################

Python文件练习_查找log中的IP并统计

需求:监控日志,如果有攻击,就把ip加入黑名单 分析: 1.打开日志文件 2.把ip地址拿出来 3.判断每一个ip出现的次数,如果大于50次的话,加入黑名单 4.每分钟读一次 log样式: 178.210.90.90 - - [04/Jun/2017:03:44:13 +0800] "GET /wp-includes/logo_img.php HTTP/1.0" 302 161 "http://nnzhp.cn/wp-includes/logo_img.php" &