全球天气爬取思路及可视化分析

前言

        前些天老师说想要一个人写爬虫,听到这个消息,我直接

                         结果老师说,你给我随便来一个爬虫,写成实验报告发给我,让我看看。

直接把我整不会了,本想装b一波,结果反被制裁。

于是我便干脆直接写个新的(之前写的不想改了),说干就干直接爬天气预报(天气网 (weather.com.cn))。

请各位打开手机,点击天气软件,ok,完结散花

呃呃,好吧,直接开始,为了弘扬爬虫精神(装b),这回我采用了模块化编程,完整代码请参考GitHub库:https://github.com/Rasrea/python-spider

大郎,该喝汤了

        首先明确目标,咱们爬的是全球的天气预报,这就说明,这有点难,所以咱们先爬某一个城市的,我投了三个色子,刚好停在666,所以咱们就先爬舟山吧,挑个简单的时间段,就最近七天吧。定位头文件、获取对应的url....,知道我为什么在题目上加一个“思路”吗?咱们只讲重点。

先上代码:

# 包含数据获取,解析与可视化
def main():
    url = 'http://www.weather.com.cn/weather/101211106.shtml'
    r = requests.get(url, headers=headers)  # 获取HTML
    # 数据清洗
    grouped_weather_lst = bath_data(r)

    # 收集数据,包括时间,天气,温度
    date_time = [item[0] for item in grouped_weather_lst]  # 时间
    weather_day = [item[1] for item in grouped_weather_lst]  # 天气
    temperature = [item[2] for item in grouped_weather_lst]  # 温度

    # 数据可视化
    line_picture(date_time, weather_day, temperature)  # 折线图

这里面包含两个函数bath_data()、line_picture(),一个负责处理数据,一个负责可视化数据。先讲第一个bath_data()。

        劳烦各位打开各自的浏览器,查看网站的源代码,你问我为什么不打开给你们演示?因为我浏览器坏了。

打开后你们应该就会发现天气数据的位置,并使用BeautifulSoup获得,这些字符串都是4个为一组,分别是时间、天气、气温、风级(这个没啥用), 因此我把它们每四个分成一个子列表,到时候存储的时候就so easy了,上代码:

# 清洗数据
def bath_data(r):
    # 先用.content获取原始字节内容,防止出现乱码
    page_content = r.content
    bs = BeautifulSoup(page_content, 'html.parser')  # 设置解析器
    text_r = bs.find('ul', {'class': 't clearfix'})  # 找到天气数据
    t_weather = text_r.text.split('\n')  # 转换字符集
    weather_lst = [i for i in t_weather if len(i) != 0]  # 去除空格
    grouped_weather_lst = [weather_lst[n:n + 4] for n in range(0, len(weather_lst), 4)]  # 要求每四个组成一个子列表
    return grouped_weather_lst

为什么说存储的时候very easy,请看main函数,仅需三行。

# 收集数据,包括时间,天气,温度
    date_time = [item[0] for item in grouped_weather_lst]  # 时间
    weather_day = [item[1] for item in grouped_weather_lst]  # 天气
    temperature = [item[2] for item in grouped_weather_lst]  # 温度

接下来就是可视化了,看第二个函数。

         这个就相对比较简单了,我选择的是折线图,直接上代码吧

def line_picture(date_time, weather_day, temperature):
    # 使用列表推导式进一步处理数据
    max_tem = [int(i.split('/')[0].replace('℃', '')) for i in temperature]  # 最高气温
    min_tem = [int(i.split('/')[1].replace('℃', '')) if len(i.split('/')) == 2
               else int(i.split('/')[0].replace('℃', '')) for i in temperature]  # 最低气温    # 竖排横坐标标签, 加空行符号
    day_lst = [date_time[i].replace('日', '日\n') +
               '\n' + weather_day[i] for i in range(len(date_time))]

    # 可视化数据
    fig = plt.figure(figsize=(12, 8))  # 创建图像对象
    plt.plot(range(len(day_lst)), max_tem, 's-', label='最高气温')  # 最高气温,并防止横坐标出现两个点
    plt.plot(range(len(day_lst)), min_tem, 'o--', label='最低气温')  # 最低气温,同理
    plt.xticks(range(len(day_lst)), day_lst)  # 设置横坐标标签
    plt.legend()  # 显示图例
    # 设置标签
    plt.title('舟山七日天气预报', fontsize=16)
    plt.xlabel('时间和天气', fontsize=14)
    plt.ylabel('温度(℃)', fontsize=14)

    fig.savefig('舟山七日天气预报.png')  # 保存图像
    plt.show()
    print('运行完成!')

在可视化之前,咱们要先再处理一下数据,因为咱们爬的都是字符串,所以需要先把他们转化成数值,这段代码应该很简单,我感觉各位都看得懂,因为我浏览器坏了,所以就不多说了。

如此这般舟山近七天的数据就爬到手了,下面就是想方设法扩展到全球。

 selenium:朕来了

        xdm,咱们如果想要爬取一个地点的天气,当然是自己输入为好,就像这样,先记住它。

    my_site = input('请输入地点:')

因为每个地点都有一个对应的url,因此咱们的思路就是找到my_site对应的网址,然后套刚才爬取舟山的代码就行了,所以咱们的重点就是获得my_site的url。

打开浏览器,可以看到每一个地区对应的url都不一样,如果要硬找其中的规律的话,我可以给你扯一天,因为我也不知道里面有什么规律。这个时候就需要selenium登场了,它在使用之前需要下载对应浏览器的driver,请移步其他大佬的博客查看。

        咱们可以直接定位搜索框,在搜索框中导入my_site,然后回车,来到相应的页面,之后再导出url就行了,话不多说,上代码:

# 寻找搜索框位置
input_box = driver.find_element(By.XPATH, "//input[@type='text']")

# 自定义地址
my_site = input('请输入地点:')
input_box.send_keys(my_site)
input_box.click()
time.sleep(1)

# 打印新的URL
print(driver.current_url)

直接运行——天气网 (weather.com.cn),结果却是原来的网址,有人可能会说,用显示等待,于是我又等了10秒结果还是原来的网址,HTML也是原来的,与my_site没有半毛钱关系,what f**k?

        看来用这个方法获得url是不成了,咱们换个思路。来到浏览器搜索框(浏览器突然好了),我百无聊赖地输入 ‘’舟山”

好奇心驱使我点击‘舟山-浙江’

  

页面跳转了!!!! 

让我们分析一下输入“舟山”后的网页源代码,怎么突然多出来这么一串

其中num="101211101",这不正是舟山网址的标签('http://www.weather.com.cn/weather/101211106.shtml)吗?说明什么?当我们在搜索框输入某个城市时,网站会生成有关该城市的网址,咱们这个时候获取其中的num值,再套http://www.weather.com.cn/weather/{}.shtml模板,不就是my_site的网址了吗。

        新的思路来了,咱们使用selenium首先在搜索框中输入my_site,这个时候再爬起源码(由于没有跳转页面,所以不会遇到第一个思路的情况) ,之后使用正则或其他方法获得num值,最后组合模板,这不就是my_site的网址!

说干就干,上代码:

def get_url():
    # 配置浏览器,并打开网站
    driver = webdriver.Chrome()
    driver.get('http://www.weather.com.cn/')
    # 等待网页加载
    time.sleep(2)

    # 寻找搜索框位置
    input_box = driver.find_element(By.XPATH, "//input[@type='text']")

    # 自定义地址
    my_site = input('请输入地点:')
    input_box.send_keys(my_site)
    input_box.click()
    time.sleep(1)
    html = driver.page_source  # 保存网站源代码

    # 关闭浏览器
    driver.quit()

    # 获取7天数据所对应的网址
    result = re.search('<li.*?num="(.*?)">', str(html)).group(1)
    url = f'http://www.weather.com.cn/weather/{result}.shtml'

        如此下来url就得到了,之后就是套咱们爬取舟山时的代码就ok了。

总结 

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值