**在项目中对商圈等需要用到地图,这样我们就需要调用地图接口,如何实现呢,我们在这里以百度地图为例:**
-
百度地图开放平台的注册:
用浏览器打开 http://lbsyun.baidu.com/index.php?title=首页 这个网站就是 百度地图开放平台
在网站首页的最底层申请密钥
点进去进行申请。- 会出现电话等信息,注册之后,就可以使用。
- 进行创建应用。
4.创建完成后在这里显示出来
ak 和 sk 得到后,就可以使用了。
注意:百度可以免费使用3千条数据
**
scala语言调用百度地图
**
代码如下:
package Tags
import ch.hsr.geohash.GeoHash
import org.apache.spark.sql.SQLContext
import org.apache.spark.{SparkConf, SparkContext}
import utils.{BaiduLBSHandler, JedisConnectionPool}
object ExtractLongandLat2Business {
def main(args: Array[String]): Unit = {
if(args.length!=1){
println("argument is wrong!!")
sys.exit()
}
val Array(inputPath) = args
val conf = new SparkConf().setMaster("local[*]")
.setAppName(s"${this.getClass.getSimpleName}")
.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
sqlContext.setConf("spark.sql.parquet.compression.codec","snappy")
sqlContext.read.parquet(inputPath).select("lat","long").filter(
"""
|cast(long as double) >=73 and cast(long as double) <=136 and
|cast(lat as double) >=3 and cast(lat as double) <=54
""".stripMargin).distinct()
// .foreachPartition(t=>{
// val jedis = JedisConnectionPool.getConnection()
// t.foreach(t=>{
// val long = t.getAs[String]("long")
// val lat = t.getAs[String]("lat")
//通过百度的逆地址解析,获取到商圈信息
// val geoHashs = GeoHash.geoHashStringWithCharacterPrecision(long.toDouble,lat.toDouble,8)
//进行sn验证
// val business = BaiduLBSHandler.parseBusinessTagBy(long,lat)
// jedis.set(geoHashs,business)
// })
// jedis.close()
// })
.map(t=>{
val long =t.getAs[String]("long")
val lat = t.getAs[String]("lat")
val geoHash = GeoHash.geoHashStringWithCharacterPrecision(lat.toDouble,long.toDouble,8)
val b = BaiduLBSHandler.parseBusinessTagBy(long,lat)
(geoHash,b)
}).foreach(println)
}
}
还有一个工具类
package utils
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
import java.security.NoSuchAlgorithmException
import java.util
import com.google.gson.{JsonObject, JsonParser}
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.httpclient.methods.GetMethod
import org.apache.commons.lang3.StringUtils
object BaiduLBSHandler {
/**
* 对外提供的解析经纬度对应的商圈信息
*
* @param lng 经度
* @param lat 纬度
*/
def parseBusinessTagBy(lng: String, lat: String) = {
var business: String = ""
val requestParams = requetParams(lng, lat)
val requestURL = "http://api.map.baidu.com/geocoder/v2/?" + requestParams
// 使用HttpClient 模拟浏览器发送请求
val httpClient = new HttpClient()
val getMethod = new GetMethod(requestURL)
val statusCode = httpClient.executeMethod(getMethod)
if (statusCode == 200) { // HTTP.OK
val response = getMethod.getResponseBodyAsString
// 判断是否是合法的json字符换
var str = response.replaceAll("renderReverse&&renderReverse\\(", "")
if (!response.startsWith("{")) {
str = str.substring(0, str.length - 1)
}
// 解析这个json字符串,取出business节点数据
val returnData = new JsonParser().parse(str).getAsJsonObject
// 服务器返回来的json数据,status表示服务器是否正常(0)处理了我的请求
val status = returnData.get("status").getAsInt
if (status == 0) {
val resultObject = returnData.getAsJsonObject("result")
business = resultObject.get("business").getAsString.replaceAll(",", ";")
// 判断business是否为空,如果为空,接着解析改坐标点附近的标签信息pois
if (StringUtils.isEmpty(business)) {
val pois = resultObject.getAsJsonArray("pois")
var tagSet = Set[String]()
for (i <- 0 until pois.size()) {
val elemObject: JsonObject = pois.get(i).getAsJsonObject
val tag = elemObject.get("tag").getAsString
if (StringUtils.isNotEmpty(tag)) tagSet += tag
}
business = tagSet.mkString(";")
}
}
}
business
}
private def requetParams(lng: String, lat: String) = {
//3eWFUfbFLTMopRpY1xk9BRD3iFdxo3r4
//rvGCL2H2iEScXwNgZvGplcyRsnDC2x9j
val list ="yv3qSdkEAwvvEvSpGs5mbpG89mUXBunk,bHL5XQgqfSGzhDgSZY2px8iXChKKfgFs"
val Array(ak, sk) = list.split(",")
// 计算sn跟参数对出现顺序有关,get请求请使用LinkedHashMap保存<key,value>,
// 该方法根据key的插入顺序排序;post请使用TreeMap保存<key,value>,
// 该方法会自动将key按照字母a-z顺序排序。所以get请求可自定义参数顺序(sn参数必须在最后)发送请求,
// 但是post请求必须按照字母a-z顺序填充body(sn参数必须在最后)。
// 以get请求为例:http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak,
// paramsMap中先放入address,再放output,然后放ak,放入顺序必须跟get请求中对应参数的出现顺序保持一致。
val paramsMap = new util.LinkedHashMap[String, String]();
paramsMap.put("callback", "renderReverse")
// paramsMap.put("location", "39.343424,116.452987")
paramsMap.put("location", lat.concat(",").concat(lng))
paramsMap.put("output", "json")
paramsMap.put("pois", "1")
paramsMap.put("ak", ak)
// 请求的参数
val paramsStr = toQueryString(paramsMap)
// 生成SN
val wholeStr = new String("/geocoder/v2/?" + paramsStr + sk)
val tempStr = URLEncoder.encode(wholeStr, "UTF-8")
val sn = MD5(tempStr)
paramsStr + "&sn=" + sn
}
// 对Map内所有value作utf8编码,拼接返回结果
@throws[UnsupportedEncodingException]
private def toQueryString(data: util.LinkedHashMap[String, String]): String = {
val queryString = new StringBuffer
import scala.collection.JavaConversions._
for (pair <- data.entrySet) {
queryString.append(pair.getKey + "=")
queryString.append(URLEncoder.encode(pair.getValue.asInstanceOf[String], "UTF-8") + "&")
}
if (queryString.length > 0) queryString.deleteCharAt(queryString.length - 1)
queryString.toString
}
// 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
private def MD5(md5: String): String = {
try {
val md = java.security.MessageDigest.getInstance("MD5")
val array = md.digest(md5.getBytes)
val sb = new StringBuffer
var i = 0
while ( {
i < array.length
}) {
sb.append(Integer.toHexString((array(i) & 0xFF) | 0x100).substring(1, 3))
{
i += 1
i
}
}
return sb.toString
} catch {
case e: NoSuchAlgorithmException =>
}
null
}
}
加上你自己的数据文件,就可以进行运行了。
个人代码Ieda演示结果截图部分: