首页 > 编程语言 >【python爬虫实战】进阶天气虫虫(过程复盘 & 心得分享)

【python爬虫实战】进阶天气虫虫(过程复盘 & 心得分享)

时间:2024-07-04 20:57:28浏览次数:19  
标签:province city 进阶 虫虫 pinyin list python weather find

程序设计过程里的一些心得:

0. 规模较大的程序,往往都是以更小的功能块搭建起来的。如此,为了提升总体程序的构建效率, 笔者发现分“两步走”会比较高效:

        A. 遇到需要反复调试的功能块,可先在另一程序中逐一单独测试某一功能块(这有助于突出模块本身的细节问题)

        B. 最后像搭积木一样将模块放回主题程序中,进行一些接口性的“磨合”

1. 见招拆招,必备的是灵活的思路

相比于上一篇初代爬虫,进阶爬虫的核心特点在于可以提供未来五天天气情况的预测,而这也是程序实现的关键难点。具体而言有如下两方面:

        A. 如何精准获取:

由于要获取的信息较多较细,观察网页html原码,或者参考编译过程中直接用find_all函数获取的结果不难发现,由于网页原码中标签的重复性较大,通过一次find_all获得的可迭代对象可谓是“鱼龙混杂”。

解决方案多层搜索,缩小目标范围:#以获取list_weather为例

weathers = soup.find_all("td",attrs={"width":"20%", "align":"left"})
list_weather = []
for weather in weathers:#预处理
    weather = weather.find("p")#找到除上述标签外还有标签"p"的
    weather = weather.find("span")#找到除上述标签外还有标签"span"的
    if weather:#排除weather为None的情况
        list_weather.append(weather.string)

AT:find_all返回的对象只可用,且可不断用“find”函数

        B.如何“完美”输出:

笔者在输出这一步碰上一个麻烦:要实现如下的规整输出,就不得不在一次for循环中将日期、气温、天气的值都输出一遍。

但是!麻烦来了,他们三者在find_all后得到的元素个数并不一样,但for循环的更新一次的依据恰恰是根据迭代一次来进行的(迭代一次,for循环进行一次),因此想要实现“优雅“输出大概没有那么容易。

解决方案:预处理

还是以上面的获取list_weather为例,实际上,之所以要专门建立一个list_weather,恰恰是为了将有效元素留在里面,最终list_weather中只留下干净的五个元素。

完整代码如下:

#请求头headers的值需根据电脑信息自行提供哈,具体方法可参考b站视频讲解哈,此处不再赘述

from bs4 import BeautifulSoup
import requests
from pypinyin import pinyin, Style
import time
import os
if __name__ == '__main__':
    headers = { }
    mode = 1
    while mode != -1:
        try:
            os.system("cls")
            mode = 1
            print("----------勇敢虫虫,不怕困难!----------")
            print("~让虫虫爬一会~")
            response = requests.get("http://qq.ip138.com/weather/", headers=headers)
            response.raise_for_status()
            soup = BeautifulSoup(response.content, "html.parser", from_encoding="utf-8")
            provinces = soup.find_all("dd")  
            # 打印所所有城市名
            dict_province = {}
            for idx, province in enumerate(provinces):
                province_text = province.get_text(strip = True)
                print(idx, province_text)
                dict_province.setdefault(idx, province_text)
            
            #接收用户选择省份
            idx_province = int(input("请选择您关注的省对应序号(虫虫只爬得动省份哈, 至于市、区,请期待一下吧~):"))
            province_chosen = dict_province[idx_province]
            # pinyin_province = ' '.join([''.join(pinyin(char, style=Style.NORMAL)) for char in province_chosen])
            pinyin_list_province = []  
            for char in province_chosen:  
                # pinyin函数返回的是一个列表,其中包含了每个音节的列表(对于多音字)  
                # 使用列表推导式将每个音节的列表转换为用空格分隔的字符串  
                pinyin_chars = ' '.join([''.join(py) for py in pinyin(char, style=Style.NORMAL)])  
                pinyin_list_province.append(pinyin_chars)  
            # 最后,使用join函数将所有汉字的拼音连接起来,用空格分隔  
            pinyin_province = ''.join(pinyin_list_province) 
            
    #省份    #访问对应省份网址
            response = requests.get(f"https://qq.ip138.com/weather/{pinyin_province}/", headers=headers)
            soup = BeautifulSoup(response.content, "html.parser")
            cities = soup.find_all("a", attrs={"class", "title"})
            temps = soup.find_all("span", attrs={"class":"temp"})
            weathers = soup.find_all("span", attrs={"class":"weather"})
            dict_cities = {}
            dict_temps = {}
            dict_weathers = {}
            idx = 1
            for city, temp, weather in zip(cities, temps, weathers):
                city_text = city.get_text(strip = True)
                print(idx, city.string)
                dict_cities.setdefault(idx, city_text)
                dict_temps.setdefault(idx, temp)
                dict_weathers.setdefault(idx, weather)
                idx += 1
            #接收用户输入城市
            while mode == 1:
                idx_city = int(input("请选择你要关注的城市对应序号:"))
                city_chosen = list(dict_cities[idx_city])
                city_chosen = ''.join(city_chosen[:len(city_chosen)-4])
                pinyin_list_city = []
                for char in city_chosen:  
                    # pinyin函数返回的是一个列表,其中包含了每个音节的列表(对于多音字)  
                    # 使用列表推导式将每个音节的列表转换为用空格分隔的字符串  
                    pinyin_chars = ' '.join([''.join(py) for py in pinyin(char, style=Style.NORMAL)])  
                    pinyin_list_city.append(pinyin_chars)  
                # 最后,使用join函数将所有汉字的拼音从列表中提取出来并连接起来,用空格分隔  
                pinyin_list_city = pinyin_list_city[:len(pinyin_list_city)]#去掉末尾“天气预报”对应拼音
                pinyin_city = ''.join(pinyin_list_city) 
                city_temp = dict_temps[idx_city]
                city_weather = dict_weathers[idx_city]
                print("\n找到啦:\n{0}市今日{1},温度{2}".format(city_chosen, city_weather.string, city_temp.string))
                time.sleep(2)
                mode = int(input("天气虫虫:看完了这座城,接下来要俺做什么嘞?(请输入:-1:结束一切程序/ 0:看看别的省(市、区)/1:看看本省的其他城市)/2:了解下当前城市未来五天天气发展情况 :"))
                if mode == 2:
                    response = requests.get(f"https://qq.ip138.com/weather/{pinyin_province}/{pinyin_city}.htm", headers=headers)
                    soup = BeautifulSoup(response.content, "html.parser")
                    dates = soup.find_all("p", attrs={"class":"date"})
                    weathers = soup.find_all("td",attrs={"width":"20%", "align":"left"})
                    # weather = weathers.f
                    temperatures = soup.find_all("td", attrs={"width":"15%", "align":"center"})
                    list_weather = []
                    for weather in weathers:#预处理
                        weather = weather.find("p")
                        weather = weather.find("span")
                        if weather:
                            list_weather.append(weather.string)
                    print(f"--------好滴~未来五天,{city_chosen}天气情况见下哦--------")
                    print("日期".ljust(len("2024-07-01")), "气温".ljust(len("20℃ ~ 28℃ ")), "天气")
                    for date, temp, wehather in zip(dates, temperatures, list_weather):
                        print(date.string, end=" | ")
                        temp = temp.find("p")
                        print(temp.string, end=" | ")
                        print(weather.string)
                    time.sleep(5)
                    mode = int(input("看完了这座城,接下来要我做什么嘞?(请输入:-1:结束一切程序/ 0:看看别的省(市、区)/1:看看本省的其他城市 :"))
                        

        except requests.RequestException as ex:
            print(f"网络错误:{ex}")

在vscode上运行可实现如下输出:

~ 本文是笔者超级用心写的,衷心希望能给你带来些许启发! ~

标签:province,city,进阶,虫虫,pinyin,list,python,weather,find
From: https://blog.csdn.net/H13420972436/article/details/140111804

相关文章

  • 2024 年第十四届 APMCM 亚太杯 数学建模 A题 飞行器外形的优化问题 详细代码+思路+mat
     比赛期间24小时内半价,思路会结合chatgpt-4,都是个人比赛思路,可能不是很好,但是24年所有数学建模思路都会发布到这一个专栏内,只需订阅一次,感谢大家的一直支持!!!A题飞行器外形的优化问题飞行器是在大气层内或大气层外空间飞行的器械。飞行器可以分为:航空器、航天器、火箭和导......
  • 2024年亚太杯数学建模竞赛 APMCM C题 基于量子计算的物流配送问 详细思路+matlab代码+
     比赛期间24小时内半价,思路会结合chatgpt-4,都是个人比赛思路,可能不是很好,但是24年所有数学建模思路都会发布到这一个专栏内,只需订阅一次,感谢大家的一直支持!!!        随着电子商务的迅猛发展,电商平台对物流配送的需求日益增长。为了确保货物能够按时、高效地送达消费......
  • Python分支
    一、顺序结构    顺序结构是计算机程序中的一种基本的控制结构,它指示计算机按照代码的顺序依次执行每一条语句。这种结构下,程序从第一条语句开始执行,然后按照顺序依次执行下一条语句,直到执行完所有语句或遇到其他控制结构为止。    顺序结构的特点是简单直观......
  • Python基于PyQt5和卷积神经网络分类模型(ResNet50分类算法)实现生活垃圾分类系统GUI界
    说明:这是一个机器学习实战项目(附带数据+代码+文档+视频讲解),如需数据+代码+文档+视频讲解可以直接到文章最后获取。1.项目背景在当今社会,随着人们对环境保护意识的增强以及科技的快速发展,智能化的垃圾分类系统成为了一个热门的研究方向。结合深度学习技术,尤其是先进的图像识......
  • python中如何写ssh登录
    python实现ssh远程登录# 测试过程中,比较常用的操作就是将DUT(待测物)接入网络中,然后远程操控对DUT,# 使用SSH远程登陆到主机,然后执行相应的command即可# python 代码如下:# paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的......
  • python怎么样将一段程序无效掉
    1、python中可以用注释屏蔽一段语句,具体方法如下,首先打开一段python的示例程序:2、然后单行注释的方法是在语句前面加上#,程序运行后添加注释的地方的语句会被自动跳过,这里可以看到将打印变量a的语句添加注释就没有打印出结果:3、最后如果有一列连续的语句需要注释,可以不......
  • 【python】Tkinter 图形用户界面
    #导入Tkinter模块,它是Python的标准GUI库importtkinter#创建一个Tkinter的根窗口对象,这是所有其他GUI元素的容器top=tkinter.Tk()#设置窗口的标题top.title('单线程')#设置窗口的初始大小和位置。这里指定了宽度为200像素,高度为150像素top.g......
  • Python性能测试框架:Locust实战教程
    01认识Locust  Locust是一个比较容易上手的分布式用户负载测试工具。它旨在对网站(或其他系统)进行负载测试,并确定系统可以处理多少个并发用户,Locust在英文中是蝗虫的意思:作者的想法是在测试期间,放一大群蝗虫攻击您的网站。当然事先是可以用Locust定义每个蝗虫(或测试用......
  • python爬虫3-多进程多线程协程
    多进程和多线程frommultiprocessingimportProcessimportthreadingdefprocess_worker():foriinrange(200):print(f"Processworker{i}")defthread_worker():foriinrange(200):print(f"Threadworker{i}")if__......
  • Python的分支结构的教学
    一.pass的介绍:1、pass在执行过程中表示的含义:“暂时跳过”,pass是一种空操作,解释器执行到它的时候,除了检查语法是否合法,什么也不做就直接跳过。它跟return、break和continue之类的非空操作相比,最大的区别是它不会改变程序的执行顺序。它就像我们写的注释,除了占用一行代码......