爬取实习僧并进行数据可视化

网页传送门
在这里插入图片描述
实习僧有字体反爬,但是是静态的字体文件,所以难度不大。

解决实习增的字体反爬的思路:先把网页中字体文件的base64编码匹配下来,进行base64解码,下载下来,用字体可视化工具将所有字体按顺序写在一个列表里面记录下来,用TTFont方法处理这个文件得到的font对象,你会发现font对象的camp unicode编码的16进制就是网页中字体编码的后几位,把这个值前面加上’&#'就ok了。

具体过程:

1.匹配出编码,对编码进行base64解码,将内容保存为本地文件。

在这里插入图片描述

def get_ttf_data(url):
    html = get_html(url)
    buffer = re.findall('base64,(.*?)\)', html, re.S)[0]
    decoded_buffer = base64.b64decode(buffer)
    # 把这个文件下载下来,把里面对应的字体找出来
    with open('D://shixizeng.ttf','wb') as fp:
        fp.write(decoded_buffer)

2.用可视化工具查看字体文件,并按顺序写入列表。
在这里插入图片描述

map_list =[
        *list(map(str,range(10))), u'一', u'师', 'X', u'会', u'四', u'计', u'财', u'场', 'D', 'H',
        'L', 'P', 'T', u'聘', u'招', u'工', 'd', u'周', 'I', u'端', 'p', u'年', 'h', 'x', u'设', u'程',
        u'二', u'五', u'天', 't', 'C', 'G', u'前', 'K', 'O', u'网', 'S', 'W', 'c', 'g', 'k', 'o', 's',
        'w', u'广', u'市', u'月', u'个', 'B', 'F', u'告', 'N', 'R', 'V', 'Z', u'作', 'b', 'f', 'j', 'n',
        'r', 'v', 'z', u'三', u'互', u'生', u'人', u'政', 'A', 'J', 'E', 'I', u'件', 'M', '行', 'Q', 'U',
        'Y', 'a', 'e', 'i', 'm', u'软', 'q', 'u', u'银', 'y', u'联', 
    ]

3.根据此字体文件初始化font对象,得到font对象的camp键并取此键为16进制

def parse_ttf() -> dict:
    font = TTFont('D://shixizeng.ttf')
    # 由于实习增的这个文件页面刷新前后是不变的,所以不用前后进行字体文件的比对了
    font_base_order = font.getGlyphOrder()[2:]# 下载下来的文件头两个是空的
    # 新下载的问件与原文件进行比对
    # 前10个是0到9,从本地将对应的文字写出来
    map_list =[
        *list(map(str,range(10))), u'一', u'师', 'X', u'会', u'四', u'计', u'财', u'场', 'D', 'H',
        'L', 'P', 'T', u'聘', u'招', u'工', 'd', u'周', 'I', u'端', 'p', u'年', 'h', 'x', u'设', u'程',
        u'二', u'五', u'天', 't', 'C', 'G', u'前', 'K', 'O', u'网', 'S', 'W', 'c', 'g', 'k', 'o', 's',
        'w', u'广', u'市', u'月', u'个', 'B', 'F', u'告', 'N', 'R', 'V', 'Z', u'作', 'b', 'f', 'j', 'n',
        'r', 'v', 'z', u'三', u'互', u'生', u'人', u'政', 'A', 'J', 'E', 'I', u'件', 'M', '行', 'Q', 'U',
        'Y', 'a', 'e', 'i', 'm', u'软', 'q', 'u', u'银', 'y', u'联', 
    ]
    # 你会发现网页中编码对应的是font.getBestCmap()的key的16进制的值
    map_dict = {value: '&#' + hex(key)[1:]
                for key, value in font.getBestCmap().items()}
    # 将固定的字体顺序和uni编码进行一一对应,并从map_dict中寻找16进制的值对应的字体
    temp_dict = {map_dict[key]: value for key, value in zip(font_base_order, map_list)}
    # print(temp_dict)
    '''{'&#xf5df': '0', '&#xe9a8': '1', '&#xf4c1': '2', '&#xf051': '3', '&#xf621': '4', '&#xf801': '5', '&#xf4c0': '6', '&#xf850': '7', '&#xe39a': '8', '&#xee69': '9', '&#xf46f': '一', '&#xe087': '师', '&#xf38c': 'X', '&#xf56a': '会', '&#xebfd': '四', '&#xf85a': '计', '&#xe2c2': '财', '&#xeaf4': '场', '&#xe82f': 'D', '&#xf662': 'H', '&#xf273': 'L', '&#xf402': 'P', '&#xe04f': 'T', '&#xf4d6': '聘', '&#xe25b': '招', '&#xeba8': '工', '&#xe75d': 'd', '&#xe074': '周', '&#xe9c3': 'I', '&#xf613': '端', '&#xe7e0': 'p', '&#xe3de': '年', '&#xe8f2': 'h', '&#xf3a5': 'x', '&#xf49f': '设', '&#xe441': '程', '&#xeeaf': '二', '&#xf3b8': '五', '&#xeea4': '天', '&#xeb42': 't', '&#xe12a': 'C', '&#xe867': 'G', '&#xe687': '前',
    '&#xe473': 'K', '&#xec0b': 'O', '&#xf110': '网', '&#xf096': 'S', '&#xec72': 'W', '&#xe34d': 'c', '&#xeb26': 'g', '&#xe960': 'k', '&#xf5b5': 'o', '&#xece9': 's', '&#xeba9': 'w',
    '&#xe2ea': '广', '&#xe224': '市', '&#xf06e': '月', '&#xf797': '个', '&#xec80': 'B', '&#xecb8': 'F', '&#xf65f': '告', '&#xed05': 'N', '&#xe3a3': 'R', '&#xe5e7': 'V', '&#xe0ae': 'Z', '&#xed5e': '作', '&#xe979': 'b', '&#xe0bd': 'f', '&#xe5b5': 'j', '&#xf8e0': 'n', '&#xe8c1': 'r', '&#xf536': 'v', '&#xf769': 'z', '&#xee08': '三', '&#xf7cd': '互', '&#xe5d2': '生', '&#xefde': '人', '&#xe3ed': '政', '&#xf7b3': 'A', '&#xf0b6': 'J', '&#xf71a': 'E', '&#xf886': 'I', '&#xf09a': '件', '&#xe82d': 'M', '&#xf8c1': '行', '&#xef61': 'Q', '&#xf143': 'U', '&#xe929': 'Y', '&#xf72b': 'a', '&#xea74': 'e', '&#xedb3': 'i', '&#xe94f': 'm', '&#xe833': '软', '&#xeb22': 'q', '&#xefe4': 'u', '&#xe07c': '银', '&#xf525': 'y', '&#xe90c': '联'}'''
    return temp_dict

为了用pandas进行数据处理,所以此处写入csv
下面看一下爬虫代码

import requests
from requests.exceptions import RequestException
from fake_useragent import UserAgent
from lxml import etree
import codecs
from fontTools.ttLib import TTFont
import random
import re
import base64
from urllib.parse import urljoin
from multiprocessing.dummy import Pool
import csv

# 生成多个随机的user-agent
ua_list = [UserAgent().chrome for _ in range(10)]
# 初始化文件编码为utf8,可以避免出现乱码的情况
with open('D:/data_analysis.csv', 'ab+') as fp:
    fp.write(codecs.BOM_UTF8)
f = open('D:/data_analysis.csv', 'a+', newline='', encoding='utf8')
writer = csv.writer(f)
writer.writerow(['title', 'daily_money', 'location', 'degree', 'weekly_work', 'advantage'])

def get_html(url):
    try:
        headers = {'User-Agent': random.choice(ua_list)}
        session = requests.session()
        response = session.get(url,headers=headers)
        if response.status_code == 200:
            return response.content.decode()
        else:
            return None
    except RequestException:
        return None


def get_ttf_data(url):
    html = get_html(url)
    buffer = re.findall('base64,(.*?)\)', html, re.S)[0]
    decoded_buffer = base64.b64decode(buffer)
    # 把这个文件下载下来,把里面对应的字体找出来
    with open('D://shixizeng.ttf','wb') as fp:
        fp.write(decoded_buffer)


def parse_ttf() -> dict:
    font = TTFont('D://shixizeng.ttf')
    # 由于实习增的这个文件页面刷新前后是不变的,所以不用前后进行字体文件的比对了
    font_base_order = font.getGlyphOrder()[2:]# 下载下来的文件头两个是空的
    # 新下载的问件与原文件进行比对
    # 前10个是0到9,从本地将对应的文字写出来
    map_list =[
        *list(map(str,range(10))), u'一', u'师', 'X', u'会', u'四', u'计', u'财', u'场', 'D', 'H',
        'L', 'P', 'T', u'聘', u'招', u'工', 'd', u'周', 'I', u'端', 'p', u'年', 'h', 'x', u'设', u'程',
        u'二', u'五', u'天', 't', 'C', 'G', u'前', 'K', 'O', u'网', 'S', 'W', 'c', 'g', 'k', 'o', 's',
        'w', u'广', u'市', u'月', u'个', 'B', 'F', u'告', 'N', 'R', 'V', 'Z', u'作', 'b', 'f', 'j', 'n',
        'r', 'v', 'z', u'三', u'互', u'生', u'人', u'政', 'A', 'J', 'E', 'I', u'件', 'M', '行', 'Q', 'U',
        'Y', 'a', 'e', 'i', 'm', u'软', 'q', 'u', u'银', 'y', u'联', 
    ]
    # 你会发现网页中编码对应的是font.getBestCmap()的key的16进制的值
    map_dict = {value: '&#' + hex(key)[1:]
                for key, value in font.getBestCmap().items()}
    # 将固定的字体顺序和uni编码进行一一对应,并从map_dict中寻找16进制的值对应的字体
    temp_dict = {map_dict[key]: value for key, value in zip(font_base_order, map_list)}
    # print(temp_dict)
    '''{'&#xf5df': '0', '&#xe9a8': '1', '&#xf4c1': '2', '&#xf051': '3', '&#xf621': '4', '&#xf801': '5', '&#xf4c0': '6', '&#xf850': '7', '&#xe39a': '8', '&#xee69': '9', '&#xf46f': '一', '&#xe087': '师', '&#xf38c': 'X', '&#xf56a': '会', '&#xebfd': '四', '&#xf85a': '计', '&#xe2c2': '财', '&#xeaf4': '场', '&#xe82f': 'D', '&#xf662': 'H', '&#xf273': 'L', '&#xf402': 'P', '&#xe04f': 'T', '&#xf4d6': '聘', '&#xe25b': '招', '&#xeba8': '工', '&#xe75d': 'd', '&#xe074': '周', '&#xe9c3': 'I', '&#xf613': '端', '&#xe7e0': 'p', '&#xe3de': '年', '&#xe8f2': 'h', '&#xf3a5': 'x', '&#xf49f': '设', '&#xe441': '程', '&#xeeaf': '二', '&#xf3b8': '五', '&#xeea4': '天', '&#xeb42': 't', '&#xe12a': 'C', '&#xe867': 'G', '&#xe687': '前',
    '&#xe473': 'K', '&#xec0b': 'O', '&#xf110': '网', '&#xf096': 'S', '&#xec72': 'W', '&#xe34d': 'c', '&#xeb26': 'g', '&#xe960': 'k', '&#xf5b5': 'o', '&#xece9': 's', '&#xeba9': 'w',
    '&#xe2ea': '广', '&#xe224': '市', '&#xf06e': '月', '&#xf797': '个', '&#xec80': 'B', '&#xecb8': 'F', '&#xf65f': '告', '&#xed05': 'N', '&#xe3a3': 'R', '&#xe5e7': 'V', '&#xe0ae': 'Z', '&#xed5e': '作', '&#xe979': 'b', '&#xe0bd': 'f', '&#xe5b5': 'j', '&#xf8e0': 'n', '&#xe8c1': 'r', '&#xf536': 'v', '&#xf769': 'z', '&#xee08': '三', '&#xf7cd': '互', '&#xe5d2': '生', '&#xefde': '人', '&#xe3ed': '政', '&#xf7b3': 'A', '&#xf0b6': 'J', '&#xf71a': 'E', '&#xf886': 'I', '&#xf09a': '件', '&#xe82d': 'M', '&#xf8c1': '行', '&#xef61': 'Q', '&#xf143': 'U', '&#xe929': 'Y', '&#xf72b': 'a', '&#xea74': 'e', '&#xedb3': 'i', '&#xe94f': 'm', '&#xe833': '软', '&#xeb22': 'q', '&#xefe4': 'u', '&#xe07c': '银', '&#xf525': 'y', '&#xe90c': '联'}'''
    return temp_dict


def parse_html(url):
    html = get_html(url)
    part_path = 'https://www.shixiseng.com'
    hrefs = re.findall(
        '<a class="position-name" target="_blank" href="(.*?)" target="_blank">', html, re.S)
    temp_dict = parse_ttf()
    for href in hrefs:
        link = urljoin(part_path, href)
        _data = get_html(link)
        for key, value in temp_dict.items():
            _data = _data.replace(key, value)
        selector = etree.HTML(_data)
        divs = selector.xpath("//div[@class='job-header']")
        for div in divs:
            title = div.xpath("div[@class='new_job_name']/span/text()")[0]
            daily_money = div.xpath(
                "div[@class='job_msg']/span[@class='job_money cutom_font']/text()")[0]
            location = div.xpath(
                "div[@class='job_msg']/span[@class='job_position']/text()")[0]
            degree = div.xpath(
                "div[@class='job_msg']/span[@class='job_academic']/text()")
            if degree:
                degree = degree[0]
            weekly_work = div.xpath(
                "div[@class='job_msg']/span[@class='job_week cutom_font']/text()")[0]
            advantage = div.xpath("div[@class='job_good_list']//span/text()")
            advantage = ''.join(advantage)
            such_list = [title, daily_money, location, degree, weekly_work, advantage]
            print(such_list)
            writer.writerow(such_list)


if __name__ == "__main__":
    url = 'https://www.shixiseng.com/interns?k=python&p=1'
    urls = ['https://www.shixiseng.com/interns?k=python&p={}'.format(i) for i in range(30)]
    get_ttf_data(url)
    parse_ttf()
    # 多线程
    pool = Pool(8)
    ret = pool.map(parse_html, urls)
    pool.close()
    pool.join()
    f.close()

数据就搞下来了。。。
在这里插入图片描述

下面进行数据处理,并可视化进行分析一哈,看了两星期的《利用Python进行数据分析》,第一次弄这,是有点菜的了。

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
from pyecharts import Bar, Pie, WordCloud
import csv
import string
import jieba
import re

# 生成工作城市分布的饼状图
df = pd.read_csv('D:/data_analysis.csv')
# 按照工作城市进行分组,统计每个城市的总数
loc_s = df.groupby(['location']).size()
sorted_s = loc_s.sort_values()[-8:]
# 将Series的Index对象转化为list对象
x = list(sorted_s.index)[::-1]
y = list(sorted_s.values)[::-1]
pie = Pie('工作城市分布')
pie.add('工作城市', x, y, is_label_show=True)
pie.render('city1.html')


# 生成每日工资的分布的柱状图
df = pd.read_csv('D:/data_analysis.csv')
loc_s = df.groupby(['daily_money']).size()
sorted_s = loc_s.sort_values()[-10:]
# 将Series的Index对象转化为list对象
x = list(sorted_s.index)[::-1]
y = list(sorted_s.values)[::-1]
bar1 = Bar('实习信息可视化', '实习每天工资', page_title='每日工资分布')
bar1.add('每日工资', x, y, is_more_utils=True, is_datazoom_show=True,
         xaxis_interval=0, xaxis_rotate=30, yaxis_rotate=30)
bar1.render('salary.html')


# 生成职位优待的词云图
df = pd.read_csv('D:/data_analysis.csv')
# 处理缺失值
content_list = df['advantage'].dropna()
# 获取纯文本并剔除符号
content = ''.join(content_list.values)
need_sub = '[' + ',。’;:、/\\\. !?' + string.digits +']'
content = re.sub(need_sub, '', content)
# jieba精准匹配
words = jieba.lcut(content)
# 词频统计
counts = dict()
for word in words:
    counts[word] = counts.get(word, 0) + 1
items = list(counts.items())
# 排序
items.sort(key=lambda x: x[1], reverse=True)
# 取出计数列表里面前50个元组的第一个值
use_list_x = [item[0] for index, item in enumerate(items) if index < 1000]
use_list_y = [item[1] for index, item in enumerate(items) if index < 1000]
wordcloud = WordCloud(width=1300, height=620)
wordcloud.add('', use_list_x, use_list_y)
wordcloud.render('word_count.html')

在这里插入图片描述
可以看到实习岗位的城市分布

在这里插入图片描述
在这里插入图片描述

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值