小言_互联网的博客

基于python的百度迁徙迁入、迁出数据爬取(爬虫大数据)(附代码)

395人阅读  评论(0)

简介

百度迁徙 :http://qianxi.baidu.com

不多逼逼,相关的自己了解。趁这几天比较好抓取数据,需要的数据就赶紧抓抓抓。

效果展示

不着急看代码,先给你们看一波效果图,各位看官看完效果图看看是不是自己需要的再看代码。

我是把获得的数据存成一个xls格式,因为csv换列不太方便(我不会)所以我选择了xls。这张图里表是我的家乡泉州一月、二月一共两个月的迁出数据,左边第一列是全国所有城市的编码(身份证前6位,这也和爬取百度迁徙url要求的编码一样),左边第二列是全国所有城市的名称,第一行是日期。为什么我要把表弄成这样呢?因为我要把表丢进GIS里做可视化(后面有可视化的图),又懒得改,所以这样方便一点,直接丢进去就可以了。

然后为了让各位看官看到像百度迁徙网站那样的前一百名排序,我就特地点了排序截了一张图(1月1日排序)如下。(这两个是同一个表)

前面说要展示的可视化,我选的好像是泉州的1月9日的迁出。随手一截。

准备——城市编码

在正式搬出代码前,可能需要个字典,要不然都不知道哪个城市是什么编码。

这个我是新建一个py文件,和主程序丢在同一个文件夹里,然后在主程序里直接import调用。

一行代表一个省份(新疆的太长了,我就分了两行)。

#ChineseAdminiDivisionsDict.py


CitiesCode = {
                '北京市':110000,'天津市':120000,
                '石家庄市':130100,'唐山市':130200,'秦皇岛市':130300,'邯郸市':130400,'邢台市':130500,'保定市':130600,'张家口市':130700,'承德市':130800,'沧州市':130900,'廊坊市':131000,'衡水市':131100,
                '太原市':140100,'大同市':140200,'阳泉市':140300,'长治市':140400,'晋城市':140500,'朔州市':140600,'晋中市':140700,'运城市':140800,'忻州市':140900,'临汾市':141000,'吕梁市':141100,
                '呼和浩特市':150100,'包头市':150200,'乌海市':150300,'赤峰市':150400,'通辽市':150500,'鄂尔多斯市':150600,'呼伦贝尔市':150700,'巴彦淖尔市':150800,'乌兰察布市':150900,'兴安盟':152200,'锡林郭勒盟':152500,'阿拉善盟':152900,
                '沈阳市':210100,'大连市':210200,'鞍山市':210300,'抚顺市':210400,'本溪市':210500,'丹东市':210600,'锦州市':210700,'营口市':210800,'阜新市':210900,'辽阳市':211000,'盘锦市':211100,'铁岭市':211200,'朝阳市':211300,'葫芦岛市':211400,
                '长春市':220100,'吉林市':220200,'四平市':220300,'辽源市':220400,'通化市':220500,'白山市':220600,'松原市':220700,'白城市':220800,'延边朝鲜族自治州':222400,
                '哈尔滨市':230100,'齐齐哈尔市':230200,'鸡西市':230300,'鹤岗市':230400,'双鸭山市':230500,'大庆市':230600,'伊春市':230700,'佳木斯市':230800,'七台河市':230900,'牡丹江市':231000,'黑河市':231100,'绥化市':231200,'大兴安岭地区':232700,
                '上海市':310000,
                '南京市':320100,'无锡市':320200,'徐州市':320300,'常州市':320400,'苏州市':320500,'南通市':320600,'连云港市':320700,'淮安市':320800,'盐城市':320900,'扬州市':321000,'镇江市':321100,'泰州市':321200,'宿迁市':321300,
                '杭州市':330100,'宁波市':330200,'温州市':330500,'嘉兴市':330400,'湖州市':330500,'绍兴市':330600,'金华市':330700,'衢州市':330800,'舟山市':330900,'台州市':331000,'丽水市':331100,
                '合肥市':340100,'芜湖市':340200,'蚌埠市':340300,'淮南市':340400,'马鞍山市':340500,'淮北市':340600,'铜陵市':340700,'安庆市':340800,'黄山市':341000,'滁州市':341100,'阜阳市':341200,'宿州市':341300,'六安市':341500,'亳州市':341600,'池州市':341700,'宣城市':341800,
                '福州市':350100,'厦门市':350200,'莆田市':350300,'三明市':350400,'泉州市':350500,'漳州市':350600,'南平市':350700,'龙岩市':350800,'宁德市':350900,
                '南昌市':360100,'景德镇市':360200,'萍乡市':360300,'九江市':360400,'新余市':360500,'鹰潭市':360600,'赣州市':360700,'吉安市':360800,'宜春市':360900,'抚州市':361000,'上饶市':361100,
                '济南市':370100,'青岛市':370200,'淄博市':370300,'枣庄市':370400,'东营市':370500,'烟台市':370600,'潍坊市':370700,'济宁市':370800,'泰安市':370900,'威海市':371000,'日照市':371100,'临沂市':371300,'德州市':371400,'聊城市':371500,'滨州市':371600,'菏泽市':371700,
                '郑州市':410100,'开封市':410200,'洛阳市':410300,'平顶山市':410400,'安阳市':410500,'鹤壁市':410600,'新乡市':410700,'焦作市':410800,'濮阳市':410900,'许昌市':411000,'漯河市':411100,'三门峡市':411200,'南阳市':411300,'商丘市':411400,'信阳市':411500,'周口市':411600,'驻马店市':411700,'济源市':419001,
                '武汉市':420100,'黄石市':420200,'十堰市':420300,'宜昌市':420500,'襄阳市':420600,'鄂州市':420700,'荆门市':420800,'孝感市':420900,'荆州市':421000,'黄冈市':421100,'咸宁市':421200,'随州市':421300,'恩施土家族苗族自治州':422800,'仙桃市':429004,'潜江市':429005,'天门市':429006,'神农架林区':429021,
                '长沙市':430100,'株洲市':430200,'湘潭市':430300,'衡阳市':430400,'邵阳市':430500,'岳阳市':430600,'常德市':430700,'张家界市':430800,'益阳市':430900,'郴州市':431000,'永州市':4311,'怀化市':431200,'娄底市':431300,'湘西土家族苗族自治州':433100,
                '广州市':440100,'韶关市':440200,'深圳市':440300,'珠海市':440400,'汕头市':440500,'佛山市':440600,'江门市':440700,'湛江市':440800,'茂名市':440900,'肇庆市':441200,'惠州市':441300,'梅州市':441400,'汕尾市':441500,'河源市':441600,'阳江市':441700,'清远市':441800,'东莞市':441900,'中山市':442000,'潮州市':445100,'揭阳市':445200,'云浮市':445300,
                '南宁市':450100,'柳州市':450200,'桂林市':450300,'梧州市':450400,'北海市':450500,'防城港市':450600,'钦州市':450700,'贵港市':450800,'玉林市':450900,'百色市':451000,'贺州市':451100,'河池市':451200,'来宾市':451300,'崇左市':451400,
                '海口市':460100,'三亚市':460200,'三沙市':460300,'儋州市':460400,'五指山市':469001,'琼海市':469002,'文昌市':469005,'万宁市':469006,'东方市':469007,'定安县':469021,'屯昌县':469022,'澄迈县':469023,'临高县':469024,'白沙黎族自治县':469025,'昌江黎族自治县':469026,'乐东黎族自治县':469027,'陵水黎族自治县':469028,'保亭黎族苗族自治县':469029,'琼中黎族苗族自治县':469030,
                '重庆市':500000,
                '成都市':510100,'自贡市':510300,'攀枝花市':510400,'泸州市':510500,'德阳市':510600,'绵阳市':510700,'广元市':510800,'遂宁市':510900,'内江市':511000,'乐山市':511100,'南充市':511300,'眉山市':511400,'宜宾市':511500,'广安市':511600,'达州市':511700,'雅安市':511800,'巴中市':511900,'资阳市':512000,'阿坝藏族羌族自治州':513200,'甘孜藏族自治州':513300,'凉山彝族自治州':513400,
                '贵阳市':520100,'六盘水市':520200,'遵义市':520300,'安顺市':520400,'毕节市':520500,'铜仁市':520600,'黔西南布依族苗族自治州':522300,'黔东南苗族侗族自治州':522600,'黔南布依族苗族自治州':522700,
                '昆明市':530100,'曲靖市':530300,'玉溪市':530400,'保山市':530500,'昭通市':530600,'丽江市':530700,'普洱市':530800,'临沧市':530900,'楚雄彝族自治州':532300,'红河哈尼族彝族自治州':532500,'文山壮族苗族自治州':532600,'西双版纳傣族自治州':532800,'大理白族自治州':532900,'德宏傣族景颇族自治州':533100,'怒江傈僳族自治州':533300,'迪庆藏族自治州':533400,
                '拉萨市':540100,'日喀则市':540200,'昌都市':540300,'林芝市':540400,'山南市':540500,'那曲市':540600,'阿里地区':542500,
                '西安市':610100,'铜川市':610200,'宝鸡市':610300,'咸阳市':610400,'渭南市':610500,'延安市':610600,'汉中市':610700,'榆林市':610800,'安康市':610900,'商洛市':611000,
                '兰州市':620100,'嘉峪关市':620200,'金昌市':620300,'白银市':620400,'天水市':620500,'武威市':620600,'张掖市':620700,'平凉市':620800,'酒泉市':620900,'庆阳市':621000,'定西市':621100,'陇南市':621200,'临夏回族自治州':622900,'甘南藏族自治州':623000,
                '西宁市':630100,'海东市':630200,'海北藏族自治州':632200,'黄南藏族自治州':632300,'海南藏族自治州':632500,'果洛藏族自治州':632600,'玉树藏族自治州':632700,'海西蒙古族藏族自治州':632800,
                '银川市':640100,'石嘴山市':640200,'吴忠市':640300,'固原市':640400,'中卫市':640500,
                '乌鲁木齐市':650100,'克拉玛依市':650200,'吐鲁番市':650400,'哈密市':650500,'昌吉回族自治州':652300,'博尔塔拉蒙古自治州':652700,'巴音郭楞蒙古自治州':652800,'阿克苏地区':652900,'克孜勒苏柯尔克孜自治州':653000,'喀什地区':653100,'和田地区':653200,'伊犁哈萨克自治州':654000,'塔城地区':654200,'阿勒泰地区':654300,
                '石河子市':659001,'阿拉尔市':659002,'图木舒克市':659003,'五家渠市':659004,'北屯市':659005,'铁门关市':659006,'双河市':659007,'可克达拉市':659008,'昆玉市':659009,
                '台湾省':710000,'香港特别行政区':810000,'澳门特别行政区':820000

                }


代码

这个代码运行的话可以直接获取一月份、二月份的数据。三月份由于才过了两天,我就打上了#,因为我有强迫症,三月份到时候再抓了。

# -*- coding: utf-8 -*-
import requests 
import json 
import time
import xlrd
import xlwt
from ChineseAdminiDivisionsDict import CitiesCode

def migration_all_date(areaname,classname,no,direction): #定义生成不同时期,不同城市,不同迁徙方向
    if no == -1 :
        no = CitiesCode[str(areaname)]
    #######创建一个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=str(nameofdire))                 #写入行头
    times = 1
    for key , value in CitiesCode.items():
        worksheet.write(times , 0 , label=str(value))                #写入城市代码
        worksheet.write(times , 1 , label=str(key))                  #写入城市名
        CitiesOrder[str(key)] = times                           #写入城市序号字典 
        times += 1
    ########################设定日期##############################
    datelist = []                                    #日期列表
    counter_data = 2                                 #日期计数器
    for date1 in range(20200101,20200132):           #一月份
        datelist.append(date1)
    for date2 in range(20200201,20200230):           #二月份
        datelist.append(date2)
    #for date3 in range(20200301,20200302):          #三月份
        #datelist.append(date3)
    for date in datelist:                            #遍历所有日期
        datename = date
        time.sleep(1)  
        url=f'http://huiyan.baidu.com/migration/cityrank.jsonp?dt={classname}&id={no}&type=move_{direction}&date={date}'
        print(url)
        time.sleep(0.5)
        response=requests.get(url, timeout=10) #发出请求并json化处理
        time.sleep(0.5)  
        r=response.text[3:-1] #去头去尾
        data_dict=json.loads(r) #字典化
        if data_dict['errmsg']=='SUCCESS':
            data_list=data_dict['data']['list']
            time.sleep(0.3)
            ################写入###############
            worksheet.write(0 , counter_data , label=datename)             #写入表头————日期
            for a in range(len(CitiesCode)):
                worksheet.write(a+1 , counter_data , label=0)              #先把当前日期下该列所有城市值置0
            ############获取数据###########
            for i in range (len(data_list)):
                city_name=data_list[i]['city_name'] #城市名
                value=data_list[i]['value']         #当日迁徙量所占百分比值
            ##############写入#############
                worksheet.write(CitiesOrder[str(city_name)] , counter_data , label=value)             #查找城市序号字典,在对应的行里写入相应的值
            counter_data += 1                                 #日期计数器自加一
    workbook.save(f"{areaname}-{nameofdire}.xls")      #保存


def circu_exe_direction(areaname,classname,no):
    mukous = ['in','out']
    for mukou in mukous:
        migration_all_date(areaname,classname,no,mukou)
    print(str(areaname)+'---','完成')


if __name__=="__main__":
    circu_exe_direction('泰安市','city',-1)
    circu_exe_direction('威海市','city',-1)
    circu_exe_direction('昌吉回族自治州','city',-1)
    circu_exe_direction('福建省','province',350500)
    circu_exe_direction('湖北省','province',420000)
    circu_exe_direction('北京市','province',110000)
    circu_exe_direction('全国','country',0)
    print('全部完成')

我可能需要重点说明一下这个函数migration_all_date(areaname,classname,no,direction),areaname是给你输出的xls文件命名的;classname是填url的;no是城市编码,如果是城市的话就填-1就行了,它就会自己去字典里找,避免手残输错,如果是省份的话就得手动输入,direction是迁徙方向,因为一个城市有两个迁徙方向(迁入和迁出),所以会生成两个xls表。

因为还要手动填direction好麻烦,所以我就又加了circu_exe_direction(areaname,classname,no),具体用法案例如下。

如果要爬取市的数据,直接就circu_exe_direction('泰安市','city',-1)就行了,最后数字填-1它就自己去字典里查对应的城市编码。另外名字一定要填官方的名字,不能多字少字,不然字典找不到,或者可以事先看看字典里怎么写的,反正我按省份分行的,很好查。

如果是省的话,就需要circu_exe_direction('福建省','province',350500),中间要改成province(直辖市也需要改成province),最后的编码要手动输入,不知道编码的百度一下就行。

如果要获取全国数据的话,就需要circu_exe_direction('全国','country',0),注意中间变成了country。


转载:https://blog.csdn.net/Leaze932822995/article/details/104639442
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场