简单上手python爬虫实战:阜阳市历史天气数据爬取

        这里我们学校开始了见习,搞的是阜阳市历史天气数据看板,加了点大数据方面的技术栈,我这里就不讲了,出一期非常简单的爬虫代码吧。

1 数据来源

        这里我们用的网站是天气后报里的,网站如下:历史天气查询|天气记录|天气预报|气温查询|过去天气_天气后报http://tianqihoubao.com/        然后选择安徽->阜阳,你就会发现如下页面。

f030b746446b47a080ff6cea25761232.png

 2 数据的爬取

        然后下滑找到历史数据,我们随便找一个月份的数据,点进去,开始检查!

21b9000cfe7049cab14040d1acd73ff8.png

        这里我们找到页面的url,选择网络,我们发现他后面的数字是202301,难道这是一个有规律的页面?在此,我们在随便打开一个月份,看看怎么样!

f4e78db7a926467293d9baae927997e2.png

        看来跟我们想的一样,这确实是一个有规律的页面,网站末尾跟着查询的年份与月份,那我们再把UA复制粘贴一下这个代码不就完成了吗(年轻人你还是太嫩了!)现在我们把初步的代码写出来

for year in range(2020, 2025):
    for j in range(1, 13):
        month = str(j).zfill(2)
        k = f"{year}{month}"
        url = 'http://tianqihoubao.com/lishi/fuyang/month/{}.html'.format(k)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0'
        }
        re = requests.get(url, headers=headers).text
        print(re)

ac5e9d722eae4afd8437528ff25166ef.png 

        最后也是成功获取到了页面 ,最后别忘了加break,不然你懂的。我们现在就可以看看我们需要的数据在哪吧!

e6b2a7ec4a35433bb0f279e23b3f1b03.png

        然后就是获取xpath路径了,让我们一键复制吧!(正则表达式写不了一点)

49b412e6d5bd4c65b65691cf2352f107.png

        然后开始写xpath代码,如下所示。

        tree = etree.HTML(re)
        list_li = tree.xpath('//*[@id="content"]/table/tbody/tr')
        print(list_li)

c7f286c92f944155b3fc22cc65bdf097.png         你会突然发现咋啥都没有呢,是不是xpath路径有问题?还是代码有问题?其实这也就是最狗的一点,我现在就告诉你们,因为这也是反爬的一种机制,因为他的源代码里是没有tbody这个标签的。

fbd96e0176e64121ab534d8158ce0b1f.png

        我们删掉tbody再试试看,就会发现能获取里面的数据

882008da4d154042a056ced635f3c545.png 

        然后我们开始遍历tr里面的每一行内容,看到我们是不需要第一行标签的,剩下的数据都在td下面,并且都是四个值。

2fd766caff754613a619dbc4ff60ef65.png 

        开始获取文档内容,并打印出来。代码如下:

        for li in list_li:
            date = li.xpath('./td[1]/text()')
            print(date)
            weather_condition = li.xpath('./td[2]/text()')
            print(weather_condition)
            max_min_temperature = li.xpath('./td[3]/text()')
            print(max_min_temperature)
            wind_direction = li.xpath('./td[4]/text()')
            print(wind_direction)

 10d81f46797b48cd8063466767bf485c.png

        我们可以发现数据是爬出来了,但是里面的内容咋这么多乱七八糟的东西,那我们把两边的符号都去掉在看看,

        for li in list_li:
            date = li.xpath('./td[1]/text()')
            date = [i.strip().replace('\r\n', '') for i in date]
            print(date)
            weather_condition = li.xpath('./td[2]/text()')
            weather_condition = [i.strip().replace('\r\n', '') for i in weather_condition]
            print(weather_condition)
            max_min_temperature = li.xpath('./td[3]/text()')
            max_min_temperature = [i.strip().replace('\r\n', '') for i in max_min_temperature]
            print(max_min_temperature)
            wind_direction = li.xpath('./td[4]/text()')
            wind_direction = [i.strip().replace('\r\n', '') for i in wind_direction]
            print(wind_direction)

141bfb0c2fe34567b20c01ef68559e44.png        但他中间还是有很多空格存在,这里我们就采用替代,将里面的空格替代成无就行了,最后处理完成的代码如下,

        for li in list_li:
            date = li.xpath('./td[1]/text()')
            date = [i.strip().replace('\r\n', '').replace(' ', '') for i in date]
            print(date)
            weather_condition = li.xpath('./td[2]/text()')
            weather_condition = [i.strip().replace('\r\n', '').replace(' ', '') for i in weather_condition]
            print(weather_condition)
            max_min_temperature = li.xpath('./td[3]/text()')
            max_min_temperature = [i.strip().replace('\r\n', '').replace(' ', '') for i in max_min_temperature]
            print(max_min_temperature)
            wind_direction = li.xpath('./td[4]/text()')
            wind_direction = [i.strip().replace('\r\n', '').replace(' ', '') for i in wind_direction]
            print(wind_direction)

33acfd069fd7407d849bbf2ace0231e4.png

        现在我们就先把数据保存在pandas里面,代码如下,

result = pd.DataFrame(columns=['date', 'weather_condition', 'max_min_temperature', 'wind_direction'])

for year in range(2020, 2025):
    for j in range(1, 13):
        r = pd.DataFrame(columns=['date', 'weather_condition', 'max_min_temperature', 'wind_direction'])
        ...
        for li in list_li:
            ...
            data_to_add = {
                'date': date,
                'weather_condition': weather_condition,
                'max_min_temperature': max_min_temperature,
                'wind_direction': wind_direction
            }
            new_row = pd.DataFrame(data_to_add)
            r = pd.concat([r, new_row], ignore_index=True)
            print(r)
        break
    break

40f1fedba5dd48c794618ef3126f8f97.png        最后也是成功保存下来了,但是他的第一行是空白,这种我们在他遍历完成之后就可以去掉第一行就OK了,然后在拼接一下就可以得到完整的数据了。

        r = r.iloc[1:]
        result = pd.concat([result, r], ignore_index=True)

8f60ef55376549b7b8c1925031a931aa.png 

3 数据的保存

         这里我因为要对接mysql的,所以我就保存在了虚拟机上的mysql了,大家按照自己的需求保存数据吧。

config = {
    'user': 'root',
    'password': '...',
    'host': 'hadoop101',
    'database': 'weather_db',
    'raise_on_warnings': True
}
engine = create_engine(
    f"mysql+pymysql://{config['user']}:{config['password']}@{config['host']}/{config['database']}")
result.to_sql('history_weather', con=engine, if_exists='replace', index=False)

4 完整代码

import requests
from lxml import etree
import pandas as pd
from sqlalchemy import create_engine

result = pd.DataFrame(columns=['date', 'weather_condition', 'max_min_temperature', 'wind_direction'])

for year in range(2020, 2025):
    for j in range(1, 13):
        r = pd.DataFrame(columns=['date', 'weather_condition', 'max_min_temperature', 'wind_direction'])
        if year == 2024 and j == 12:
            continue
        month = str(j).zfill(2)
        k = f"{year}{month}"
        url = 'http://tianqihoubao.com/lishi/fuyang/month/{}.html'.format(k)
        headers = {
            'User-Agent': '...'
        }
        re = requests.get(url, headers=headers).text
        tree = etree.HTML(re)
        list_li = tree.xpath('//*[@id="content"]/table/tr')
        for li in list_li:
            date = li.xpath('./td[1]/text()')
            date = [i.strip().replace('\r\n', '').replace(' ', '') for i in date]
            weather_condition = li.xpath('./td[2]/text()')
            weather_condition = [i.strip().replace('\r\n', '').replace(' ', '') for i in weather_condition]
            max_min_temperature = li.xpath('./td[3]/text()')
            max_min_temperature = [i.strip().replace('\r\n', '').replace(' ', '') for i in max_min_temperature]
            wind_direction = li.xpath('./td[4]/text()')
            wind_direction = [i.strip().replace('\r\n', '').replace(' ', '') for i in wind_direction]
            data_to_add = {
                'date': date,
                'weather_condition': weather_condition,
                'max_min_temperature': max_min_temperature,
                'wind_direction': wind_direction
            }
            new_row = pd.DataFrame(data_to_add)
            r = pd.concat([r, new_row], ignore_index=True)
        r = r.iloc[1:]
        result = pd.concat([result, r], ignore_index=True)
        print(result)
    break


config = {
    'user': 'root',
    'password': '...',
    'host': 'hadoop101',
    'database': 'weather_db',
    'raise_on_warnings': True
}
engine = create_engine(
    f"mysql+pymysql://{config['user']}:{config['password']}@{config['host']}/{config['database']}")
result.to_sql('history_weather', con=engine, if_exists='replace', index=False)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值