【Python爬虫实战入门】:全球天气信息爬取

文章目录

      • 一、爬取需求
      • 二、所需第三方库
        • 2.1 简介
      • 三、实战案例
      • 四、完整代码

一、爬取需求

目标网站http://www.weather.com.cn/textFC/hb.shtml
需求:爬取全国的天气(获取城市以及最低气温)
目标urlhttp://www.weather.com.cn/textFC/hz.shtml

二、所需第三方库

requests
BeautifulSoup4

安装

requestspip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
BeautifulSoup4pip install BeautifulSoup4 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

2.1 简介

requests模块

官方文档https://requests.readthedocs.io/projects/cn/zh-cn/latest/
requests 是 Python 编程语言中一个常用的第三方库,它可以帮助我们向 HTTP 服务器发送各种类型的请求,并处理响应。

  • 向 Web 服务器发送 GET、POST 等请求方法;
  • 在请求中添加自定义标头(headers)、URL 参数、请求体等;
  • 自动处理 cookies;
  • 返回响应内容,并对其进行解码;
  • 处理重定向和跳转等操作;
  • 检查响应状态码以及请求所消耗的时间等信息。

BeautifulSoup4模块

官方文档https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
Beautiful Soup 是一个 可以从 HTML 或 XML 文件中提取数据的 Python 库。它能用你喜欢的解析器和习惯的方式实现 文档树的导航、查找、和修改。

下表描述了几种解析器的优缺点:
在这里插入图片描述
注意:如果一段文档格式不标准,那么在不同解析器生成的 Beautiful Soup 数可能不一样。 查看 解析器之间的区别 了解更多细节。

数据提取之CSS选择器

  • 熟悉前端的同学对 css 选择器一定不会陌生,比如 jquery 中通过各种 css 选择器语法进行 DOM 操作等
  • 学习网站http://www.w3cmap.com/cssref/css-selectors.html

在爬虫中使用css选择器,代码教程

>>> from requests_html import session

# 返回一个Response对象
>>> r = session.get('https://python.org/')

# 获取所有链接
>>> r.html.links
{'/users/membership/', '/about/gettingstarted/'}

# 使用css选择器的方式获取某个元素
>>> about = r.html.find('#about')[0]

>>> print(about.text)
About
Applications
Quotes
Getting Started
Help
Python Brochure

三、实战案例

目标网站:http://www.weather.com.cn/textFC/hb.shtml

思路分析:

  1. 通过find方法,定位的div class=conMidtab2
  2. 通过find_all方法,找所有的tr标签

函数功能

  1. 得到网页源码
  2. 解析数据
  3. 保存数据
  4. 主函数

程序框架

import requests
from bs4 import BeautifulSoup
# 获取网页源码
def get_html():
    pass
# 解析数据
def parse_html():
    pass
# 保存数据
def save_data():
    pass
# 主函数
def main():
    pass

获取网页源码
在主函数中进行传参调用

# 获取网页源码
def get_html(url):
    html = requests.get(url)
    html.encoding = 'utf-8'
    # print(html.text)
    return html.text

# 主函数
def main():
    url = 'http://www.weather.com.cn/textFC/hz.shtml'
    html = get_html(url)
main()

解析数据
get_html函数的返回值(网页源码)作为参数传给parse_html函数

# 主函数
def main():
    url = 'http://www.weather.com.cn/textFC/hz.shtml'
    html = get_html(url)
    parse_html(html)
main()

对于parse_html函数,要将传入的网页源码进行解析,获取我们想要的数据。
在这里插入图片描述
通过观察元素,每一个class="conMidtab2"的div标签就代表一个省份,那么他的父级元素class="conMidtab"的div标签就包含三个省份的天气信息,了解了这些,剩下的我们只需要根据元素之间的关系,一步步提取我们想要的数据即可。

# 解析数据
def parse_html(html):
    # 创建对象
    soup = BeautifulSoup(html, 'lxml')
    conMidtab = soup.find('div', class_="conMidtab")
    tables = conMidtab.find_all('table')
    # print(tables)
    for table in tables:
        trs = table.find_all('tr')[2:]
        # print(trs)
        for index, tr in enumerate(trs):
            tds = tr.find_all('td')
            # print(tds)
            city = list(tds[1].stripped_strings)[0]  # 城市
            temp = tds[-2].string  # 最低气温
            print(city, temp)
        break

在这里插入图片描述
但是,这里出现了一个问题,那就是我们要打印城市信息的时候,只能打印出第一个城市,后面的城市无法打印出来,通过查看元素后我们会发现,除了第一个城市是在第二个td标签里面,其余城市都在第一个td标签里面,所以在这里我们要将循环改一下,同时还要加一个判断,只要是第一个城市就去第二个td标签,其余的取第一个td标签
在这里插入图片描述
想要实现这种效果,我们就要用到一个函数enumerate,这个函数可以将下标和下标对应的值给显示出来。

# 解析数据
def parse_html(html):
    # 创建对象
    soup = BeautifulSoup(html, 'lxml')
    conMidtab = soup.find('div', class_="conMidtab")
    tables = conMidtab.find_all('table')
    # print(tables)
    for table in tables:
        trs = table.find_all('tr')[2:]
        # print(trs)
        for index, tr in enumerate(trs):
            tds = tr.find_all('td')
            # print(tds)
            if index == 0:  # 第一个城市取第二个td标签
                city = list(tds[1].stripped_strings)[0]  # 城市
            else:  # 其余的取第一个td标签
                city = list(tds[0].stripped_strings)[0]  # 城市
            temp = tds[-2].string  # 最低气温
            print(city, temp)

在这里插入图片描述
更换url查看数据信息
在主函数里面去更换url,然后查看打印的数据信息是否正确。运行后发现前面的都是正确的,直到更换到港澳台1地区时就出现了问题。

# 主函数
def main():
    # url = 'http://www.weather.com.cn/textFC/hz.shtml'  # 华中地区
    # url = 'http://www.weather.com.cn/textFC/hb.shtml'  # 华北地区
    url = 'http://www.weather.com.cn/textFC/gat.shtml'  # 港澳台地区
    html = get_html(url)
    parse_html(html)
main()

在这里插入图片描述
在这里插入图片描述
我们发现,我们无法在元素中发现问题,那么我们现在就应该查看一下网页源代码。
在这里插入图片描述
查看网页源代码之后可以发现,他所在的table标签是没有结束标签的,后面的城市的table标签也没有结束标签,这也就导致了数据混乱。
想要解决这个问题,就需要更换一下解析器。上面在提到BeautifulSoup4时的解析器,我们发现html5lib这个解析器拥有最好的容错性。
在这里插入图片描述
下载pip install html5lib

# 解析数据
def parse_html(html):
    # 创建对象
    soup = BeautifulSoup(html, 'html5lib')  # 将lxml换成html5lib
    conMidtab = soup.find('div', class_="conMidtab")
    tables = conMidtab.find_all('table')
    # print(tables)
    for table in tables:
        trs = table.find_all('tr')[2:]
        # print(trs)
        for index, tr in enumerate(trs):
            tds = tr.find_all('td')
            # print(tds)
            if index == 0:  # 第一个城市取第二个td标签
                city = list(tds[1].stripped_strings)[0]  # 城市
            else:  # 其余的取第一个td标签
                city = list(tds[0].stripped_strings)[0]  # 城市
            temp = tds[-2].string  # 最低气温
            print(city, temp)

在这里插入图片描述
页面切换
要实现页面切换首先我们要观察一下不同页面的url

华北:http://www.weather.com.cn/textFC/hb.shtml
东北:http://www.weather.com.cn/textFC/db.shtml
华南:http://www.weather.com.cn/textFC/hn.shtml
华中:http://www.weather.com.cn/textFC/hz.shtml
港澳台:http://www.weather.com.cn/textFC/gat.shtml

我们发现,这些url的不同之处就在于后面的字母的不同,而这些字母又恰好是地区的首字母,那么我们只需要将这些地区的首字母存入到一个列表当中,循环之后就可以实现页面的切换。

# 主函数
def main():
    district = ['hb', 'db', 'hd', 'hz', 'hn', 'xb', 'xn', 'gat']
    # url = 'http://www.weather.com.cn/textFC/hz.shtml'
    # url = 'http://www.weather.com.cn/textFC/hb.shtml'
    for dist in district:
        url = f'http://www.weather.com.cn/textFC/{dist}.shtml'
        html = get_html(url)
        parse_html(html)
main()

数据保存
定义一个全局变量的列表list_data,在解析数据的第二层循环中定义一个字典,将城市和最低气温添加到字典中去,最后将字典添加到list_data列表中。

# 保存数据
def save_data():
    with open('全国天气.csv', 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=('城市', '最低气温'))
        writer.writeheader()
        writer.writerows(list_data)

在这里插入图片描述

四、完整代码

import requests
from bs4 import BeautifulSoup
import csv


list_data = []
# 获取网页源码
def get_html(url):
    html = requests.get(url)
    html.encoding = 'utf-8'
    # print(html.text)
    return html.text


# 解析数据
def parse_html(html):
    # 创建对象
    soup = BeautifulSoup(html, 'html5lib')  # 将lxml换成html5lib
    conMidtab = soup.find('div', class_="conMidtab")
    tables = conMidtab.find_all('table')
    # print(tables)
    for table in tables:
        trs = table.find_all('tr')[2:]
        # print(trs)
        for index, tr in enumerate(trs):
            dic = {}
            tds = tr.find_all('td')
            # print(tds)
            if index == 0:  # 第一个城市取第二个td标签
                city = list(tds[1].stripped_strings)[0]  # 城市
            else:  # 其余的取第一个td标签
                city = list(tds[0].stripped_strings)[0]  # 城市
            dic['城市'] = city
            temp = tds[-2].string  # 最低气温
            dic['最低气温'] = temp
            list_data.append(dic)


# 保存数据
def save_data():
    with open('全国天气.csv', 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=('城市', '最低气温'))
        writer.writeheader()
        writer.writerows(list_data)


# 主函数
def main():
    district = ['hb', 'db', 'hd', 'hz', 'hn', 'xb', 'xn', 'gat']
    # url = 'http://www.weather.com.cn/textFC/hz.shtml'
    # url = 'http://www.weather.com.cn/textFC/hb.shtml'
    for dist in district:
        url = f'http://www.weather.com.cn/textFC/{dist}.shtml'
        html = get_html(url)
        parse_html(html)
    save_data()  # 数据保存

main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/599008.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字孪生技术在垃圾焚烧处理中的可视化应用

在迈向智慧城市的进程中,数字孪生技术在垃圾处理领域展现出了巨大潜力。特别是在垃圾焚烧过程的管理和优化上,数字孪生垃圾焚烧可视化技术已成为一项革命性的进步。 通过 HT 构建虚拟的垃圾焚烧模型,实时映射和模拟实际焚烧过程中的各项关键…

QT+网络调试助手+TCP服务器

一、UI界面设计 二、单线程 代码设计 1、 查找合法的本地地址&#xff0c;用于当作服务器的IP地址 #include <QThread> #include <QTcpSocket> #include <QNetworkInterface> #include <QMessageBox>QList<QHostAddress> ipAddressesList QNe…

抖音短视频矩阵系统技术源头/源代码开发部署/SaaS贴牌/源码api代开发

抖音短视频矩阵系统技术源头/源代码开发部署/SaaS贴牌/源码官方平台api授权代开发 一、短视频矩阵系统源码开发步骤 短视频矩阵系统的源头开发步骤通常包括以下几个关键阶段&#xff1a; 1.需求分析&#xff1a;明确系统的目标用户、功能需求、性能要求等。 2.系统设计&…

bite阶段性测试_数据结构

解决问题之前我们要了解什么是度&#xff0c;特别是二叉树中的度&#xff0c;和图论中的度的定义是不同的 什么是度&#xff1a; 在图论中&#xff0c;一个节点&#xff08;或称为顶点&#xff09;的“度”是指与该节点直接相连的边的数量。度是用来衡量一个节点与其他节点连接…

Python:实现b站登录并保存登录信息(baidu Comate插件帮助我逐行分析代码)

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 &#xff08;目前正在带领大家一起提升认知&#xff0c;感兴趣可以来围观一下&#xff09; &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍 ❤️感谢大家点赞&#x1f44d;&…

O2OA(翱途)支持高斯_openGauss,瀚高_HighGo,磐维_panweidb等各种国产postgres分支数据库接入

O2OA&#xff08;翱途&#xff09;作为一款企业级应用平台&#xff0c;其支持多种数据库系统是其灵活性和可扩展性的重要体现。从MySQL、Oracle到国产的达梦、神州等数据库&#xff0c;再到对PostgreSQL的原生支持&#xff0c;O2OA展现了其对不同数据库环境的良好适应性。特别地…

LeetCode 难题解析 —— 正则表达式匹配 (动态规划)

10. 正则表达式匹配 思路解析 这道题虽然看起来不难理解&#xff0c;但却存在多种可能&#xff0c;当然这种可能的数量是有限的&#xff0c;且其规律对于每一次判别都使用&#xff0c;所以自然而然就想到用 动态规划 的方法啦 接下来逐步分析可能的情况&#xff1a; &#x…

stm32f103zet6_DAC_2_输出电压

实现效果 DAC输出的电压 同过电压表测量电压 1.DAC配置的步骤 初始化DAC时钟。配置DAC的GPIO端口。设置DAC的工作模式&#xff08;例如&#xff0c;是否使用触发功能&#xff0c;是否启用DAC中断等&#xff09;。启动DAC。 2常用的函数 函数 HAL_DAC_Start() - 开启指定…

企业终端安全管理软件有哪些?终端安全管理软件哪个好?

终端安全的重要性大家众所周知&#xff0c;关系到生死存亡的东西。 各类终端安全管理软件应运而生&#xff0c;为企业提供全方位、多层次的终端防护。 有哪些企业终端安全管理软件&#xff1f; 一、主流企业终端安全管理软件 1. 域智盾 域智盾是一款专为企业打造的全面终端…

淘宝商品搜索API:关键字搜索返回值详解与利用

在当今电子商务蓬勃发展的时代&#xff0c;淘宝作为中国最大的在线购物平台之一&#xff0c;拥有海量的商品信息和用户数据。为了更好地满足商家和开发者的需求&#xff0c;淘宝提供了商品搜索API&#xff0c;允许通过关键字搜索来获取商品信息。本文将详细解析淘宝商品搜索API…

LeetCode 每日一题 Day 144-157

2385. 感染二叉树需要的总时间 给你一棵二叉树的根节点 root &#xff0c;二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟&#xff0c;感染 将会从值为 start 的节点开始爆发。 每分钟&#xff0c;如果节点满足以下全部条件&#xff0c;就会被感染&#xf…

抖音小店怎么快速出体验分?分享三种不花一分钱,就能出分的技巧

哈喽~我是电商月月 才做抖音小店&#xff0c;新开的店铺是没有体验分的 没有体验分就没法用猜你喜欢和搜索流量&#xff0c;也没法持续做精选联盟&#xff0c;没体验分店铺就不好出单 于是很多朋友就去网上选择找S分机构&#xff0c;想快速出体验分&#xff0c;但这种方式我…

学习软考----数据库系统工程师24

关系数据库设计基础知识 函数依赖 码 多值依赖 性质

Semi-decentralized Federated Ego Graph Learning for Recommendation

论文概况 本文是2023年WWW的一篇联邦推荐论文&#xff0c;提出了一个半去中心化的联合自我图学习框架。 Introduction 作者提出问题 现有的推荐方法收集所有用户的自我图来组成一个全局图&#xff0c;导致隐私风险。联合推荐系统已被提出来缓解隐私问题&#xff0c;但在客户…

TXT文本高效批量编辑,支持批量将每个单号间的空白行进行删除掉,文本内容管理更方便

TXT文本是一种常用的存储快递单号的数据格式。然而&#xff0c;当TXT文本中存在大量的空白行时&#xff0c;不仅浪费了存储空间&#xff0c;还可能导致批量编辑和查询变得低效。为了解决这一问题&#xff0c;我们推出了高效的TXT文本批量编辑功能&#xff0c;支持批量删除单号间…

EOCR-ELR-30RM7Q电机保护器 施耐德韩国三和

EOCR-ELR-30RM7Q电机保护器 施耐德韩国三和 基于MCU(微处理器)的密集型设计 精确的接地故障保护功能 电力系统和电动机的接地故障保护 零序电流互感器监测接地故障 电流和故障延时单独设定 LED显示电源输入和运行状态 嵌入式安装 EOCR主要产品有电子式电动机保护继电器&#xf…

redis分片java实践、redis哨兵机制实现、redis集群搭建

redis分片java实践 linux安装redishttps://mp.csdn.net/mp_blog/creation/editor/134864302复制redis.conf配置文件成redis1.conf、redis2.conf、redis3.conf 修改redis的端口信息和存pid文件的路径。存pid文件的路径只要不同就行了&#xff0c;没什么特别要求。 指定配置文件…

记录汇川:电磁阀封装

二位电磁阀封装&#xff1a; 中封三位电磁阀封装&#xff1a; HMI&#xff1a;

5.6代码

1.最大公约数 这个题最重要的是要找到一个区间是1&#xff0c;找到之后就可以直接加次数就可以了 #include <bits/stdc.h>using namespace std;main() {long long n,i,j,a0,b,ans99999;cin>>n;long long s[n],dp[n][n];for(i0;i<n;i){cin>>s[i];if(s[i]1…

小程序预览或上传代码时,遇到app.json未找到某个wxml文件的解决方法

uniapp小程序&#xff0c;点击预览或者是上传代码&#xff0c;遇到app.json无法找到某个wxml文件的解决方法&#xff1a;清缓存 问题&#xff1a; message&#xff1a;Error: app.json: 未找到 ["subPackages"][3]["pages"][3] 对应的 subPackages4/pages/…