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字段,地区全名,即如图所示的湖北>武汉>城区。

需要再写个函数获取:

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个整点的天气数据

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()

看看数据库

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

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字段目前只是小时,可以扩展成时间戳,方便之后的分析。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容