python爬虫入门,获取全国气象站24小时整点气象数据(二)

python爬虫入门,获取全国气象站24小时整点气象数据(一)
python爬虫入门,获取全国气象站24小时整点气象数据(二)
上一节我们已经成功获取了单个城市的天气数据,接下来我们就要扩展到获取全国所有城市地区的气象数据,很简单,一步一步来。

3.将数据存储到数据库

我们的目标是收集全国所有气象站每天24小时整点数据,数据量很大,所以需要将数据存储到数据库中。我们选择sqlite
对应的python库是sqlite3
首先建立数据库
数据库设计如下

  • 地区编码,positionId,int
  • 地区名,name,text
  • 小时,date_time,date
  • 温度,temperature, int
  • 降雨量,rain,int
  • 相对湿度,humidity,int
  • 风向,windDirection,int
  • 风速,windPower,int
  • 全名,fullName,text
  • 插入时间,createTime,text

建库建表代码:

import sqlite3
conn = sqlite3.connect("demo.db")  #直接在同级目录下创建名为demo的数据库
c = conn.cursor()
c.execute('''create table weather
            (positionId int not null,
            name text not null,
            date_time date not null,
            temperature int,
            rain int,
            humidity int,
            windDirection int,
            windPower int,            
            fullName text not null,
            createTime text not null DEFAULT (datetime('now','localtime')));''')

各个字段都在上一节获取到了。我们还需要获取fullname字段,地区全名,即如图所示的湖北>武汉>城区。
python爬虫入门,获取全国气象站24小时整点气象数据(二)_第1张图片

需要再写个函数获取:

def getPositionName(soup, num):  #soup:beautiful的soup对象,num城市编码
    position_name = soup.find(class_="crumbs")
    name = []
    for i in range(len(position_name.find_all("a"))):
        name.append(position_name.find_all("a")[i].text)
    name.append(position_name.find_all("span")[len(position_name.find_all("span"))-1].text)
[0].text, position_name.find_all("a")[1].text,position_name.find_all("span")[1].text,position_name.find_all("span")[2].text
    name_str = "-".join(name)
    return name_str

数据库建好了,下面编写代码将数据写入表中。先将节爬虫代码抽象成函数spider:

def spider(url,num): #url,num:城市编码
    html = urllib.request.urlopen(url).read()
    soup = BeautifulSoup(html,'html.parser',from_encoding='utf-8')
    res_data = soup.findAll('script')
    weather_data = res_data[4]
    fullName = getPositionName(soup, num)
    for x in weather_data:
        weather1 = x
    index_start = weather1.find("{")
    index_end = weather1.find(";")
    weather_str = weather1[index_start:index_end]
    weather = eval(weather_str)
    weather_dict = weather["od"]
    weather_date = weather_dict["od0"]
    weather_position_name = weather_dict["od1"]
    weather_list = list(reversed(weather["od"]["od2"]))

    #将数据存入数据库
    save_in_db(num,weather_date, weather_position_name, weather_list, fullName)
    return True

将数据存入数据库的函数:

def save_in_db(num,weather_date, weather_position_name, weather_list, fullName):
    insert_list = []
    for item in weather_list:
        #od21小时,od22温度,od26降雨,od24风向,od25风力
        weather_item = {}
        weather_item['time'] = item['od21']
        weather_item['temperature'] = item['od22']
        weather_item['rain'] = item['od26']
        weather_item['humidity'] = item['od27']
        weather_item['windDirection'] = item['od24']
        weather_item['windPower'] = item['od25']
        weather_item['od23'] = item['od23']
        insert_list.append(weather_item)
    conn = sqlite3.connect("demo.db")
    c = conn.cursor()
    for item in insert_list:
        c.execute("insert into weather (positionId,name,date_time,temperature,rain,humidity,windDirection,windPower,fullName) \
            values(?,?,?,?,?,?,?,?,?)",(num,weather_position_name,item['time'],item['temperature'],item['rain'],item['humidity'],item['windDirection'],item['windPower'],fullName))
    conn.commit()
    conn.close()

使用武汉的url测试一下

if __name__ == "__main__":
    spider("http://www.weather.com.cn/weather1d/101200101.shtml",101200101)

让我们看看数据库,已经成功写入了24个整点的天气数据
python爬虫入门,获取全国气象站24小时整点气象数据(二)_第2张图片

4.寻找url规律

接下来就是获取全国的城市地区的数据。
数据来自网页,网页来自url请求。通过观察url,很容易就发现了规律。
http://www.weather.com.cn/weather1d/101200101.shtml
weather1d是1天的数据
101200101是城市编码,比如武汉就是101200101
不同城市的url只有最后的城市编码不一样,让我们观察下其他城市编码

湖北-武汉-城区:101'20'01'01
湖北-武汉-蔡甸:101'20'01'02
湖北-武汉-黄陂:101'20'01'03
湖北-武汉-江夏:101'20'01'05
--
湖北-襄阳-城区:101'20'02'01
--
湖北-江夏-城区:101'20'05'01
--
浙江-杭州-城区:101'21'01'01
--
四川-成都-城区:101'27'01'01
--
日本-札幌:103'56'01'00

大家是不是已经发现规律了,显然编码规律如下

一共九位数xxx'xx'xx'xx
xxx(国家)xxx(省份)xx(城市)xx(地区)

现在知道编码规律了,只需要按规律发送url,即可获取全国所有站点的数据,是不是很棒棒,哈哈!
我用了一个笨办法来遍历url,通过三个while循环来依次递增省份、城市、地区的编码,代码如下:

def start():
    base_url = "http://www.weather.com.cn/weather1d/101" 
    province_num = 1
    while (province_num < 80):
        flag = True
        city_num = 1
        while (city_num < 20):
            position_num = 1
            while (position_num < 30):
                num_str = str(province_num).zfill(2) + str(city_num).zfill(2) + str(position_num).zfill(2)
                url = base_url + num_str + ".shtml"
                time.sleep(2)
                #print(url)
                flag = spider(url, num_str)
                if (flag == False):
                    break
                position_num += 1
                pass
            if (flag == False and position_num == 1):
                break
            city_num += 1
            pass
        if (flag == False and position_num == 1 and city_num == 1):
            break
        province_num += 1    

一切都完成了,下面,爬虫,启动!

if __name__ == "__main__":
    start()

看看数据库
python爬虫入门,获取全国气象站24小时整点气象数据(二)_第3张图片

看看全国一天大概会产生多少数据呢,今天的最低温度是多少呢

select count(DISTINCT positionid) from weather  --全国一共有多少地区
select count(*) from weather --全国一天产生的数据量
select * from weather where temperature = (select min(temperature) from weather) --温度最低的地区

结果分别如下:

3024
75600
50705   呼中  7   -36 0   68  东南风 1   黑龙江-大兴安岭-呼中 2018-02-15 21:15:36

可以看到中国天气网大概有3024个地区有天气信息,每天产生75600条数据。
截止到年三十10点,国内最低温度位于黑龙江-大兴安岭-呼中,达到了零下36度,真是瑟瑟发抖呀。

5.总结

  • 地址编码的遍历代码写的太笨,而且有地区遗漏,比如直辖市和景点。可以有更好的实现。
  • 网页解析代码部分,由于我挖了一下坑,可能无法完美运行,需要的同学可以私信讨论。
  • 数据库的data_time字段目前只是小时,可以扩展成时间戳,方便之后的分析。

你可能感兴趣的:(python爬虫入门,获取全国气象站24小时整点气象数据(二))