Python简单爬虫实践案例
学习目标
能够知道Web开发流程
能够掌握FastAPI实现访问多个指定网页
知道通过requests模块爬取图片
知道通过requests模块爬取GDP数据
能够用pyecharts实现饼图
能够知道logging日志的使用
一、基于FastAPI之Web站点开发
FastAPI是一个高性能、易于使用、快速编写API的现代Web框架。它基于Python3.6+的新特性(如类型标注、异步支持、协程等),对性能和开发速度进行了优化,支持异步编程,可以轻松地创建具有高性能的API服务。
FastAPI的主要特点包括:
1. 快速:FastAPI的请求响应速度非常快,相比其他框架甚至能快几倍。
2. 易于使用:FastAPI的API设计类似于Flask,提供了简单易用的路由和参数解析。同时,它的类型标注功能使开发更加可靠,易于维护。
3. 异步支持:FastAPI完全支持异步编程模式,利用Python 3.6以上版本的async/await关键字,使得复杂的I/O操作变得非常简单。
4. 自动生成API文档:FastAPI基于OpenAPI标准,自动生成并提供了优美的API文档,无需手动编写文档。
5. 安全性:FastAPI完全支持OpenID Connect 和OAuth2规范,提供安全的认证方式,同时支持JWT和Bearer Token。
1、基于FastAPI搭建Web服务器
搭建基于FastAPI的Web服务器的具体步骤如下:
安装FastAPI和uvicorn:
创建一个Python文件,例如main.py,并导入必要的模块:
创建一个FastAPI应用实例:
定义一个路由处理函数,用于处理HTTP请求:
启动Web服务器:
在命令行中运行Python文件,启动Web服务器:
访问http://localhost:8000/,应该能够看到返回的JSON数据{"Hello": "World"}。
以上就是使用FastAPI搭建Web服务器的基本步骤。你可以根据需要添加更多的路由处理函数和业务逻辑。 接下来我们来看一个具体的例子:
运行结果:

2、Web服务器和浏览器的通讯流程
实际上Web服务器和浏览器的通讯流程过程并不是一次性完成的, 这里html代码中也会有访问服务器的代码,比如请求图片资源。 Web服务器和浏览器的通讯流程一般如下:
浏览器向Web服务器发送HTTP请求。
Web服务器接收到请求后,根据请求的内容生成相应的HTTP响应。
Web服务器将HTTP响应返回给浏览器。
浏览器接收到HTTP响应后,解析响应内容并渲染页面。
如果页面中包含其他资源(如图片、CSS、JavaScript等),浏览器会再次向Web服务器发送请求获取这些资源,并重复上述流程。
在这个过程中,HTTP协议是Web服务器和浏览器通信的基础。 我们来看一个具体的例子:

那像0.jpg、1.jpg、2.jpg、3.jpg、4.jpg、5.jpg、6.jpg这些访问来自哪里呢 ?
答:它们来自index.html

3、浏览器访问Web服务器的通讯流程

浏览器访问Web服务器的通讯流程:
浏览器 (127.0.0.1/index.html) ==> 向Web服务器请求index.html
Web服务器 (返回index.html) ==> 浏览器
浏览器解析index.html发现需要0.jpg ==>发送请求给 Web服务器请求0.jpg
Web服务器 收到请求返回0.jpg ==> 浏览器 接受0.jpg
通讯过程能够成功的前提: 浏览器发送的0.jpg请求, Web服务器可以做出响应, 也就是代码如下
4、加载图片资源代码
这段代码是一个使用FastAPI框架创建的简单Web服务器。下面是代码的解释:
首先,导入所需的模块:
FastAPI模块用于创建Web应用程序。
Response模块用于构建HTTP响应。
uvicorn模块用于运行服务器。
创建FastAPI的实例对象 app。
定义了多个路由处理函数,每个函数对应一个URL路径。每一个函数中,它们会打开并读取指定的图片文件或HTML文件。
当访问 /images/0.jpg 路径时,执行 func_01() 函数。该函数打开名为 0.jpg 的图片文件,读取文件的内容,并返回一个含有图片内容的HTTP响应。
同样的方式定义了 /images/1.jpg 至 /images/6.jpg 路径对应的函数。
当访问 /gdp.html 路径时,执行 func_08() 函数。该函数打开名为 gdp.html 的HTML文件,读取文件的内容,并返回一个含有HTML内容的HTTP响应。
当访问 /index.html 路径时,执行 main() 函数。该函数打开名为 index.html 的HTML文件,读取文件的内容,并返回一个含有HTML内容的HTTP响应。
最后,使用 uvicorn.run() 方法运行服务器,监听IP地址 127.0.0.1 上的端口号 8000。
5、小结
浏览器访问Web服务器的通讯流程:
浏览器 (127.0.0.1/index.html) ==> 向Web服务器请求index.html
Web服务器 (返回index.html) ==> 浏览器
浏览器解析index.html发现需要0.jpg ==>发送请求给 Web服务器请求0.jpg
Web服务器 收到请求返回0.jpg ==> 浏览器 接受0.jpg
二、基于Web请求的FastAPI通用配置
1、目前Web服务器存在问题
这段代码是一个使用Python的FastAPI框架编写的Web应用程序。它创建了三个路由(或称为端点),分别用于返回不同的图片文件。 通过@app.get装饰器,每个函数定义了一个路由,指定了路由的URL路径,以及当请求该路径时执行的函数。
这个函数定义了一个路由/images/0.jpg,当访问此路径时会执行func_01函数。该函数打开并读取名为source/images/0.jpg的文件,并将读取的数据赋值给变量data。然后,函数返回一个Response对象,其中包含data作为内容,并指定媒体类型为jpg。
类似地,func_02函数定义了另一个路由/images/1.jpg,用于返回名为source/images/1.jpg的文件。 最后,func_03函数定义了一个路由/images/2.jpg,用于返回名为source/images/2.jpg的文件。 这些函数使用了with open语句来打开文件并读取其内容。打开文件时使用了"rb"模式(以二进制模式打开文件),表示这是一个二进制文件(比如图片),而不是文本文件。
这些函数返回的Response对象指定了响应的内容和媒体类型,以便客户端能够正确解析和处理返回的图像数据。
对以上代码观察,会发现每一张图片0.jpg、1.jpg、2.jpg就需要一个函数对应, 如果我们需要1000张图片那就需要1000个函数对应, 显然这样做代码的重复太多了.
2、基于Web请求的FastAPI通用配置
完整代码:
这段代码使用了Python的FastAPI框架来创建一个简单的Web服务器。以下是代码的解释:
导入必要的模块:代码首先导入了FastAPI框架模块,用于创建Web应用程序。然后导入了Response模块,用于返回HTTP响应报文。最后导入了uvicorn模块,用于运行Web服务器。
创建FastAPI应用程序对象:使用app = FastAPI()创建了FastAPI框架的应用程序对象。
定义路由和处理函数:
/images/{path}路由匹配请求路径为/images/0.jpg。path参数表示请求中的文件路径。
get_pic函数是处理/images/{path}路由的处理函数。它从指定路径读取图片文件的内容,并将其作为二进制数据返回给客户端。使用Response(content=data, media_type="jpg")创建了一个Response对象,将图片数据作为响应数据返回给客户端。
/{path}路由匹配其他所有请求路径。path参数表示请求中的文件路径。
get_html函数是处理/{path}路由的处理函数。它从指定路径读取HTML文件的内容,并将其作为二进制数据返回给客户端。使用Response(content=data, media_type="text/html")创建了一个Response对象,将HTML数据作为响应数据返回给客户端。
4.运行Web服务器:使用uvicorn.run(app, host="127.0.0.1", port=8000)运行Web服务器,监听127.0.0.1:8000地址。这将启动一个HTTP服务器,接受客户端请求,并根据定义的路由和处理函数进行响应。
运行结果:

3、小结
通用配置代码:
这段代码是一个基于FastAPI框架的HTTP服务端代码。该代码中定义了一个GET请求处理函数get_pic,用于处理请求路径为/images/{path}的请求。
当接收到一个请求时,FastAPI会将请求路径中的{path}部分作为参数传递给get_pic函数。在函数内部,该参数被声明为path: str,表示path是一个字符串类型的数据。
函数内部使用open()函数打开了一个文件,文件路径为source/images/{path},其中{path}是请求路径中的具体值。然后使用rb模式读取文件内容,并将内容赋值给变量data。
最后,使用Response类创建一个响应对象,并将文件内容作为响应数据,数据格式为jpg。最终返回该响应对象作为HTTP响应。
三、Python爬虫介绍
1、什么是爬虫

网络爬虫:
又被称为网页蜘蛛,网络机器人,是一种按照一定的规则,自动地抓取网络信息的程序或者脚本,另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
通俗理解:
简单来讲,爬虫就是一个探测机器,它的基本操作就是模拟人的行为去各个网站溜达,点点按钮,查查数据,或者把看到的信息背回来. 就像一只虫子在一幢楼里不知疲倦地爬来爬去.
你可以简单地想象:
每个爬虫都是你的「分身」。就像孙悟空拔了一撮汗毛,吹出一堆猴子一样

百度:
其实就是利用了这种爬虫技术, 每天放出无数爬虫到各个网站,把他们的信息抓回来,然后化好淡妆排着小队等你来检索。 有了这样的特性, 对于一些自己公司数据量不足的小公司, 这个时候还想做数据分析就可以通过爬虫获取同行业的数据然后进行分析, 进而指导公司的策略指定。
2、爬虫的基本步骤
基本步骤:
起始URL地址
发出请求获取响应数据
对响应数据解析
数据入库
3、安装requests模块
requests : 可以模拟浏览器的请求
官方文档 :http://cn.python-requests.org/zh_CN/latest/
安装 :pip install requests
快速入门(requests三步走):
4、小结
requests三步走:
5、爬取照片
☆ 查看index.html

☆ 爬取照片的步骤
获取index.html代码
解析index.html代码获取图片url
通过图片url获取图片
☆ 获取index.html代码
☆ 解析index.html代码获取图片url
这段代码是一个函数,用于获取图片的请求URL。具体的流程如下:
1. 使用爬虫向"http://127.0.0.1:8000/index.html"发送请求,获取网页内容。
2. 将获取到的网页内容进行解码,使用utf-8编码格式。
3. 将解码后的内容按行分割,得到一个列表,每个元素是网页的一行内容。 4. 创建一个空列表url_list,用于存储所有图片的URL地址。
5. 遍历每一行的内容,使用正则表达式解析出所有的图片URL。
6. 如果解析结果不为空,将解析出来的图片URL添加到url_list中。
7. 最后返回url_list,即所有图片的URL地址。
☆ 通过图片url获取图片
这段代码是一个函数,用于将爬取到的图片保存到本地。
首先,函数接受一个参数url_list,该参数是一个包含图片url的列表。
然后,通过一个循环遍历url_list中的每一个url。 在循环内部,使用requests.get()方法获取每一张图片。这个方法发送一个HTTP GET请求到指定的url,并返回一个Response对象。
接下来,使用open()函数打开一个文件,文件路径为"./source/spyder/{num}.jpg",其中num是一个递增的数字,用于给每张图片起一个唯一的名字。
然后,使用文件对象的write()方法将图片内容写入到文件中。pic.content是获取到的图片内容。
最后,关闭文件,num递增,继续处理下一张图片,直到遍历完所有的url_list中的url。 完整代码:
详细解释一下代码,这段代码实现了以下功能:
导入了requests和re模块。
定义了一个函数get_pic_url(),用于获取图片的请求url。
首先,通过使用requests.get()方法向"http://127.0.0.1:8000/index.html"发送请求,获取网页的内容。
然后,使用content.decode("utf8")将获取到的内容解码为字符串。
接着,使用split("\n")将字符串按行分割成一个列表。
创建一个空列表url_list,用于存储图片的url地址。
遍历列表data中的每个元素,使用正则表达式匹配出所有的图片url,并将其添加到url_list中。
返回url_list。
3. 定义了一个函数save_pic(url_list),用于将爬取到的图片保存到本地。
初始化一个变量num为0,用于给照片起名字。
遍历url_list中的每个url。
使用requests.get()方法获取每张图片的内容。
使用open()方法打开一个文件,将图片内容写入文件中,文件名为"./source/spyder/{num}.jpg",并递增num。
4. 在主程序中,首先调用get_pic_url()函数获取图片的url列表,然后调用save_pic(url_list)函数将图片保存到本地。
☆ 小结
爬取照片的步骤
获取index.html代码
解析index.html代码获取图片url
通过图片url获取图片
四、使用Python爬取GDP数据
1、gdp.html

通过访问 http://127.0.0.1:8080/gdp.html 可以获取2020年世界GDP排名. 在这里我们通过和爬取照片一样的流程步骤获取GDP数据。
2、zip函数的使用
zip() 函数: 用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. zip()函数是Python内置的一个函数,用于将多个可迭代对象打包成一个元组的列表。 zip()函数的语法如下:
其中,iterables是一个或多个可迭代对象,可以是列表、元组、字符串或其他可迭代对象。 zip()函数的工作原理是,它会从每个可迭代对象中依次取出一个元素,然后将这些元素打包成一个元组,再将这个元组添加到结果列表中。当其中任何一个可迭代对象取尽元素时,zip()函数就会停止打包。 下面是一个简单的示例,展示了zip()函数的使用:
输出结果:
在这个示例中,zip()函数将numbers和letters两个可迭代对象打包成了一个元组的列表。每个元组由numbers和letters中对应位置的元素组成。 需要注意的是,如果传入的可迭代对象的长度不一致,zip()函数会以最短的可迭代对象为准进行打包。如果需要以最长的可迭代对象为准进行打包,可以使用itertools.zip_longest()函数。 zip()函数在实际应用中常用于同时迭代多个可迭代对象,特别是在需要将它们的对应位置的元素进行处理或组合时非常有用。 下面是另外一个例子:
3、爬取GDP数据
这段代码的功能是爬取一个网页上的国家名字和GDP数据。具体的实现过程如下:
导入requests和re模块。
创建两个空列表country_list和gdp_list,用于存储爬取到的国家名字和GDP数据。
定义一个函数get_gdp_data(),用于获取GDP数据。
在函数中,首先使用requests.get()函数获取网页的HTML数据,并将其解码为utf8格式。
将获取到的HTML数据按行分割,得到一个列表data_list。
遍历data_list列表,对每一行的HTML数据进行解析。
使用re.match()函数对每一行的HTML数据进行匹配,以获取国家名字和GDP数据。
如果匹配成功,将国家名字存放到country_list列表中,将GDP数据存放到gdp_list列表中。
将country_list和gdp_list两个列表融合成一个列表gdp_data。
最后,打印出gdp_data列表。
在主程序中,调用get_gdp_data()函数来执行爬取操作。
4、小结
爬取gdp的步骤
获取gdp.html代码
解析gdp.html代码获取gdp数据
五、多任务爬虫实现
1、为什么用多任务
在我们的案例中, 我们只是爬取了2个非常简单的页面, 这两个页面的数据爬取并不会使用太多的时间, 所以我们也没有太多的考虑效率问题. 但是在真正的工作环境中, 我们爬取的数据可能非常的多, 如果还是使用单任务实现, 这时候就会让我们爬取数据的时间很长, 那么显然使用多任务可以大大提升我们爬取数据的效率
2、多任务爬取数据
实际上实现多任务并不难, 只需要使用我们之前讲过的多任务就可以了
3、多任务代码实现
4、小结
多任务
导入模块
创建多进程或者多线程
启动多任务
六、数据可视化
1、 什么是数据可视化

数据可视化:顾名思义就是让数据看的到, 他的作用也很明显, 让人们不用再去阅读枯燥无味的数据, 一眼看去就可以明白数据是什么, 数据间的关系是什么, 更好的让我们通过数据发现潜在的规律进而进行商业决策。
2、pyecharts模块

概况 : Echarts 是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可. 而 Python 是门富有表达力的语言,很适合用于数据处理,当数据分析遇上数据可视化时pyecharts 诞生了. 特性:
简洁的API设计,使用如丝滑般流畅,支持链式调用
囊括了30+种常见图表,应有尽有
支持主流Notebook 环境,Jupyter Notebook 和JupyterLab
可轻松集成至Flask, Django等主流Web框架
高度灵活的配置项,可轻松搭配出精美的图表
详细的文档和示例,帮助开发者更快的上手项目
多达400+地图文件以及原生的百度地图,为地理数据可视化提供强有力的支持
3、通过pyecharts模块创建饼状图
导入模块
初始化饼状图:
Pie()函数: 创建饼图
opts.InitOpts参数: Pie(init_opts=opts.InitOpts(width="1400px", height="800px"))
init_opts: 指定参数名 opts.InitOpts: 配置选项
width="1400px" height="800px" :界面的宽度和高度
给饼图添加数据:
add()函数:
参数1: 名称
参数2: 具体数据, 数据类型为==>[(a,b),(a,b),(a,b)]==>a为数据名称,b为数据大小
参数3: 标签设置 label_opts=opts.LabelOpts(formatter='{b}:{d}%') 符合百分比的形式
给饼图添设置标题:
set_global_opts()函数 :
title_opts=opts.TitleOpts : 设置标题
title="2020年世界GDP排名", subtitle="美元" : 设置主标题和副标题
保存数据:
4、完整代码
5、小结
可视化
Pie()函数 : 创建饼图
add()函数 : 添加数据
set_global_opts()函数 : 设置标题
render()函数 : 保存数据
七、Logging日志模块
1、logging日志的介绍
在现实生活中,记录日志非常重要,比如:银行转账时会有转账记录;飞机飞行过程中,会有个黑盒子(飞行数据记录器)记录着飞机的飞行过程,那在咱们python程序中想要记录程序在运行时所产生的日志信息,怎么做呢?
可以使用 logging 这个包来完成
在软件开发中,日志是一种记录程序运行过程中产生的重要信息的方式。日志可以帮助开发人员了解程序的运行状态、发现问题和进行故障排查。Python提供了内置的logging模块,用于实现日志记录功能。 logging模块提供了一套灵活且易于使用的API,可以方便地在程序中添加日志记录。以下是使用logging模块进行日志记录的基本步骤:
导入logging模块:
配置日志记录器:
在这个例子中,使用basicConfig()函数配置了日志记录器的级别、日志文件名和日志格式。level参数指定了日志记录的级别,常见的级别有DEBUG、INFO、WARNING、ERROR和CRITICAL。filename参数指定了日志文件的名称,如果不指定,则日志会输出到控制台。format参数指定了日志的格式,可以自定义日志的输出格式。
记录程序日志信息的目的是:
可以很方便的了解程序的运行情况
可以分析用户的操作行为、喜好等信息
方便开发人员检查bug
2、logging日志级别介绍
日志等级可以分为5个,从低到高分别是:
DEBUG
INFO
WARNING
ERROR
CRITICAL
3、logging日志的使用
在 logging 包中记录日志的方式有两种:
输出到控制台
保存到日志文件
日志信息输出到控制台的示例代码:
运行结果:
说明:
日志信息只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING
logging日志等级和输出格式的设置:
运行结果:
日志等级说明:
DEBUG:程序调试bug时使用
INFO:程序正常运行时使用
WARNING:程序未按预期运行时使用,但并不是错误,如:用户登录密码错误
ERROR:程序出错误时使用,如:IO操作失败
CRITICAL:特别严重的问题,导致程序不能再继续运行时使用,如:磁盘空间为空,一般很少使用
默认的是WARNING等级,当在WARNING或WARNING之上等级的才记录日志信息。
日志等级从低到高的顺序是: DEBUG < INFO < WARNING < ERROR < CRITICAL
代码说明:
level 表示设置的日志等级
format 表示日志的输出格式, 参数说明:
%(levelname)s: 打印日志级别名称
%(filename)s: 打印当前执行程序名
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(message)s: 打印日志信息
日志信息保存到日志文件的示例代码:
运行结果:

4、logging日志在Web项目中应用
使用logging日志示例:
程序入口模块设置logging日志的设置
访问index.html时进行日志输出,示例代码:
访问gdp.html时进行日志输出,示例代码:
logging日志:

通过日志信息我们得知, index.html被访问了2次, gdp.html被访问了2次.
说明:
logging日志配置信息在程序入口模块设置一次,整个程序都可以生效。
logging.basicConfig 表示 logging 日志配置操作
5、小结
记录python程序中日志信息使用 logging 包来完成
logging日志等级有5个:
DEBUG
INFO
WARNING
ERROR
CRITICAL
打印(记录)日志的函数有5个:
logging.debug函数, 表示: 打印(记录)DEBUG级别的日志信息
logging.info函数, 表示: 打印(记录)INFO级别的日志信息
logging.warning函数, 表示: 打印(记录)WARNING级别的日志信息
logging.error函数, 表示: 打印(记录)ERROR级别的日志信息
logging.critical函数, 表示: 打印(记录)CRITICAL级别的日志信息