python学习之路——爬虫天气预报

博主学习Python后,决定爬取天气预报数据。介绍了用到的selenium、time等模块,阐述了用类实现爬虫的过程,包括构造函数定义、驱动下载、页面操作、数据循环获取与处理等,还提及因页面动态加载,最终选用selenium,源码可在github获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

 抱着《python学习手册》啃了很久,心里想着要动手写点东西,但是一直拖延症到最近才真正开始准备。一开始不知道写点啥好,就从生活中挖掘,发现自己每天查天气预报查的挺频繁的,那就爬一波天气预报吧。

技术概览

  1. selenium
  2. time
  3. re
  4. calendar
     爬取网页数据的过程中就用到以上4个模块,其中calendar是可选的,最初的版本是只爬取当月的每日天气所以不需要calendar,后续新增了可选月份的功能,才加上calendar。本次爬虫是用类来实现的,但实际上用简单函数即可,但抱着学以致用的想法还是用类吧,虽然类有很多很强大的功能(继承、多态、定制等),但在我这几十行的代码里并不能体现出来。我的环境是win10+python27,因为工作需要所以个人PC也是python2的,后续会更新成python3。

具体内容

class Weather(object):
    def __init__(self):
        self.day = time.strftime('%d', time.localtime(time.time()))
        self.month = time.strftime('%m', time.localtime(time.time()))

 在类的开始定义了一个构造函数,里面有两个属性:day和month分别是今天的日期和当月月份,这里就用到time模块中的time、localtime、strftime。详细的介绍可以看菜鸟教程,我们现场实践下。
1695897-20190524215147411-217584005.png
 这里先导入time模块,然后time.time()是当前时间的一个时间戳,需要用localtime()格式化成time.struct_time类型的对象。(struct_time是在time模块中定义的表示时间的对象)然后再用strftime()接收struct_time对象,返回一个字符串表示的时间值,如图所示,我码字的时候正是5月23号。

    def get_weather_html(self):
       #打开中国天气网的40天天气预报的网页,爬取数据
       url = 'http://www.weather.com.cn/weather40d/101020100.shtml'
       driver = webdriver.Chrome()
       driver.get(url)
       driver.maximize_window()
       driver.implicitly_wait(3)
       month_input = raw_input('please input month:')
       if month_input != '' and month_input != self.month:
           self.select_month(month_input,driver)

 如果想用selenium的话,要先下个驱动下载地址我用的是谷歌浏览器,所以对应的驱动是cromedriver.exe,注意驱动跟版本强相关,没有下对版本的话就会报错。驱动放在python.exe同目录下即可。上面代码主要做的事情就是:

  1. 创建浏览器的实例driver
  2. 打开中国天气网
  3. 将浏览器最大化
  4. 等待页面加载完成
  5. 等待用户输入期待爬虫的月份
  6. 如果输入的月份不是当前月份或者不是空字符串(不输入月份直接回车就是空字符串),则调用select_month

 这里要强调下implicitly_wait作为隐式等待可以在页面元素找到的时间提前退出等待,但是这里设置的全局的等待时候,假设代码里的路径有错或者其他什么问题,会导致调试时间变长。也可以使用time.sleep(3)这种显式等待,设3s就是等待3s,不管元素找到与否。selenium-python里有很多selenium的详细介绍,关于显示等待和隐式等待的也有。

    def select_month(self, month, driver):
        driver.find_element_by_xpath('//*[@class="zong"]').click()
        month_path = '//div[@class="w_nian"]/ul[2]/li['+month+']'
        driver.find_element_by_xpath(month_path).click()
  1. 点击打开网页上选择月份的弹框
  2. 创建用户需要的月份的路径
  3. 点击该月份
    xpath安装详见左边链接,亲测可用。这里需要用到xpath相关的知识,w3school、菜鸟教程上有很多很详细的这里就不赘述。让我们动手实践下:
    1695897-20190524215224308-696692558.png
    图片文字显示不全,1、打开开发者模式,用这个小箭头点你要的元素。2、这里找到元素对应的位置。
for week_index in range(2,8):
    for day_index in range(1,8):
        week = str(week_index)
        day = str(day_index)
        day_path = '//*[@id="table"]/tbody/tr['+week+']/td['+day+']/h2/span[2]'
        max_temp_path = '//*[@id="table"]/tbody/tr['+week+']/td['+day+']/div[1]/p/span[1]'
        min_temp_path = '//*[@id="table"]/tbody/tr['+week+']/td['+day+']/div[1]/p/span[2]'
        date = driver.find_element_by_xpath(day_path)
        date = date.text
        try:
            date_int = int(date)
        except(ValueError):
            break
        if month_input == '':
            month = self.month
        else:
            month = month_input
        if date_int == 01 and week_index != 2:
            print u'19年{}月每日温度情况如下'.format(month)
            break
        max_temp = driver.find_element_by_xpath(max_temp_path)
        min_temp = driver.find_element_by_xpath(min_temp_path)
        max_temp = re.findall('\d+', max_temp.text)
        min_temp = re.findall('\d+', min_temp.text)
  1. 循环获取数据
  2. 创建日期,最高温,最低温的xpath路径
  3. 获取路径里的文本信息
  4. 路径获取不到正确的信息或者匹配到下个月的1号就跳出循环
  5. 用正则把温度中的数字取出来
     emm这里就是爬数据处理数据的主要逻辑了,因为天气预报上40天的显示是按日历来的,跟周数,星期数相关,于是这里用了嵌套的循环,但是因为月份的不同,周数有变化,我这里就写死range(2,8)(html数据从2开始到6或者7,range不包括8),有的月份没有第6周会获取不到元素的时候,强行int会报ValueError,等捕捉到这个错就是数据已经全部获取完可以break了。这里我用字典(key=value)存放日期和温度的对应,因为字典的key是唯一的,所以即使会获取到上个月30号的温度,也会被覆盖。这里还有个问题就是温度显示方式有多种,因此获取温度的xpath不是唯一的,于是我把这部分用try包起来,except捕捉到异常后用另一个xpath去获取,直到取到数据。详见下图
    1695897-20190524215240567-335831352.png
if __name__ == '__main__':
    weather = Weather()
    dict,month = weather.get_weather_html()
    count = 0
    for key in dict.keys():
        monthRange = calendar.monthrange(2019, int(month))
        print u"{name:10d}号:{max}~{min}℃".format(name=key,max=dict[key][0],min=dict[key][1])
        count += 1
        if count == monthRange[-1]:
            break

1695897-20190524215258035-1266251117.png

 最后我们就可以创建类实例,运行方法,打印数据了。提醒下cmd下运行的话,中文字符前要加个u转成Unicode,不然会报错。下图就是最后的运行结果啦。
1695897-20190524215338781-1759418923.png

 其实获取html的方法有很多种页面获取方法,我一开始用了urllib和request都失败了,因为天气预报的页面是动态加载的,而这两个库只能帮助我们获取静态页面,然后我就想试试自己模拟请求,实现动态加载,无奈才疏学浅,最后只能用万能牌selenium。selenium会模拟用户操作,真的在你电脑上打开浏览器然后点点点,这样虽然万能,但是就很慢呐。 以上就是我代码的大部分了,源码的话可以去我的github获取。

转载于:https://www.cnblogs.com/cts2710/p/10920377.html

### 使用Python编写天气预报程序 以下是基于Python编写的天气预报查询系统的实现方式。该系统可以通过输入城市名称返回对应的天气信息。 #### 方法概述 为了简化开发过程,可以采用本地模拟的数据结构(如字典),或者通过第三方API获取实时天气数据。如果需要更复杂的功能,则可引入网络爬虫技术抓取公开网站上的天气信息[^1]。 #### 示例代码:基于字典的简易版天气预报系统 下面是一个简单的例子,展示如何使用Python中的`dict`存储预定义的城市及其对应天气状况: ```python weather_data = { '北京': '晴', '上海': '雨', '广州': '多云', '深圳': '雷阵雨' } def get_weather(city_name): weather = weather_data.get(city_name, None) if not weather: return f"{city_name} 的天气暂无记录" else: return f"{city_name} 当前天气为 {weather}" if __name__ == "__main__": city_input = input("请输入要查询的城市名:").strip() result = get_weather(city_input) print(result) ``` 此脚本允许用户输入任意城市的名称,并打印出其当前假设下的天气状态。对于未收录于列表内的地点,默认提示无法找到相关信息[^1]。 #### 基于API调用的真实世界应用案例 当追求更高的准确性时,建议连接专业的气象服务提供商所提供的RESTful API接口来动态加载最新消息。例如OpenWeatherMap就是一个广泛使用的开源平台之一[^2]。以下是如何配置请求头以及解析JSON响应的一个片段: ```python import requests api_key = "your_api_key_here" # 替换为你自己的API密钥 base_url = "http://api.openweathermap.org/data/2.5/weather?" def fetch_realtime_weather(city_name): complete_url = base_url + "appid=" + api_key + "&q=" + city_name response = requests.get(complete_url) if response.status_code != 200: return f'Error fetching data for {city_name}' json_response = response.json() main_info = json_response['main'] temperature_kelvin = main_info['temp'] temp_celsius = round(temperature_kelvin - 273.15) description = json_response['weather'][0]['description'] return (f'{city_name}: Temperature is approximately ' f'{temp_celsius}°C with conditions described as "{description}".') if __name__ == '__main__': location = input('Enter the name of a city: ') output = fetch_realtime_weather(location) print(output) ``` 注意,在运行以上代码之前,请先注册获得个人专属的API key[^4]。 #### 数据采集扩展——Web Scraping方案简介 除了依赖外部API之外,还可以尝试构建自定义爬虫工具定期访问特定网页提取所需字段。不过这种方法存在一定的法律风险和技术难度,需谨慎行事[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值