2020年8月1日更:百度迁徙在5月8日后就不开放了,目前好像只能爬取到3月15日之前的数据,而且爬取的时候会遇到挺多问题的(具体我也不知道,不开放后我就没爬过了,但是最近很多朋友在问)。评论里关于爬取遇到的问题很多我也没遇到过,没办法帮到你们。
2020年10月21日更:百度迁徙重新开放了,数据从9月22开始都有。以下旧的代码需要更改一个地方,即把代码里所有r=response.text[3:-1]
全部替换为r=response.text[4:-1]
即可。
目录
- 简介
- 效果展示
- 准备——城市编码
- 代码(旧版本—xlwt)
- 代码(新版本—xlsxwriter)
- 编辑日志
- 系列文章
简介
百度迁徙 :百度迁徙
不多逼逼,相关的自己了解。趁这几天比较好抓取数据,需要的数据就赶紧抓抓抓。
效果展示
本文的数据主要是来自百度迁徙里面的迁徙规模指数,如下图。
本文提供的代码可以批量抓取数据,如抓取所有城市级别的迁入规模指数放进一个表格里,迁出规模指数放进另一个表格里,这样。或者你也可以设定抓取所有省份级别的数据。如下图,我分别按全国级别、省份级别、城市级别抓取,共获得五个表格,为什么是五个呢,因为全国的数据没有分迁入迁出,按照百度迁徙的说法是“全国为总体迁徙规模,不区分迁入或迁出”。当然也可以通过自定义字典来抓取你想要的城市,具体可参考第三部分“准备——城市编码”。
先展示一波抓取后的数据,各位看官看看是不是自己需要的,如下图。
因为上上图的迁徙规模指数的曲线有和去年农历同期对比,所以我就连去年的指数也抓取了,第一行是日期,去年的日期在前面,今年的在后面,你越晚抓取,今年的日期就越多。
准备——城市编码
城市编码和我的上一篇文章一样,可以直接参考。
代码(旧版本—xlwt)
记得调用相关的城市编码和省份编码数据。
# -*- coding: utf-8 -*-
import requests #导入请求模块
import json #导入json模块
import time #导入时间模块
import xlwt
from ChineseAdminiDivisionsDict import CitiesCode, ProvinceCode
def migration_index(FileTittle,classname,direction,CodeDict): #CodeDict字典里所有城市的迁徙规模指数,以全国列表形式列出
#######创建一个workbook########
workbook = xlwt.Workbook(encoding = 'utf-8') # 创建一个workbook 设置编码
worksheet = workbook.add_sheet('Sheet', cell_overwrite_ok=True) # 创建一个worksheet
#################写入行头各城市代码及其城市名###############
if direction == 'in' :
nameofdire = '迁入'
if direction == 'out':
nameofdire = '迁出'
CitiesOrder = {} #存放城市序号的空字典
worksheet.write(0 , 0 , label='城市代码') #写入行头
worksheet.write(0 , 1 , label='城市') #写入行头
times = 1
for key , value in CodeDict.items():
worksheet.write(times , 0 , label=str(value)) #写入城市代码
worksheet.write(times , 1 , label=str(key)) #写入城市名
CitiesOrder[str(key)] = times #写入城市序号字典
times += 1
########################开始抓取数据##############################
for Area , Code in CodeDict.items():
url=f'http://huiyan.baidu.com/migration/historycurve.jsonp?dt={classname}&id={Code}&type=move_{direction}'
print(f'{Area}:{url}')
response=requests.get(url, timeout=2) # #发出请求并json化处理
time.sleep(3)
r=response.text[3:-1] #去头去尾
data_dict=json.loads(r) #字典化
if data_dict['errmsg']=='SUCCESS':
data_list=data_dict['data']['list']
counter_date = 2 #日期计数器
datelist = []
for date , index in data_list.items(): #按日期排序
datelist.append(date)
datelist.sort()
for date in datelist:
index = data_list[date]
# print(f'{date} : {index}')
worksheet.write(0 , counter_date , label=date)
worksheet.write(CitiesOrder[str(Area)] , counter_date , label=index)
counter_date += 1 #日期计数器自加一
else:
print('错误')
workbook.save(f'{FileTittle} {nameofdire}规模指数.xls')
quanguo = {'全国':0} #全国编码
if __name__=="__main__":
migration_index('城市','city','in',CitiesCode)
migration_index('城市','city','out',CitiesCode)
print('全部完成')
代码(新版本—xlsxwriter)
# -*- coding: utf-8 -*-
import requests #导入请求模块
import json #导入json模块
import time #导入时间模块
import xlsxwriter
from ChineseAdminiDivisionsDict import CitiesCode, ProvinceCode
def migration_index(FileTittle,classname,direction,CodeDict): #CodeDict字典里所有城市的迁徙规模指数,以全国列表形式列出
if direction == 'in' :
nameofdire = '迁入'
if direction == 'out':
nameofdire = '迁出'
#######创建一个workbook########
workbook = xlsxwriter.Workbook(f'百度迁徙数据V3.1\\迁徙规模\\{FileTittle} {nameofdire}规模指数.xlsx')
worksheet = workbook.add_worksheet('Sheet')
#################写入行头各城市代码及其城市名###############
if direction == 'in' :
nameofdire = '迁入'
if direction == 'out':
nameofdire = '迁出'
CitiesOrder = {} #存放城市序号的空字典
worksheet.write(0 , 0 , '城市代码') #写入行头
worksheet.write(0 , 1 , '城市') #写入行头
times = 1
for key , value in CodeDict.items():
worksheet.write(times , 0 , str(value)) #写入城市代码
worksheet.write(times , 1 , str(key)) #写入城市名
CitiesOrder[str(key)] = times #写入城市序号字典
times += 1
########################开始抓取数据##############################
for Area , Code in CodeDict.items():
url=f'http://huiyan.baidu.com/migration/historycurve.jsonp?dt={classname}&id={Code}&type=move_{direction}'
print(f'{Area}:{url}')
response=requests.get(url, timeout=2) # #发出请求并json化处理
time.sleep(3)
r=response.text[4:-1] #去头去尾
data_dict=json.loads(r) #字典化
if data_dict['errmsg']=='SUCCESS':
data_list=data_dict['data']['list']
counter_date = 2 #日期计数器
datelist = []
for date , index in data_list.items(): #按日期排序
datelist.append(date)
datelist.sort()
for date in datelist:
index = data_list[date]
# print(f'{date} : {index}')
worksheet.write(0 , counter_date , float(date))
worksheet.write(CitiesOrder[str(Area)] , counter_date , float(index))
counter_date += 1 #日期计数器自加一
else:
print('错误')
workbook.close()
quanguo = {'全国':0} #全国编码
if __name__=="__main__":
migration_index('城市','city','in',CitiesCode)
migration_index('城市','city','out',CitiesCode)
print('全部完成')
重点说明一下这个函数,migration_index(FileTittle,classname,direction,CodeDict)
,FileTittle是你要设定的文件夹的名字,仅作标识区分,你要写个狗蛋也行,自己能知道是啥就行了;classname是城市级别,如果你抓取城市级别数据就写city,抓取省份级别就写province,抓取全国的就写country,这和我的上一篇文章的这个部分是一样的;direction是迁徙方向,如果你要抓取迁入强度,就写in,抓取迁出强度就写out;CodeDict是需要你导入的带有城市编码的字典,如果想直接抓取全部城市或全部省份就直接导入我给的CitiesCode或ProvinceCode,具体参考“准备——城市编码”部分。
编辑日志
2020年5月4日:刚才有小伙伴私信我说今天的代码跑不了了,我看了一眼是因为数据的更新导致数据量变大了,而xlwt包写不了255列以上的数据,所以在这里我建议今后要使用代码且有一定条件的朋友改为调用xlsxwriter包,相关的代码当然也要同步更改。我也在这两天会把更新的代码放上来。另外感谢小伙伴们的支持!
2020年5月4日:把原来的xlwt包换成了xlsxwriter包,解决了无法写入超过255列的问题。