Bootstrap

Python进阶08-爬虫

零、文章目录

Python进阶08-爬虫

1、爬虫介绍

(1)爬虫是什么
  • **网络爬虫:**又被称为网页蜘蛛,网络机器人,是一种按照一定的规则,自动地抓取网络信息的程序或者脚本,另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
  • **通俗理解:**简单来讲,爬虫就是一个探测机器,它的基本操作就是模拟人的行为去各个网站溜达,点点按钮,查查数据,或者把看到的信息背回来. 就像一只虫子在一幢楼里不知疲倦地爬来爬去。
  • **百度:**其实就是利用了这种爬虫技术, 每天放出无数爬虫到各个网站,把他们的信息抓回来,然后化好淡妆排着小队等你来检索。
  • 有了这样的特性, 对于一些自己公司数据量不足的小公司, 这个时候还想做数据分析就可以通过爬虫获取同行业的数据然后进行分析, 进而指导公司的策略指定。
(2)爬虫的基本执行步骤
  • 起始URL地址

  • 发出请求获取响应数据

  • 对响应数据解析

  • 数据入库

(3)requests模块
  • requests : 可以模拟浏览器的请求
  • 官方文档 :http://cn.python-requests.org/zh_CN/latest/
  • 安装 :pip install requests -i https://mirrors.aliyun.com/pypi/simple/
  • 快速入门(requests三步走):
# 导入模块
import requests
# 通过requests.get()发送请求
# data保存返回的响应数据(这里的响应数据不是单纯的html,需要通过content获取html代码)
data = requests.get("http://www.baidu.com")
# 通过data.content获取html代码
data = data.content.decode("utf-8")
(4)爬取网页图片
  • 首先准备爬取的网页

    • 制作网页index.html

    • 启动一个Web服务器

  • 爬取照片的步骤

    • 获取index.html代码

    • 解析index.html代码获取图片url

    • 通过图片url获取图片

  • 制作网页index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>百度一下 你就高薪</title>

    <style type="text/css">
    ul {list-style-type: none;}
            li {float: left; display: inline; margin-left: 10px;}
            .body { width: 980px; height: 800px; margin: 0 auto;}
            table{width: 100%;}
            .left {width: 60%; float: left; text-align: center;margin-top:10px}
            .right {width: 40%; float: left; }
            img {border-radius: 20px;}


        body{
        font-family:arial;
        font-size:12px;
        }


        #topbar{/*id选择器*/
        text-align:right;
        font-size:13px;
        margin-top:18px;
        padding-right:5px;
        }

        #topbar1 a{
        color:#999;
        margin-left:25px;
        margin-top:18px
        }


        #topbar2 a{
        color:#999;
        }


        #topbar2 span{
        color:#999;
        }

        #topbar a{
        color:#333;
        margin-left:20px;
        }

        .bola{
        font-weight:700;
        }

        #topbar #morepro{
        background:#2d78f4;
        color:#fff;
        padding:3px;
        }

        .centerdiv{
        text-align:center;
        }

        #searchText{
        width:540px;
        height:32px;
        border-radius:9px;
        border:2px solid #2d78f4;
        }

        #submitBtn{
        width:85px;
        height:32px;
        background:#3385ff;
        color:#fff;
        border-radius:9px;
        border:3px solid #3385ff;
        text-align: center;}
    </style>

</head>

<body>

<div id="topbar">
    <a class="bola">Python</a>
    <a class="bola">Java</a>
    <a class="bola">大数据</a>
    <a class="bola">数据分析</a>
    <a >登录</a>
    <a >设置</a>
</div>

<div class="centerdiv">
    <img src="./favicon.ico" width="350px" height="160px" style="margin-top:100px" >
</div>

<div class="centerdiv" >
    <form >
        <input id="searchText">
        <input id="submitBtn" value="百度一下"  style="margin-top:10px" onclick="window.location.href='./gdp.html';">
    </form>
</div>

<div class="body" >

    <div class="left">
        <p> </p>

        <a style="display: block;text-align:left; color:gray"><h3>推荐  导航  关注</h3></a>
        <table style = "border-collapse:separate; border-spacing:10px;">
            <tr>
                <td colspan="3" style="text-align:left;"><font size="4" face="Arial,sans-serif">惊爆 亚洲舞王卫冕成功</font></td>
            </tr>

            <tr>
                <td><img src="./images/1.jpg" width="184px" height="122px" /></td>
                <td><img src="./images/2.jpg" width="184px" height="122px" /></td>
                <td><img src="./images/3.jpg" width="184px" height="122px" /></td>
            </tr>

            <tr>
                <td colspan="3" style="text-align:left;"><font size="4" face="Arial,sans-serif">两少年人穷志不短 仅着内裤环游世界</font></td>
            </tr>

            <tr>
                <td><img src="./images/4.jpg" width="184px" height="122px" /></td>
                <td><img src="./images/5.jpg" width="184px" height="122px" /></td>
                <td><img src="./images/6.jpg" width="184px" height="122px" /></td>
            </tr>
        </table>

    </div>


    <div class="right">

    </div>

</div>

<div class="centerdiv">
    <span style="color:#666;">百度</span>
</div>

<div id="topbar1" class="centerdiv" style="margin-top:0px">
    <a>把百度设置为主页  </a>
    <a>关于百度  </a>
    <a>AboutBaidu  </a>
    <a>百度推广</a>
</div>

<div id="topbar2" class="centerdiv" style="margin-top:0px">
    <span>@2018Baidu</span>
    <a>使用百度前必读  </a>
    <a>意见反馈  </a>
    <span>京ICP证030173</span>
    <span class="iconCls0"></span>
    <a style="margin-left:18px">京公安网备号11000002000001  </a>
    <span class="iconCls"></span>
</div>

</body>
</html>
  • 启动一个Web服务器
'''
FastAPI使用四步走:① 导入模块 ② 创建FastAPI对象 ③ 使用装饰器收发信息 ④ 启动服务器开始监听
'''
# ① 导入模块
from fastapi import FastAPI
from fastapi import Response

import uvicorn

# ② 创建FastAPI对象
app = FastAPI()

# ③ 使用装饰器收发信息
@app.get('/')  # 首页
def main():
    with open('source/html/index.html', 'rb') as f:
        data = f.read()
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='text/html')

# 使用装饰器处理图片请求
@app.get('/images/{path}')  # /images/0.jpg
def get_pic(path: str):  # 在Python函数中,可以这么写def 函数名称(参数: 建议的参数类型,可以不遵守)
    with open(f'source/images/{path}', 'rb') as f:
        data = f.read()
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='jpg')

# 会用装饰器处理html请求
@app.get('/{path}')
def get_html(path: str):
    with open(f'source/html/{path}', 'rb') as f:
        data = f.read()
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='text/html')

# 添加一个小图标接收请求与处理返回
@app.get('/favicon.ico')
def get_ico():
    with open(f'source/html/favicon.ico', 'rb') as f:
        data = f.read()
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='image/x-icon')

# ④ 启动服务器开始监听
uvicorn.run(app, host='127.0.0.1', port=8000)
  • 获取index.html代码
# 通过爬虫向index.html发送请求
# requests.get(网址): 向一个网址发送请求,和在浏览器中输入网址是一样的
data = requests.get("http://127.0.0.1:8000/index.html")
# content可以把requests.get()获取的返回值中的html内容获取到
data = data.content.decode("utf-8")
  • 解析index.html代码获取图片url
# 获取图片的请求url
def get_pic_url():
    # 通过爬虫向index.html发送请求
    # requests.get(网址): 向一个网址发送请求,和在浏览器中输入网址是一样的
    data = requests.get("http://127.0.0.1:8000/index.html")
    # content可以把requests.get()获取的返回值中的html内容获取到
    data = data.content.decode("utf-8")
    # html每一行都有"\n", 对html进行分割获得一个列表
    data = data.split("\n")
    # 创建一个列表存储所有图片的url地址(也就是图片网址)
    url_list = []
    for url in data:
        # 通过正则解析出所有的图片url
        result = re.match('.*src="(.*)" width.*', url)
        if result is not None:
            # 把解析出来的图片url添加到url_list中
            url_list.append(result.group(1))

    return url_list
  • 通过图片url获取图片
# 把爬取到的图片保存到本地
def save_pic(url_list):
    # 通过num给照片起名字 例如:0.jpg 1.jpg 2.jpg
    num = 0
    for url in url_list:
        # 通过requests.get()获取每一张图片
        pic = requests.get(f"http://127.0.0.1:8000{url[1:]}")
        # 保存每一张图片
        with open(f"./source/spyder/{num}.jpg", "wb") as f:
            f.write(pic.content)
            num += 1
  • 爬虫完整代码
import requests
import re


# 获取图片的请求url
def get_pic_url():
    # 通过爬虫向index.html发送请求
    # requests.get(网址): 向一个网址发送请求,和在浏览器中输入网址是一样的
    data = requests.get("http://127.0.0.1:8000/index.html")
    # content可以把requests.get()获取的返回值中的html内容获取到
    data = data.content.decode("utf8")
    # html每一行都有"\n", 对html进行分割获得一个列表
    data = data.split("\n")
    # 创建一个列表存储所有图片的url地址(也就是图片网址)
    url_list = []
    for url in data:
        # 通过正则解析出所有的图片url
        result = re.match('.*src="(.*)" width.*', url)
        if result is not None:
            # 把解析出来的图片url添加到url_list中
            url_list.append(result.group(1))

    return url_list


# 把爬取到的图片保存到本地
def save_pic(url_list):
    # 通过num给照片起名字 例如:0.jpg 1.jpg 2.jpg
    num = 0
    for url in url_list:
        # 通过requests.get()获取每一张图片
        pic = requests.get(f"http://127.0.0.1:8000{url[1:]}")
        # 保存每一张图片
        with open(f"./source/spyder/{num}.jpg", "wb") as f:
            f.write(pic.content)
            num += 1


if __name__ == '__main__':
    url_list = get_pic_url()
    save_pic(url_list)

2、使用Python爬取GDP数据

(1)制作网页gdp.html
  • 制作网页gdp.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2020年世界GDP排名</title>
    <style type="text/css">
       .t1
        {
            clear: both;
            border: 1px solid #c9dae4;
        }
        .t1 tr th
        {
            color: #0d487b;
            background: #f2f4f8;
            line-height: 28px;
            border-bottom: 1px solid #9cb6cf;
            border-top: 1px solid #e9edf3;
            font-weight: normal;
            text-shadow: #e6ecf3 1px 1px 0px;
            padding-left: 5px;
            padding-right: 5px;
        }
        .t1 tr td
        {
            border-bottom: 1px solid #e9e9e9;
            padding-bottom: 5px;
            padding-top: 5px;
            color: #444;
            border-top: 1px solid #FFFFFF;
            padding-left: 5px;
            padding-right: 5px;
            word-break: break-all;
        }
        tr td
        {
            background: #ecf6fc; /*这行将给所有的tr加上背景色*/
            text-align: center;
        }


    </style>
<!--    <link rel="icon" href="data:;base64,=">-->
</head>
<body>


<div style="text-align:center;"><h1>2020年世界GDP排名</h1></div>

<table width="100%" id="ListArea" border="0" class="t1" align="center" cellpadding="0"
        cellspacing="0">

          <tr>
            <th><font><font><font><font>GDP总量</font></font>排名</font></font></th>
            <th><font><font>国家/地区</font></font></th>
            <th><font><font>单位亿美元</font></font></th>
            <th><font><font><font>GDP总量</font>(人民币亿元)</font></font></th>
            <th><font><font>GDP总量(人民币亿元)</font></font></th>
            <th><font><font>地区</font></font></th>
          </tr>



          <tr style="">
            <td class="rank" ><font><font>排名第1</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>美国</font></a></td>
            <td class="value"><font>$218463.3<font>亿</font></font></td>
            <td class="rank_prev"><font>1422196.083亿元</font></td>
            <td>壹佰肆拾贰<font color="red"></font>贰仟壹佰玖拾陆<font color="red">亿元</font></td>
            <td class="area"><font><font>美洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第2</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>中国</font></a></td>
            <td class="value"><font>$155518.9<font>亿</font></font></td>
            <td class="rank_prev"><font>1012428.039亿元</font></td>
            <td>壹佰零壹<font color="red"></font>贰仟肆佰贰拾捌<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第3</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>日本</font></a></td>
            <td class="value"><font>$52797.7<font>亿</font></font></td>
            <td class="rank_prev"><font>343713.027亿元</font></td>
            <td>叁拾肆<font color="red"></font>叁仟柒佰壹拾叁<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第4</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>德国</font></a></td>
            <td class="value"><font>$42119<font>亿</font></font></td>
            <td class="rank_prev"><font>274194.69亿元</font></td>
            <td>贰拾柒<font color="red"></font>肆仟壹佰玖拾肆<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第5</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>印度</font></a></td>
            <td class="value"><font>$32248.7<font>亿</font></font></td>
            <td class="rank_prev"><font>209939.037亿元</font></td>
            <td>贰拾<font color="red"></font>玖仟玖佰叁拾玖<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第6</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>法国</font></a></td>
            <td class="value"><font>$29749<font>亿</font></font></td>
            <td class="rank_prev"><font>193665.99亿元</font></td>
            <td>壹拾玖<font color="red"></font>叁仟陆佰陆拾伍<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第7</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>英国</font></a></td>
            <td class="value"><font>$28037.9<font>亿</font></font></td>
            <td class="rank_prev"><font>182526.729亿元</font></td>
            <td>壹拾捌<font color="red"></font>贰仟伍佰贰拾陆<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第8</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>巴西</font></a></td>
            <td class="value"><font>$24038.7<font>亿</font></font></td>
            <td class="rank_prev"><font>156491.937亿元</font></td>
            <td>壹拾伍<font color="red"></font>陆仟肆佰玖拾壹<font color="red">亿元</font></td>
            <td class="area"><font><font>美洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第9</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>意大利</font></a></td>
            <td class="value"><font>$21602<font>亿</font></font></td>
            <td class="rank_prev"><font>140629.02亿元</font></td>
            <td>壹拾肆<font color="red"></font>零陆佰贰拾玖<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第10</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>加拿大</font></a></td>
            <td class="value"><font>$19071.8<font>亿</font></font></td>
            <td class="rank_prev"><font>124157.418亿元</font></td>
            <td>壹拾贰<font color="red"></font>肆仟壹佰伍拾柒<font color="red">亿元</font></td>
            <td class="area"><font><font>美洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第11</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>韩国</font></a></td>
            <td class="value"><font>$17379.6<font>亿</font></font></td>
            <td class="rank_prev"><font>113141.196亿元</font></td>
            <td>壹拾壹<font color="red"></font>叁仟壹佰肆拾壹<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第12</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>俄罗斯</font></a></td>
            <td class="value"><font>$16527.3<font>亿</font></font></td>
            <td class="rank_prev"><font>107592.723亿元</font></td>
            <td>壹拾<font color="red"></font>柒仟伍佰玖拾贰<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr style="">
            <td class="rank"><font><font>排名第13</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>澳大利亚</font></a></td>
            <td class="value"><font>$16314.4<font>亿</font></font></td>
            <td class="rank_prev"><font>106206.744亿元</font></td>
            <td>壹拾<font color="red"></font>陆仟贰佰零陆<font color="red">亿元</font></td>
            <td class="area"><font><font>大洋州国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第14</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>西班牙</font></a></td>
            <td class="value"><font>$15336.1<font>亿</font></font></td>
            <td class="rank_prev"><font>99838.011亿元</font></td>
            <td><font color="red"></font>玖仟捌佰叁拾捌<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第15</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>墨西哥</font></a></td>
            <td class="value"><font>$13929.2<font>亿</font></font></td>
            <td class="rank_prev"><font>90679.092亿元</font></td>
            <td><font color="red"></font>零陆佰柒拾玖<font color="red">亿元</font></td>
            <td class="area"><font><font>美洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第16</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>印度尼西亚</font></a></td>
            <td class="value"><font>$12908.4<font>亿</font></font></td>
            <td class="rank_prev"><font>84033.684亿元</font></td>
            <td><font color="red"></font>肆仟零叁拾叁<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第17</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>土耳其</font></a></td>
            <td class="value"><font>$10189.1<font>亿</font></font></td>
            <td class="rank_prev"><font>66331.041亿元</font></td>
            <td><font color="red"></font>陆仟叁佰叁拾壹<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第18</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>荷兰</font></a></td>
            <td class="value"><font>$9519.34<font>亿</font></font></td>
            <td class="rank_prev"><font>61970.9034亿元</font></td>
            <td><font color="red"></font>壹仟玖佰柒拾<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第19</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>阿根廷</font></a></td>
            <td class="value"><font>$7650.96<font>亿</font></font></td>
            <td class="rank_prev"><font>49807.7496亿元</font></td>
            <td><font color="red"></font>玖仟捌佰零柒<font color="red">亿元</font></td>
            <td class="area"><font><font>美洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第20</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>沙特阿拉伯</font></a></td>
            <td class="value"><font>$7609.9<font>亿</font></font></td>
            <td class="rank_prev"><font>49540.449亿元</font></td>
            <td><font color="red"></font>玖仟伍佰肆拾<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第21</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>瑞士</font></a></td>
            <td class="value"><font>$7497.32<font>亿</font></font></td>
            <td class="rank_prev"><font>48807.5532亿元</font></td>
            <td><font color="red"></font>捌仟捌佰零柒<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第22</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>瑞典</font></a></td>
            <td class="value"><font>$6509.2<font>亿</font></font></td>
            <td class="rank_prev"><font>42374.892亿元</font></td>
            <td><font color="red"></font>贰仟叁佰柒拾肆<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第23</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>波兰</font></a></td>
            <td class="value"><font>$6327.86<font>亿</font></font></td>
            <td class="rank_prev"><font>41194.3686亿元</font></td>
            <td><font color="red"></font>壹仟壹佰玖拾肆<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第24</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>中国台湾</font></a></td>
            <td class="value"><font>$6252.46<font>亿</font></font></td>
            <td class="rank_prev"><font>40703.5146亿元</font></td>
            <td><font color="red"></font>零柒佰零叁<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第25</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>尼日利亚</font></a></td>
            <td class="value"><font>$5888.41<font>亿</font></font></td>
            <td class="rank_prev"><font>38333.5491亿元</font></td>
            <td><font color="red"></font>捌仟叁佰叁拾叁<font color="red">亿元</font></td>
            <td class="area"><font><font>非洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第26</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>比利时</font></a></td>
            <td class="value"><font>$5684.22<font>亿</font></font></td>
            <td class="rank_prev"><font>37004.2722亿元</font></td>
            <td><font color="red"></font>柒仟零肆<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第27</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>泰国</font></a></td>
            <td class="value"><font>$5271.29<font>亿</font></font></td>
            <td class="rank_prev"><font>34316.0979亿元</font></td>
            <td><font color="red"></font>肆仟叁佰壹拾陆<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第28</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>奥地利</font></a></td>
            <td class="value"><font>$4767.54<font>亿</font></font></td>
            <td class="rank_prev"><font>31036.6854亿元</font></td>
            <td><font color="red"></font>壹仟零叁拾陆<font color="red">亿元</font></td>
            <td class="area"><font><font>欧洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第29</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>伊朗</font></a></td>
            <td class="value"><font>$4556.46<font>亿</font></font></td>
            <td class="rank_prev"><font>29662.5546亿元</font></td>
            <td><font color="red"></font>玖仟陆佰陆拾贰<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>

          <tr  style="">
            <td class="rank"><font><font>排名第30</font></font></td>
            <td>&nbsp;&nbsp;<a href=""><font>阿闻酋</font></a></td>
            <td class="value"><font>$4459.15<font>亿</font></font></td>
            <td class="rank_prev"><font>29029.0665亿元</font></td>
            <td><font color="red"></font>玖仟零贰拾玖<font color="red">亿元</font></td>
            <td class="area"><font><font>亚洲国家</font></font></td>
          </tr>


      </table>
</body>
</html>
  • 启动Web服务器,同上
  • 通过访问 http://127.0.0.1:8080/gdp.htmlimage-20240829151940637
(2)使用zip函数
  • zip() 函数: 用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
'''
为什么要把数据进行合并?
答:主要是因为我们要把GDP的数据组装成[(), (), (), ()]结构

zip()函数有何作用呢?
答:其作用就是把两个列表甚至多个列表进行合并操作
特别说明:zip()返回的结果是一个对象,不支持直接打印,所以我们需要通过list()函数对其进行转换

GDP数据可视化格式 => [('美国', 100亿), ('中国', 90亿), ('日本', 80亿)]
'''
a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]

list1 = list(zip(a, b))
print(list1) #[(1, 4), (2, 5), (3, 6)]


list2 = list(zip(a, c))
print(list2) #[(1, 4), (2, 5), (3, 6)]
(3)爬取GDP数据
import re
import requests

country_list = []
gdp_list = []

def get_gdp():
    res = requests.get('http://127.0.0.1:8000/gdp.html')
    data = res.content.decode('utf-8')
    data = data.split('\n')
    for row in data:
        # print(row)  # <td>&nbsp;&nbsp;<a href=""><font>美国</font></a></td>
        result = re.match('.*<a href=""><font>(.*)</font></a>.*', row)
        if result:
            country_list.append(result.group(1))
        # <td class="rank_prev"><font>¥29662.5546亿元</font></td>
        result = re.match('.*¥(.*)亿元.*', row)
        if result:
            gdp_list.append(float(result.group(1)))

    # print(country_list)
    # print(gdp_list)
    # 把以上得到的结果转换为[(), (), ()]
    return list(zip(country_list, gdp_list))

if __name__ == '__main__':
    data = get_gdp()
    print(data)

3、多任务爬虫实现

(1)为什么用多任务
  • 案例中:我们只是爬取了2个非常简单的页面, 这两个页面的数据爬取并不会使用太多的时间, 所以我们也没有太多的考虑效率问题。

  • 实际场景:爬取的数据可能非常的多, 如果还是使用单任务实现, 这时候就会让我们爬取数据的时间很长, 那么显然使用多任务可以大大提升我们爬取数据的效率。

(2)代码实现
import re
import requests
import multiprocessing

country_list = []
gdp_list = []

def get_pic_url():
    res = requests.get('http://127.0.0.1:8000/')
    data = res.content.decode('utf-8')  # 获取目标页面的html源代码
    # 对html代码进行切割
    data = data.split('\n')

    url_list = []
    # 对列表进行遍历
    for row in data:
        result = re.match('.*src="(.*)" width', row)  # '    <img src="./images/0.jpg" width="350px" height="160px" style="margin-top:100px" >'
        if result:
            url_list.append(result.group(1))
    return url_list

# 用于实现爬取图片的保存
def save_pic(pic_url_list):
    num = 0
    # 第一步:循环遍历图片的url地址
    for pic_url in pic_url_list:
        # 第二步:向图片的服务器端发起请求,获取图片的内容
        res = requests.get('http://127.0.0.1:8000' + pic_url[1:])  # http://127.0.0.1:8000/images/0.jpg
        # 第三步:把以上得到的图片信息,直接写入到图片中
        with open(f'source/spyder/{num}.jpg', 'wb') as f:
            f.write(res.content)
        num += 1

def get_pic():
    pic_url_list = get_pic_url()
    save_pic(pic_url_list)
    
def get_gdp():
    res = requests.get('http://127.0.0.1:8000/gdp.html')
    data = res.content.decode('utf-8')
    data = data.split('\n')
    for row in data:
        # print(row)  # <td>&nbsp;&nbsp;<a href=""><font>美国</font></a></td>
        result = re.match('.*<a href=""><font>(.*)</font></a>.*', row)
        if result:
            country_list.append(result.group(1))
        # <td class="rank_prev"><font>¥29662.5546亿元</font></td>
        result = re.match('.*¥(.*)亿元.*', row)
        if result:
            gdp_list.append(float(result.group(1)))

    # print(country_list)
    # print(gdp_list)
    # 把以上得到的结果转换为[(), (), ()]
    return list(zip(country_list, gdp_list))

if __name__ == '__main__':
    p1 = multiprocessing.Process(target=get_pic)
    p2 = multiprocessing.Process(target=get_gdp)

    p1.start()
    p2.start()

4、数据可视化

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

fef74d6c-94c7-4f4f-8dd5-72618ae5778b

(2)pyecharts模块

image-20240901161647813

  • 概况 :Echarts 是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可. 而 Python 是门富有表达力的语言,很适合用于数据处理. 当数据分析遇上数据可视化时pyecharts 诞生了.
  • 官网:https://05x-docs.pyecharts.org/#/
  • 特性 :
    • 简洁的API设计,使用如丝滑般流畅,支持链式调用
    • 囊括了**30+**种常见图表,应有尽有
    • 支持主流Notebook 环境,Jupyter NotebookJupyterLab
    • 可轻松集成至Flask, Django等主流Web框架
    • 高度灵活的配置项,可轻松搭配出精美的图表
    • 详细的文档和示例,帮助开发者更快的上手项目
    • 多达400+地图文件以及原生的百度地图,为地理数据可视化提供强有力的支持
(3)pyecharts创建饼图
  • 导入模块:
    • 先安装一下:pip install pyecharts -i https://mirrors.aliyun.com/pypi/simple/
# 导入饼图模块
from pyecharts.charts import Pie
# 导入配置选项模块
import pyecharts.options as opts
  • **初始化饼状图:**Pie()函数创建饼图
    • init_opts: 指定参数名
    • opts.InitOpts: 配置选项
    • **width=“1400px” height=“800px” 😗*界面的宽度和高度
# 创建饼图并设置这个界面的长和高 
# px:像素单位
pie = Pie(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}%’) 符合百分比的形式

# 给饼图添加数据
pie.add(
  "GDP",
  data,
  label_opts=opts.LabelOpts(formatter='{b}:{d}%')
)
  • **给饼图添设置标题:**set_global_opts()函数

    • title_opts=opts.TitleOpts : 设置标题

    • title=“2020年世界GDP排名”, subtitle=“美元” : 设置主标题和副标题

# 给饼图设置标题
pie.set_global_opts(title_opts=opts.TitleOpts(title="2020年世界GDP排名", subtitle="美元"))
  • 保存数据:会在同目录下生成pie.html浏览器打开即可
# 保存结果
pie.render("pie.html")
(4)完整代码
import requests
import re
# 导入饼图模块
from pyecharts.charts import Pie
# 导入配置选项模块
import pyecharts.options as opts

# 存储爬取到的国家的名字
country_list = []
# 春初爬取到的国家gdp的数据
gdp_list = []


def get_gdp_data():
    global country_list
    global gdp_list

    # 获取gdp的html数据
    data = requests.get("http://localhost:8000/gdp.html")
    # 对获取数据进行解码
    data = data.content.decode("utf8")
    # 对gdp的html数据进行按行分割
    data_list = data.split("\n")

    for i in data_list:
        # 对html进行解析获取<国家名字>
        country_result = re.match('.*<a href=""><font>(.*)</font></a>', i)
        # 匹配成功就存放到列表中
        if country_result is not None:
            country_list.append(country_result.group(1))
        # 对html进行解析获取<gdp数据>
        gdp_result = re.match(".*¥(.*)亿元", i)
        # 匹配成功就存储到列表中
        if gdp_result is not None:
            gdp_list.append(gdp_result.group(1))


# 创建一个饼状图显示GDP前十的国家
def data_view_pie():
    # 获取前十的过的GDP数据, 同时让数据符合[(),()...]的形式
    data = list(zip(country_list[:10], gdp_list[:10]))
    # 创建饼图
    pie = Pie(init_opts=opts.InitOpts(width="1400px", height="800px"))
    # 给饼图添加数据
    pie.add(
        "GDP",
        data,
        label_opts=opts.LabelOpts(formatter='{b}:{d}%')
    )
    # 给饼图设置标题
    pie.set_global_opts(title_opts=opts.TitleOpts(title="2020年世界GDP排名", subtitle="美元"))
    # 保存结果
    pie.render("pie.html")


if __name__ == '__main__':
    # 获取GDP数据
    get_gdp_data()
    # 生成可视化饼图
    data_view_pie()
(5)打开pie.html页面

image-20240902094500850

5、Logging日志模块

(1)为什么要记录日志
  • 在现实生活中,记录日志非常重要,比如:银行转账时会有转账记录;飞机飞行过程中,会有个黑盒子(飞行数据记录器)记录着飞机的飞行过程,那在咱们python程序中想要记录程序在运行时所产生的日志信息,可以使用 logging 这个包来完成

  • 记录程序日志信息的目的是:

    • 可以很方便的了解程序的运行情况
    • 可以分析用户的操作行为、喜好等信息
    • 方便开发人员检查bug
(2)logging日志级别
  • 日志等级可以分为5个,从低到高分别是:

    • DEBUG:程序调试bug时使用
    • INFO:程序正常运行时使用
    • WARNING(默认):程序未按预期运行时使用,但并不是错误,如:用户登录密码错误
    • ERROR:程序出错误时使用,如:IO操作失败
    • CRITICAL:特别严重的问题,导致程序不能再继续运行时使用,如:磁盘空间为空,一般很少使用
  • 日志打设定的等级及以上

(3)logging日志使用
  • 在 logging 包中记录日志的方式有两种:

    • 输出到控制台
    • 保存到日志文件
  • 日志信息输出到控制台:

    • 代码实现
    import logging
    
    logging.debug('这是一个debug级别的日志信息')
    logging.info('这是一个info级别的日志信息')
    logging.warning('这是一个warning级别的日志信息')
    logging.error('这是一个error级别的日志信息')
    logging.critical('这是一个critical级别的日志信息')
    
    • 运行结果
    WARNING:root:这是一个warning级别的日志信息
    ERROR:root:这是一个error级别的日志信息
    CRITICAL:root:这是一个critical级别的日志信息
    
  • 日志信息输出到日志文件:

    • 代码实现
    import logging
    
    logging.basicConfig(filename="log.txt",
                        filemode="w")
    
    logging.debug('这是一个debug级别的日志信息')
    logging.info('这是一个info级别的日志信息')
    logging.warning('这是一个warning级别的日志信息')
    logging.error('这是一个error级别的日志信息')
    logging.critical('这是一个critical级别的日志信息')
    
    • 运行结果

    image-20240902104703184

  • 日志等级和格式的设置:

    • 代码实现
    import logging
    
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
    
    logging.debug('这是一个debug级别的日志信息')
    logging.info('这是一个info级别的日志信息')
    logging.warning('这是一个warning级别的日志信息')
    logging.error('这是一个error级别的日志信息')
    logging.critical('这是一个critical级别的日志信息')
    
    • 运行结果
    2024-09-02 10:51:07,331 - 11-Python中使用logging设置输出日志等级和格式.py[line:6] - DEBUG: 这是一个debug级别的日志信息
    2024-09-02 10:51:07,331 - 11-Python中使用logging设置输出日志等级和格式.py[line:7] - INFO: 这是一个info级别的日志信息
    2024-09-02 10:51:07,332 - 11-Python中使用logging设置输出日志等级和格式.py[line:8] - WARNING: 这是一个warning级别的日志信息
    2024-09-02 10:51:07,332 - 11-Python中使用logging设置输出日志等级和格式.py[line:9] - ERROR: 这是一个error级别的日志信息
    2024-09-02 10:51:07,332 - 11-Python中使用logging设置输出日志等级和格式.py[line:10] - CRITICAL: 这是一个critical级别的日志信息
    
    • 参数说明
      • level:表示设置的日志等级
      • format:表示日志的输出格式
        • %(levelname)s: 打印日志级别名称
        • %(filename)s: 打印当前执行程序名
        • %(lineno)d: 打印日志的当前行号
        • %(asctime)s: 打印日志的时间
        • %(message)s: 打印日志信息
(4)logging在Web项目中应用
  • 代码实现
'''
FastAPI使用四步走:① 导入模块 ② 创建FastAPI对象 ③ 使用装饰器收发信息 ④ 启动服务器开始监听
'''
# ① 导入模块
from fastapi import FastAPI
from fastapi import Response
import logging

import uvicorn

# ② 创建FastAPI对象
app = FastAPI()

# 配置logging日志的输出信息(输出格式、输出到哪个文件)
f = open('fastapi.log', 'a', encoding='utf-8')
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    stream=f)

# ③ 使用装饰器收发信息
@app.get('/')  # 首页
def main():
    with open('source/html/index.html', 'rb') as f:
        data = f.read()
    logging.info('访问了/首页')
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='text/html')

# 添加一个小图标接收请求与处理返回
@app.get('/favicon.ico')
def get_ico():
    with open(f'source/html/favicon.ico', 'rb') as f:
        data = f.read()
    logging.info('访问了favicon.ico小图标')
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='image/x-icon')

# 使用装饰器处理图片请求
@app.get('/images/{path}')  # /images/0.jpg
def get_pic(path: str):  # 在Python函数中,可以这么写def 函数名称(参数: 建议的参数类型,可以不遵守)
    with open(f'source/images/{path}', 'rb') as f:
        data = f.read()
    logging.info(f'访问了/images/{path}图片')
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='jpg')

# 会用装饰器处理html请求
@app.get('/{path}')
def get_html(path: str):
    with open(f'source/html/{path}', 'rb') as f:
        data = f.read()
    logging.info(f'访问了/{path}文件')
    # 返回数据给客户端浏览器
    return Response(content=data, media_type='text/html')

# ④ 启动服务器开始监听
uvicorn.run(app, host='127.0.0.1', port=8000)
  • 请求页面,运行结果

image-20240902122418493

6、xpath

(1)lxml是什么
  • lxml是一款高性能的 Python HTML/XML 解析器,我们可以利用XPath,来快速的定位特定元素以及获取节点信息
(2)xpath是什么
  • XPath (XML Path Language) 是一门在 HTML\XML 文档中查找信息的语言,可用来在 HTML\XML 文档中对元素和属性进行遍历
  • W3School官方文档:http://www.w3school.com.cn/xpath/index.asp
(3)xpath的节点关系
  • 每个XML的标签我们都称之为节点,其中最顶层的节点称为根节点。

image-20240902142519869

image-20240902142603797

(4)chrome浏览器xpath helper插件

image-20240902145628707

  • 重启浏览器,输入url,点开xpath插件,即可输入xpath语法验证

image-20240902145850699

(5)xpath语法
  • XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
  • 使用xpathhelper插件选择标签时候,选中时,选中的标签会添加属性class=“xh-highlight”
  • 下面列出了最有用的表达式:

image-20240902151018313

  • 以下是一些案例

image-20240902151142900

image-20240902151119665

(6)案例1-豆瓣250

image-20240902152800986

  • 获取所有的a标签的href://a/@href

image-20240902152902456

  • 获取html下的head下的title的文本:/html/head/title/text()

image-20240902152959392

  • 获取html下的head下的link标签的href:/html/head/link/@href

image-20240902153100535

(7)xpath语法进阶

image-20240902151142900

  • 查找特定的节点:在xpath中,第一个元素的位置是1,最后一个元素的位置是last(),倒数第二个是last()-1

image-20240902153506457

(8)案例2-豆瓣250进阶
  • 选取所有的电影的名字://div[@class=‘hd’]/a/span[1]

image-20240902153957261

  • 选取所有的href://div[@class=‘hd’]/a/@href

image-20240902154200896

  • 选取所有的评分://span[@class=‘rating_num’]/text()

image-20240902172137350

  • 选取所有的评价人数://div[@class=‘star’]/span[last()]

image-20240902173805290

(9)选取未知节点
  • XPath 通配符可用来选取未知的 XML 元素。

image-20240902173918995

  • 案例

image-20240902151142900

image-20240902174022146

(10)选取若干路径
  • 通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

  • 案例

image-20240902151142900

image-20240902174321628

(11)案例-使用xpath爬取网页数据
from lxml import etree  # 把字符串转换为HTML结构
import requests

# 伪造浏览器的头信息
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
res = requests.get('http://www.splxx.cn/WarticleList.aspx?typeid=opDItqtHf7A=', headers=headers)

# 把数据转换为HTML结构 => 结合XPath读取
data = etree.HTML(res.text)
data = data.xpath('//div[@class="list_body"]//li/a/text()')

for row in data:
    print(row)
;