【对话系统】天气对话机器人 (一) ----- 全国各地天气数据的爬取以及存到数据库中。

这次的事情是老板让做一个对话机器人,先拿天气来练练手。所以首先要有数据吧QAQ。没办法,自己动手,丰衣足食。

顺便说一句,整个天气对话机器人的的初始demo已经弄好了,在我的github里。并且初始的展示平台放到了我的腾讯云学生机上。不过目前还处于人工智障阶段,还需要进一步优化。

好了,废话说完了,下面来正经的。

首先需要搞到全国各地的主要城市地名数据。

然后根据地点数据去天气网站上爬数据

我爬取的主要是两个网站 http://pm25.in/+city 以及 https://www.tianqi.com/city 

参考一些已经有的博客,beautifulsoup4以及正则我都用了,感觉还是bs4方便点。

首先爬取一些PM2.5之类的空气数据以及单日常有的数据,例如湿度啊,风速啊,紫外线啊之类的。

def get_PM25(city):
    try:
        #天气网站地址
        url = "http://pm25.in/"+city
        data = urllib.request.urlopen(url).read().decode("utf-8")
        # print("城市:{}".format(city))

        data_time = '<div class="live_data_time">\s{1,}<p>数据更新时间:(.*?)</p>'
        datatime = re.compile(data_time, re.S).findall(data)

        #先爬PM2.5的
        data_pm25 = '<div class="span1">\s{1,}<div class="value">\n\s{1,}(.*?)\s{1,}</div>'
        data_o3 = '<div class="span1">\s{1,}<div class ="value">\n\s{1,}(.*?)\s{1,}</div>'
        pm25list = re.compile(data_pm25, re.S).findall(data)
        o3list = re.compile(data_o3, re.S).findall(data)
        pm25list.append(o3list[0])

        #再爬一些单日数据
        url = 'https://www.tianqi.com/{}/'.format(city)
        data = urllib.request.urlopen(url).read().decode("utf-8")
        soup = BeautifulSoup(data, 'html.parser')
        li_shidu = soup.find('dd',attrs={'class':'shidu'}).find_all('b')

        #数据保存
        pm_list = {"AQI": pm25list[0]+"μg/m3", "PM25": pm25list[1]+"μg/m3", "PM10": pm25list[2]+"μg/m3", "CO": pm25list[3]+"mg/m3", "NO2": pm25list[4]+"μg/m3",
                   "SO2": pm25list[5]+"μg/m3", "O3": pm25list[6]+"μg/m3",
                   "humidty": li_shidu[0].string.split(":")[1],
                   "wind": li_shidu[1].string.split(":")[1].split()[0],
                   "wind_inten": li_shidu[1].string.split(":")[1].split()[1],
                   "ultra_ray": li_shidu[2].string.split(":")[1],
                   "date": datatime[0]}
        return pm_list
    except urllib.error.URLError as e:
        print("出现URLERROR!一分钟后重试……")
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
        time.sleep(60)
    except Exception as e:
        print(e)
        time.sleep(5)

然后再爬取一周的天气数据:

def get_Weather(city):
    try:
        weatherlist = []
        url='https://www.tianqi.com/{}/'.format(city)
        data=urllib.request.urlopen(url).read().decode("utf-8")
        soup = BeautifulSoup(data,'html.parser')

        li_date = soup.find('ul',attrs={'class':'week'}).find_all('li')
        li_shidu = soup.find('dd', attrs={'class': 'shidu'}).find_all('b')
        li_weather = soup.find('ul', attrs={'class': 'txt txt2'}).find_all('li')
        li_temp = soup.find('div', attrs={'class': 'zxt_shuju'}).find('ul').find_all('li')
        for i in range (len(li_weather)):
            slot = [];
            slot.append({'日期': li_date[i].find('b').string,'星期': li_date[i].find('span').string,'天气':li_weather[i].string,'最高气温': li_temp[i].find('span').string+"℃",'最低气温': li_temp[i].find('b').string+"℃"})
            weatherlist.append(slot)
        return weatherlist

    except urllib.error.URLError as e:
        print("出现URLERROR!一分钟后重试……")
        if hasattr(e,"code"):
            print(e.code)
        if hasattr(e,"reason"):
            print(e.reason)
        time.sleep(60)
        # get_Weather(city)
    except Exception as e:
        print("Exception:"+str(e))
        # time.sleep(10)

爬的时候一定要写try_catch.因为网络会出问题,或者你爬的太快人家网站把你封了,或者出一些乱七八糟的错误都有可能的。

然后就是保存的数据库。

这里我建了两个表,分别是单日数据表以及一周数据表:

城市主键
日期主键
一周数据...
城市主键
单日各项数据......
......

 

 

 

 

用到的是sqllite.本来就不是啥大型数据库系统,也没啥保密的,就不搞视图,密码,索引啥的了。

查询的时候也是直接访问数据库的(话说要是正规的这么做会不会被打死0.0)

建表代码:

def create_dataDB(path):
    conn = sqlite3.connect(path)
    cursor = conn.cursor()
    sql_weather = '''
            CREATE TABLE IF NOT EXISTS weather(
            date text,
            city_name text,
            week text,
            city_pinyin text,
            weather text,
            high_temp text,
            low_temp text,
            primary key (date,city_name)
            )'''

    sql_pm = '''
            CREATE TABLE IF NOT EXISTS pm(
            city text,
            date text,
            AQI text,
            PM25 text,
            PM10 text,
            CO text,
            NO2 text,
            SO2 text,
            O3 text,
            humidty text,
            wind text,
            wind_inten text,
            ultra_ray text,
            primary key(city)
            )'''
    cursor.execute(sql_weather)
    cursor.execute(sql_pm)
    cursor.close()
    print("database has created!")

插入代码:

def insert_weatherdata(path,data,cp,cn):
    try:
        conn = sqlite3.connect(path)
        cursor = conn.cursor()
        for i in range(len(data)):
            cursor.execute(
                '''
                    replace into weather
                                    (date,
                                    city_name,
                                    week,
                                    city_pinyin,
                                    weather,
                                    high_temp,
                                    low_temp)
                    values
                        ('{}','{}','{}','{}','{}','{}','{}')
                '''.format(
                                data[i][0]['日期'],
                                cn,
                                data[i][0]['星期'],
                                cp,
                                data[i][0]['天气'],
                                data[i][0]['最高气温'],
                                data[i][0]['最低气温']
                            )
            )
        conn.commit()
        cursor.close()
        print("{}一周天气数据已经成功插入!".format(cn))
    except Exception as e:
        print(e)

def insert_PMdata(path,data,cn):
    try:
        conn = sqlite3.connect(path)
        cursor = conn.cursor()
        cursor.execute(
                '''
                    replace into pm
                                (city,
                                date,
                                AQI,
                                PM25,
                                PM10,
                                CO,
                                NO2,
                                SO2,
                                O3,
                                humidty,
                                wind,
                                wind_inten,
                                ultra_ray)
                    values
                        ('{}','{}','{}','{}','{}',
                        '{}','{}','{}','{}','{}',
                        '{}','{}','{}')
                '''.format(
                                cn,
                                data.get("date"),
                                data.get("AQI"),
                                data.get('PM25'),
                                data.get('PM10'),
                                data.get('CO'),
                                data.get('NO2'),
                                data.get('SO2'),
                                data.get('O3'),
                                data.get('humidty'),
                                data.get('wind'),
                                data.get('wind_inten'),
                                data.get('ultra_ray'),
                            )
            )
        conn.commit()
        cursor.close()
        print("{}PM最新数据已经成功插入!".format(cn))
    except Exception as e:
        print(e)

这里有一个小问题,就是数据库是可以批量插入的。但我在代码里是爬一条插一条的,以后肯定会改,不然这样也太慢了。

另外,爬虫的时候我设置了随机2-5秒爬一次(不知道是不是太久了),因为之前没设置休息时间被封IP了。。。。。

最后的结果如下:

改进:

目前这样是肯定不满意的啦。首先,数据的爬取和插入就很有问题,之后会改进,定时爬取,统一更新。然后就是开个进程自动更新数据库,不会自己更新天气的,你不是人工智障,谁是人工智障。

改进就不在这里写了,会在github上更新。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值