python爬取中国天气网天气图标

python爬取中国天气网天气图标

准备工作

  • 天气预报图例网址:http://www.weather.com.cn/static/html/legend.shtml
  • 安装requests:pip install requests

网页分析

  • 打开网页,可以看到图标有很多,而且分白天和夜间,我们要把图标保存到本地,并且图标名字要对应

在这里插入图片描述

  - 右键查看网页源代码,发现图标和名称都放到 `<td width="12%" ...` 的 **td** 标签下,而我们要做的就是提取其中的图片和名称
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200107142815884.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDc3NTU0OA==,size_16,color_FFFFFF,t_70)

编写代码

爬取网页

import requests
url = 'http://www.weather.com.cn/static/html/legend.shtml'
def getPage():
  # 请求头
  headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5383.400 QQBrowser/10.0.1313.400"}
  res = requests.get(url, headers)
  # 手动指定字符编码为utf-8
  res.encoding = 'utf-8'
  print(res.text)
  return res.text
if __name__ == "__main__":
  getPage()
  • requests库的使用方法非常简单,requests.get(网页url) 就可以拿到网页内容了,但是为了模拟浏览器请求,最好还是加上请求头headers
  • requests响应内容:
    res.encoding:可以拿到当前的编码格式,也可以设置编码格式
    res.text:字符串响应体,这里就是网页的源代码
    res.content:二进制的响应体,如果是图片需要用到

    r.encoding                       #获取当前的编码
    r.encoding = 'utf-8'             #设置编码
    r.text                           #以encoding解析返回内容。字符串方式的响应体,会自动根据响应头部的字符编码进行解码。
    r.content                        #以字节形式(二进制)返回。字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩。
    r.headers                        #以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
    r.status_code                    #响应状态码
    r.raw                            #返回原始响应体,也就是 urllib 的 response 对象,使用 r.raw.read()   
    r.ok                             # 查看r.ok的布尔值便可以知道是否登陆成功
    r.json()                         #Requests中内置的JSON解码器,以json形式返回,前提返回的内容确保是json格式的,不然解析出错会抛异常
    r.raise_for_status()             #失败请求(非200响应)抛出异常
  • 爬取下来的网页,打印出来时发现中文乱码了,因此需要指定编码方式为 utf-8

提取图片和名称

import re

# td正则
wrapReg = r'<td width="12%"[^>]*>.*?</td>'
# 图片url正则
imgReg = r'<img src="(.*?)"'
# 天气名称正则
nameReg = r'<a[^>]*>([^>]*?)</a>'
# 颜色正则
colorReg = r'bgcolor="(.*?)"'

def run():
  # 爬取网页
  text = getPage()
  # 拿到td标签里的内容
  lis = re.findall(wrapReg, text, re.S|re.M)
  for item in lis:
    bgcolor = re.findall(colorReg, item, re.S|re.M)
    imgUrl = re.findall(imgReg, item, re.S|re.M)
    nameStr = re.findall(nameReg, item, re.S|re.M)
    if imgUrl and len(imgUrl) > 0 and nameStr and len(nameStr) > 0 and bgcolor and len(bgcolor) > 0:
      print('------------')
      print(imgUrl[0], nameStr[0], bgcolor[0])
  1. 首先我们拿到网页的源码 res.text
  2. 然后正则匹配包裹图片和名称的 td 标签,这里需要匹配包含 td 元素。为什么?后面会有说明

    re.findall(pattern, string, flags=0)
    返回string中所有与pattern匹配的全部字符串,返回形式为数组

    wrapReg = r'<td width="12%"[^>]*>.*?</td>'
    1.一个 . 就 是匹配除 n (换行符)以外的任意一个字符
    2.* 前面的字符出现0次或以上
    3..* 贪婪,匹配从.*前面为开始到后面为结束的所有内容
    4..*? 非贪婪,遇到开始和结束就进行截取,因此截取多次符合的结果,中间没有字符也会被截取
    5.(.*?) 非贪婪,与上面一样,只是与上面的相比多了一个括号,只保留括号的内容,在这里,如果加上括号,则只返回td标签的子元素,不返回td标签本身

    修饰符     描述
    re.I      使匹配对大小写不敏感
    re.L      做本地化识别(locale-aware)匹配
    re.M      多行匹配,影响 ^ 和 $
    re.S      使 . 匹配包括换行在内的所有字符
    re.U      根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
    re.X      该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
  3. 循环 td 标签列表,继续用正则匹配 td 标签里的 图片url天气名称,td 标签下还有 p > a 标签包裹,图片只需要img 标签 src 属性里面的内容,而天气名称是拿整个 a 标签里的内容,这里注意看括号的位置
    在这里插入图片描述
    在这里插入图片描述
  4. 最后就可以根据图片url和天气名称下载保存图片了,但是还有个问题需要注意,把网页拉到下面发现,td 标签里面可能是空的,因此需要判断是否有正确匹配才继续

在这里插入图片描述

  1. 另外,还需要匹配一个 td 的属性,bgcolor ,这个也会在后面说明

下载保存图片

# 后缀正则
suffixReg = r'\.([^.]*?)$'
def saveFile(url, name, bgcolor):
  # 获取后缀
  suffix = re.findall(suffixReg, url)
  # 下载文件
  res = requests.get(url)
  # 根据bgcolor区分白天和黑夜文件路径
  filePath = 'day/' if bgcolor == '#FEE6C5' else 'night/'
  print('filePath --> ', filePath)
  # 文件名
  fileName = filePath + name + '.' + suffix[0]
  with open(fileName, 'wb') as f:
    # 保存文件
    f.write(res.content)
    f.close
  • 前面提到,为什么要匹配包含 td 标签以及 bgcolor 有啥用?去掉 td 标签本身不是更简洁?这是因为白天夜间 的天气名称是一样的,如果不分白天夜间,那么保存了白天的图片,程序执行到保存夜间图片的时候,会把白天的图片替换掉。而白天和夜间的图片和名称正则都是相同的,有什么办法来区分白天和黑夜?
  • 回去看源代码,发现了白天和黑夜 td 标签有个属性,白天的 bgcolor="#FEE6C5",而夜间的 bgcolor="#D8E7F8",因此就可以用这个属性来区分,分别将白天图片保存到 day目录下,夜间图片保存到 night目录。需要在当前路径下新建day 和 night 文件夹,否则会报错
  • 另外,保存图片的时候只有图片名称,没有图片后缀,而图片url又刚好有图片的后缀,所以就可以根据图片url的后缀来确定文件的后缀

完整代码

Image placeholder
LiJie123
未设置
  35人点赞

没有讨论,发表一下自己的看法吧

推荐文章
如何使用 Python 和 BeautifulSoup 爬取网站

互联网上的信息如此之多,任何人穷其一生也无法全部消化吸收。你需要的不是访问这些信息,而是一种可伸缩的方式,可以用来收集、组织和分析这些信息。你需要的是Web爬取。Web爬取可以自动提取数据,并以一种

Python 教程-了解Python

什么是Python Python能干什么? 有什么特点? 什么是Python 官方介绍: Python是一个易于学习、功能强大的编程语言。它拥有高效高级的数据结构和一种简单有效的面向对象编程的

Python 教程-Python 安装

在Windows上安装 访问https://www.python.org/downloads/并下载最新版本。在撰写时当前最新是3.8。在安装的时候和其他软件一样,无脑式下一步。需要注意的是如果在W

Python入门教程_2. 使用 Python 解释器

2.1.调用解释器 Python解释器通常安装在目标机器上的/usr/local/bin/python3.7目录下;把/usr/local/bin目录放进你的Unixshell的搜索路径里,确保它可以

Python入门教程_3. Python 简介

在下面的例子中,输入和输出分别由大于号和句号提示符(>>>和...)标注:如果想重现这些例子,就要在解释器的提示符后,输入(提示符后面的)那些不包含提示符的代码行。需要注意的是在练习中遇到的从属提示符

Python入门教程_4. 深入 Python 流程控制

除了刚刚介绍的while语句,Python还有一些在其他语言中常见的控制流语句,并做了一些改动。 4.1.if语句 也许最著名的语句是if语句了。 例如: >>>x=int(input("Please

【python测试开发栈】帮你总结python random模块高频使用方法

随机数据在平时写python脚本时会经常被用到,比如随机生成0和1来控制逻辑、或者从列表中随机选择一个元素(其实抽奖程序也类似,就是从公司所有人中随机选择中奖用户)等等。这篇文章,就帮大家整理在pyt

流畅的Python读书笔记 --- 第一章 Python数据模型

近期开始读“流畅的Python”这本书,想把自己的读书笔记分享给大家,希望能帮到也对这本书感兴趣但是没时间看的各位。(文章中大部分的话和图片摘录总结自“流畅的Python”一书,以及python官方网

【python测试开发栈】帮你总结python time模块高频使用方法

在平时写python脚本时,时间是我们经常用到的数据,比如:时间戳、前端展示的对应格式的时间等,在python中主要有三个和时间处理相关的模块:time、datetime、calendar,这篇文章主

中国AI人才图鉴:59%的中国籍研究员隶属美国研究机构

大数据文摘出品编译:Walker、蒋宝尚研究人员很容易被人们忽略,但不可否认,他们才是所有AI生态系统的核心组成部分。长期以来,中国和美国在人工智能方面的实力对比一直存在争议,但相关的数据支撑较弱。因

超8千Star,火遍Github的Python反直觉案例集!

大数据文摘授权转载作者:SatwikKansal译者:暮晨Python,是一个设计优美的解释型高级语言,它提供了很多能让程序员感到舒适的功能特性。但有的时候,Python的一些输出结果对于初学者来说似

面向回家编程!GitHub标星两万的”Python抢票教程”,我们先帮你跑了一遍

盼望着,盼望着,春节的脚步近了,然而,每年到这个时候,最难的,莫过于一张回家的火车票。据悉,今年春运期间,全国铁路发送旅客人次同比将增长8.0%。达到4.4亿人次,2020年铁路春运自1月10日开始,

CSS小图标不加载问题

CSS小图标不加载问题css小图标不加载的原因:●文件引入不全●css样式丢失(类名填写错误、css文件路径错误)解决方法:1、首先将需要的图标下载下来以下是iconfont下载的图标目录2、将ico

css3有内置图标吗?

css3有内置图标吗?css3没有内置图标,所有的图标都需要用户自己下载后使用。但是我们可以通过设置特殊字符,来实现图标的样式。(推荐学习:CSS视频教程)下面是一个特殊字符来代替图标的案例:

Python 多个return值

多个return值 那如果你想从一个函数里返回两个变量而不是一个呢?新手们有若干种方法。最著名的方法,是使用global关键字。让我们看下这个没用的例子: defprofile(): globalna

python 处理多个异常

处理多个异常 我们可以使用三种方法来处理多个异常。 第一种方法需要把所有可能发生的异常放到一个元组里。像这样: try: file=open('test.txt','rb') except(IOErr

python *args 的用法

*args的用法 *args和**kwargs主要用于函数定义。你可以将不定数量的参数传递给一个函数。 这里的不定的意思是:预先并不知道,函数使用者会传递多少个参数给你,所以在这个场景下使用这两个关键

python **kwargs 的用法

**kwargs的用法 **kwargs允许你将不定长度的键值对,作为参数传递给一个函数。如果你想要在一个函数里处理带名字的参数,你应该使用**kwargs。 这里有个让你上手的例子: defgree

Python 使用 CTypes调用 C 方法

CTypes Python中的ctypes模块可能是Python调用C方法中最简单的一种。ctypes模块提供了和C语言兼容的数据类型和函数来加载dll文件,因此在调用时不需对源文件做任何的修改。也正

Python/C API

Python/CAPI Python/CAPI可能是被最广泛使用的方法。它不仅简单,而且可以在C代码中操作你的Python对象。 这种方法需要以特定的方式来编写C代码以供Python去调用它。所有的P

SWIG-Python中调用C代码的另一种方法

SWIG SWIG是SimplifiedWrapperandInterfaceGenerator的缩写。是Python中调用C代码的另一种方法。在这个方法中,开发人员必须编写一个额外的接口文件来作为S

Python 容器 Collections

容器(Collections) Python附带一个模块,它包含许多容器数据类型,名字叫作collections。我们将讨论它的作用和用法。 我们将讨论的是: defaultdict counter

python __slots__ 魔法

在Python中,每个类都有实例属性。默认情况下Python用一个字典来保存一个对象的实例属性。这非常有用,因为它允许我们在运行时去设置任意的新属性。 然而,对于有着已知属性的小类来说,它可能是个瓶颈

python set (集合)数据结构

set(集合)是一个非常有用的数据结构。它与列表(list)的行为类似,区别在于set不能包含重复的值。这在很多情况下非常有用。例如你可能想检查列表中是否包含重复的元素,你有两个选择,第一个需要使用f

python 协程

Python中的协程和生成器很相似但又稍有不同。主要区别在于: 生成器是数据的生产者 协程则是数据的消费者 首先我们先来回顾下生成器的创建过程。我们可以这样去创建一个生成器: deffib():

{