[Python]百度慧眼⼈⼝热⼒图数据爬取--以深圳市为例
百度慧眼⼈⼝热⼒图数据爬取--以深圳市为例
利⽤python爬取深圳市百度慧眼⼈⼝热⼒图数据,线形回归分析对爬取坐标进⾏转换,最后对爬取数据进⾏可视化展⽰。
数据爬取
另外,还请⼤家不要对端⼝进⾏恶意攻击或⾼频访问,⼀次请求即可获取全市数据,⽽且数据按⼩时更新。
import requests
headers ={
'Connection':'keep-alive',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
'Accept':'*/*',
'Origin':'huiyan.baidu',
'Sec-Fetch-Site':'cross-site',
'Sec-Fetch-Mode':'cors',
'Sec-Fetch-Dest':'empty',
'Referer':'huiyan.baidu/cms/heatmap/shenzhen.html',
'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8',
}
params =(
('cityId','440300'),
('ak','3gHV4PFiWyZ7xnwnVjDq6vEel99V3jQc'),
)
response = ('huiyan.baidu/openapi/v1/heatmap/heatmapsearch', headers=headers, params=params)
#NB. Original query string below. It seems impossible to parse and
#reproduce query strings 100% accurately so the one below is given
#in case the reproduced version is not "correct".
# response = ('huiyan.baidu/openapi/v1/heatmap/heatmapsearch?cityId=440300&ak=3gHV4PFiWyZ7xnwnVjDq6vEel99V3jQc', he aders=headers)
对爬取数据进⾏结构解析,发现数据储存形式为“横坐标_纵坐标_地名计数”,并且每个值由“|”分隔。
# coding=utf-8
import pandas as pd
# 将数据转化为dataframe格式
js1= response.json()# 获取响应⽂件的json格式
js2=js1['result']['data']# 提取data部分
str1 = js2.split("|")# 以“|”符号对data进⾏分隔
df = pd.DataFrame(str1)# 传⼊dataframe
# 利⽤str.split()将数据分为多列
df['x']= df[0].str.split('_').str[0]
df['y']= df[0].str.split('_').str[1]
df['value']= df[0].str.split('_').str[2]
需要注意的是,由于“data”是以 “|”结尾,df最后⼀⾏为空值,需要对其剔除。
# 剔除含有空值的⾏
df = df.dropna()
得到最终结果:
坐标转换
LNG LAT X Y 113.90457922.656801126799672573996
113.79025122.676882126672282576368
114.57261722.505705127543022555841
114.28426122.801803127222052591362
113.93143422.848654126829162596991
113.88237322.853966126774862597634
利⽤pandas、sklearn模块对坐标映射表进⾏回归分析:
1、读取坐标映射表
# 复制上表,读取剪切板数据
data = pd.read_clipboard()
我们查看⼀下各列数据之间的相关性,发现“LNG与X”以及“LAT与Y”之间相关性接近1,说明他们之间线性相关较强,印证了前⾯的猜想,理论上我们选取的映射坐标对越多,精度越⾼。
# 相关性系数分析
<()
2、利⽤sklearn进⾏回归分析
对经度和横坐标拟合:
from sklearn.linear_model import LinearRegression
#估计模型参数,建⽴回归模型
'''
(1) ⾸先导⼊简单线性回归的求解类LinearRegression
(2) 然后使⽤该类进⾏建模,得到lrModel的模型变量
'''
lrModel = LinearRegression()
#(3) 接着,我们把⾃变量和因变量选择出来
x = data[['X']]
y = data[['LNG']]
#模型训练
'''
调⽤模型的fit⽅法,对模型进⾏训练
这个训练过程就是参数求解的过程
并对模型进⾏拟合
'''
lrModel.fit(x,y)
#对回归模型进⾏检验
print('决定系数(R^2):',lrModel.score(x,y))
#查看截距
alpha = lrModel.intercept_[0]
#查看参数
beta = f_[0][0]
print('alpha值:',alpha,"    beta值:",beta)
输出结果:
决定系数(R^2):0.9999998457083179
alpha值:-0.027743944995606284    beta值:8.98523370006391e-06
得到经度与横坐标之间的联系:
经度:lng = -0.027743944995606284 + 8.98523370006391e-06 * x 同样,对纬度和纵坐标拟合:
lrModel_2 = LinearRegression()
x_2 = data[['Y']]
y_2 = data[['LAT']]
#模型训练
'''
调⽤模型的fit⽅法,对模型进⾏训练
这个训练过程就是参数求解的过程
并对模型进⾏拟合
'''
lrModel_2.fit(x_2,y_2)
#对回归模型进⾏检验
print('决定系数(R^2):',lrModel_2.score(x,y))
#查看截距
alpha_2 = lrModel_2.intercept_[0]
#查看参数
beta_2 = f_[0][0]
print('alpha_2值:',alpha_2,"    beta_2值:",beta_2)
输出结果:
决定系数(R^2):0.9999993702024847
alpha_2值:1.20316833550093    beta_2值:8.33483092560397e-06
得到纬度与纵坐标之间的联系:
纬度:lat = 1.20316833550093 + 8.33483092560397e-06 * y
3、坐标转换输出
# 添加百度坐标
df['lng']= alpha+beta*df['x'].astype('f')
df['lat']= alpha_2+beta_2*df['y'].astype('f')
# 剔除⾸列
df = df.drop([0],axis=1)
# 获取当前时间,请求结果中的time字段
time = js1['result']['time']
#输出到csv⽂件,结合⾃⼰所需⽂件编码类型,⾃⾏调整encoding的值
<_csv('./data/'+time+'.csv',index=0,encoding='utf-8')
完整代码
# coding=utf-8
import requests
import pandas as pd
import json
from sklearn.linear_model import LinearRegression
import time
def req_data(url):
'''
数据爬取,返回json类结构
'''
headers ={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0', 'Accept':'*/*',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer':'huiyan.baidu/cms/heatmap/shenzhen.html',
'Origin':'huiyan.baidu',
write的返回值'Origin':'huiyan.baidu',
'DNT':'1',
'Connection':'keep-alive',
'Cache-Control':'max-age=0',
}
params =(
('cityId','440300'),
('ak','3gHV4PFiWyZ7xnwnVjDq6vEel99V3jQc'),
)
try:
r = (url=url, headers=headers, params=params)
r.raise_for_status()
return r.json()
except:
return"⽹络传输异常"
def linear_regression(df_1,df_2):
'''
对df_1,df_2两个单列进⾏线性回归分析
'''
lrModel = LinearRegression()# 构建线性回归模型
lrModel.fit(df_1,df_2)# 拟合
#对回归模型进⾏检验
print('决定系数(R^2):',lrModel.score(df_1,df_2))
#查看截距
alpha = lrModel.intercept_[0]
#查看参数
beta = f_[0][0]
return alpha,beta
def clean_data(json):
'''
数据整理,对返回数据进⾏重构
'''
data_cell = json['result']['data'].split("|")
df = pd.DataFrame(data_cell)
# 以‘_’为分隔符,拆分为多列,并删除⾸列
df['x']= df[0].str.split('_').str[0]
df['y']= df[0].str.split('_').str[1]
df['value']= df[0].str.split('_').str[2]
df = df.drop([0],axis=1)
# 相应⽂件的‘data’以“|”结尾,需剔除最后⼀⾏
df = df.dropna()
# 传⼊映射坐标列表,格式为{百度坐标系经度,百度坐标系维度,横坐标,纵坐标}
data = pd.read_csv('./data/mapping_coordinates.csv')
# 拟合映射坐标
alpha_1,beta_1 = linear_regression(data[['X']],data[['LNG']])
alpha_2,beta_2 = linear_regression(data[['Y']],data[['LAT']])
# 添加百度坐标
df['lng']= alpha_1+beta_1*df['x'].astype('f')
df['lat']= alpha_2+beta_2*df['y'].astype('f')
return df
def main():
url =r"huiyan.baidu/openapi/v1/heatmap/heatmapsearch"# 深圳市百度慧眼⼈流热⼒图⽹址    js = req_data(url)
# 获取当前时间,请求结果中的time字段
global file_time
file_time = js['result']['time']
df = clean_data(js)
#输出到csv⽂件,结合⾃⼰所需⽂件编码类型,⾃⾏调整encoding的值
<_csv('./data/'+file_time+'.csv',index=0,encoding='utf-8')