使用Python爬取信息403解决,并统计汇总绘制直方图,柱状图,折线图

39 篇文章 5 订阅
12 篇文章 5 订阅

使用Python爬取信息403解决,并统计汇总绘制直方图,柱状图,折线图

写这篇博客源于博友的提问
在这里插入图片描述

1. 效果图

拟录取专业-人数分布直方图效果图如下:
在这里插入图片描述

拟录取专业-人数效果图如下:
在这里插入图片描述

拟录取专业-人数柱状图效果图如下:

在这里插入图片描述

拟录取专业-人数折线图效果图如下:
在这里插入图片描述

2. 原理

  • 爬取403,可以在请求request里加入header,cookie;
  • 观察结果值为html以及td,class不太一样,介于标题和值不一样,最终决定找所有td进行处理

在这里插入图片描述

  • matplotlib图例超出范围,设置plt.tight_layout(),不太管用,fig.savefig(‘tight.png’, bbox_inches=‘tight’)查看保存后的图ok。

直接savefig时显示不全

fig.savefig(‘withoutTight.png’)

savefig时加上 bbox_inches=‘tight’ 后,可以解决

fig.savefig(‘tight.png’, bbox_inches=‘tight’)

3. 源码

# 1. 爬取数据:http://www.cdzy.cn/zsb/HTML/2021lq4.htm
# 2. 考生号,姓名,准考证号,拟录取专业保存到new_data.xls
# 3. 按"拟录取专业"统计各专业录取人数
# 4. 绘制“拟录取专业-录取人数”,直方图,柱状图,折线图
# -*- coding:utf-8 -*-
# USAGE
# python ask_pa_plot.py

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import requests
from lxml import html

# 正确显示中文和负号

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False


def getData(url):
    print(url)
    # # 设置请求超时(20s) 报错403
    # r = requests.get(url, timeout=1)
    # print(r) 
    # # 报错403
    # headers = {
    #     'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
    # r = requests.get(url=url, headers=headers)
    # print('addHeader: ', r)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        'Cookie': 'cf_clearance=1159d2ca806b3ebf2a85a8706f4b8c90ff6abc01-1517488982-1800'
    }

    r = requests.get(url, headers=headers)
    if r.status_code == requests.codes.ok:
        print('=== status_code === ', r.status_code)  # 响应码
        print('=== headers === ', r.headers)  # 响应头
        print('=== Content-Type === ', r.headers.get('Content-Type'))  # 获取响应头中的Content-Type字段

        # 解析数据
        r.encoding = 'utf-8'
        # print('content: ', type(r.text))
        # print(r.content)
        f = open("out.txt", "w", encoding='utf-8')
        f.write(r.text)
        f.close()

        tree = html.parse(url)
        d = {}

        all_td_val = tree.xpath('//td')
        print('all: ', len(all_td_val))
        # 跳过前6行无效行
        all_td_val = all_td_val[6:]

        # 获取标题列
        # th_td_val = tree.xpath('//td[@class="xl6931833"]')
        th_td_val = all_td_val[:4]
        header = []
        for i in th_td_val:
            hd = i.xpath('./text()')[0]
            header.append(hd)
            d.setdefault(str(hd), [])

        # 获取值,跳过标头4列
        all_td_val = all_td_val[4:]
        for i in range(len(all_td_val) // 4):
            for j in range(4):
                if (i * 4 + j >= len(all_td_val)): break
                val = all_td_val[i * 4 + j].xpath('./text()')
                if (len(val) == 0): continue
                val = all_td_val[i * 4 + j].xpath('./text()')[0]
                d[header.__getitem__(j)].append(val)

        print(d.keys())
        return d


# 直方图绘制
def plot_hist(pd):
    # print(np.unique(pd.values))
    # print(len(pd.values), len(np.unique(pd.values)))
    # edgecolor加分割线
    plt.hist(pd.values, bins=len(np.unique(pd.values)), edgecolor='black')
    labels = [i for i in pd.index]
    print(labels)
    # 设置图片标题
    plt.title("拟录取专业-人数分布直方图")
    plt.xlabel('专业')
    plt.ylabel('人数')
    plt.tight_layout()
    plt.show()


# 柱状图绘制
def plot_bar(pd):
    # 画图,plt.bar()可以画柱状图
    print(type(pd.keys), type(pd.values), type(pd.index))
    print(pd.keys)
    print(pd.values)
    print(pd.index[0])
    labels = [i for i in pd.index]
    bar = plt.bar(pd.keys(), pd.values, label=labels)
    # # 添加图例名称到图标
    # plt.legend(handles=bar.legend_elements()[0],
    #            labels=pd.keys(),
    #            title="拟录取专业", loc="upper right")
    plt.show()

    fig = plt.figure()
    for i, (x, y) in enumerate(pd.items()):
        print(i, x, y)
        plt.bar(x, y, label=x)
    # 设置图片标题
    plt.title("拟录取专业-人数柱状图")
    # 设置x轴标签名
    plt.xlabel("拟录取专业")
    # 设置y轴标签名
    plt.ylabel("人数")
    plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
    plt.tight_layout()
    # 显示
    plt.show()

    # 直接savefig时显示不全
    fig.savefig('withoutTight.png')
    # savefig时加上 bbox_inches='tight' 后,可以解决
    fig.savefig('tight.png', bbox_inches='tight')


# 折线图绘制
def plot_line(pd):
    fig = plt.figure()
    label = np.arange(len(pd.values))
    scatter = plt.scatter(pd.keys(), pd.values, c=label, marker="*")
    labels = [i for i in pd.index]
    plt.plot(pd.keys(), pd.values, label='拟录取专业人数', c='red', lw=5.0, ls="--")
    # 添加图例名称到图标
    plt.legend(handles=scatter.legend_elements()[0],
               labels=labels,
               title="拟录取专业", bbox_to_anchor=(-0.2, 1))
    # plt.legend(bbox_to_anchor=(-0.2, 1), loc='upper right', borderaxespad=0.)
    # 设置图片标题
    plt.title("拟录取专业-人数折线图")
    # 设置x轴标签名
    plt.xlabel("拟录取专业")
    # 设置y轴标签名
    plt.ylabel("人数")
    plt.tight_layout()
    # 显示
    plt.show()

    # 直接savefig时显示不全
    fig.savefig('withoutTight_z.png')
    # savefig时加上 bbox_inches='tight' 后,可以解决
    fig.savefig('tight_z.png', bbox_inches='tight')


url = 'http://www.cdzy.cn/zsb/HTML/2021lq4.htm'
dict = getData(url)
# print(dict)
pd = pd.DataFrame(dict)

pd_x = pd.groupby('拟录取专业')['姓名'].count()
print(pd_x)
# pd_arr = np.array(pd_x)
# for i, j in enumerate(pd_arr):
#     print(i, j)

plot_hist(pd['拟录取专业'])
plot_bar(pd_x)
plot_line(pd_x)

参考

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛一枚~

您的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值