第三章 Python 编程进阶


第三章 Python 编程进阶

1、输入输出与文件操作

  1. 输入输出

基本输入、输出
2. 文件操作
文件编码、基本操作

1.1 输入

  1. Python 提供了 input() 内置函数从标准输入读入一行文本。
  2. input() 函数也可以接收一个 Python 表达式作为输入,并将运算结果返回。
  3. input() 函数的返回值永远是字符串,当我们需要返回 int 型时需要使用int(input()) 。

eval() 函数用来执行一个字符串表达式,并返回表达式的值。

str = input("请输入:")
print("你输入的内容是:", str)
sum = input("请输入算术表达式:")
sum = eval(sum)
print(sum)

请输入:Python编程学习
你输入的内容是: Python编程学习
请输入算术表达式:2+5
7

1.2 输出

  1. 用 print() 在括号中加上字符串,就可以向屏幕上输出指定的文字。比如:输出“hello world”,用代码实现如下:

print(“hello world”)
2. print() 函数也可以接受多个字符串,用逗号“,”隔开,就可以连成一串输出:
print(‘The quick brown fox’, ‘jumps over’, ‘the lazy dog!’)
3. print() 会依次打印每个字符串,遇到逗号”,”会输出一个空格,因此,输出的字符串是这样拼起来的:

print('The quick brown fox', 'jumps over', 'the lazy dog!')

The quick brown fox jumps over the lazy dog!

  1. print()也可以打印整数,或者计算结果:

print(300) # 输出300
print(100+200) # 输出300

  1. print()函数也可以接受多个字符串,用逗号“,”隔开,就可以连成一串输出:
print('100+200=', 100+200)

100+200= 300

对于100 + 200,Python解释器自动计算出结果300,但是,’100 + 200 =’是字符串而非数学公式,Python把它视为字符串。

1.3 格式化输出

1.3.1 整数的输出

1)%o —- oct 八进制
2)%d —- dec 十进制
3)%x —- hex 十六进制

print('%o' % 20)
print('%d' % 20)
print('%x' % 20)

24
20
14

1.3.2 浮点数的输出

1)

print('%f' % 1.11)     # 默认保留6位小数
print('%.1f' % 1.11)   # 取1位小数
print('%e' % 1.11)     # 默认6位小数,用科学计数法
print('%.3e' % 1.11)   # 取3位小数,用科学计数法
print('%g' % 1111.1111)    # 默认6位有效数字
print('%.7g' % 1111.1111)  # 取7位有效数字
print('%.2g' % 1111.1111)  # 取2位有效数字,自动转换为科学计数法1.1e+03

1.110000
1.1
1.110000e+00
1.110e+00
1111.11
1111.111
1.1e+03

2)
round(number[, ndigits])

number —- 这是一个数字表达式。
ndigits —- 表示从小数点到最后四舍五入的位数。默认值为 0。
:该方法返回 x 的小数点舍入为 n 位数后的值。

  1. round()函数只有一个参数,不指定位数时,返回一个整数,而且是最靠近的整数,类似于四舍五入。
  2. 当指定取舍的小数点位数的时候,一般情况也是使用四舍五入的规则。
  3. 但是碰到.5的情况时,如果要取舍的位数前的小数是奇数,则直接舍弃,如果是偶数则向上取舍。
round(1.1125)         # 四舍五入,不指定位数,取整
round(1.1135,3)     # 取3位小数,由于3为奇数,则向下“舍”
round(1.1125,3)     # 取3位小数,由于2为偶数,则向上“入”
round(2.675, 2)     # 取2们有效小数

1
1.113
1.113
2.67

round(2.675, 2) 的结果,结果应该是2.68的,但它偏偏是2.67,为什么?这跟浮点数的精度有关。在机器中浮点数不一定能精确表达,换算成一串1和 0 后可能是无限位数的,机器已经做出了截断处理。因此在机器中保存的2.675这个数字就比实际数字要小那么一点点。这一点点就导致了它离2.67要更近一点点,所以保留两位小数时就近似到了2.67。

1.3.3 字符串输出
  1. %s
  2. %10s —— 右对齐,占位符10位
  3. %.2s —— 截取2位字符串
print('%s' % 'hello world') # 字符串输出
print('%20s' % 'hello world') # 右对齐,取20位,不够则补位
print('%-20s' % 'hello world') # 左对齐,取20位,不够则补位
print('%.2s' % 'hello world') # 取2位
print('%10.2s' % 'hello world') # 右对齐,取2位
print('%-10.2s' % 'hello world') # 左对齐,取2位

结果:

hello world
         hello world
hello world         
he
        he
he       

2、文件

2.1 文件编码

2.1.1 ASCII 码
  1. ASCII(American Standard Code for Information Interchange),是一种的编码。
  2. ASCII 码使用指定的 7 位或 8 位二进制数组合来表示 128 或 256 种可能的字符。
  3. 英语中,用 128 个符号编码便可以表示全部,但是用来表示其他语言,128 个符号是不够。欧洲国家就决定,利用字节中闲置的最高位编入新的符号。欧洲国家编码体系,可以表示最多 256 个符号。
  4. 汉字多达 10 万左右,一个字节只能表示 256 种符号,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是 GB2312,使用两个字节表示一个汉字。
2.1.2 Unicode
  1. Unicode 码扩展自 ASCII 字元集
  2. Unicode 是计算机科学领域里的一项业界标准,包括字符集、编码方案等。
  3. Unicode 通常用表示一个字符,原有的英文编码从单字节变成双字节,只需要把高字节全部填为 0 就可以。
  4. 跨语言、跨平台进行文本转换和处理。
  5. 对每种语言中字符设定统一且唯一的二进制编码。
  6. 每个英文字母前都必然有二到三个字节是 0,这对于存储来说是极大的浪费。
2.1.3 UTF-8(8-bit Unicode Transformation Format)
  1. 可变长度的Unicode的实现方式。
  2. 使用 1~4 个字节表示一个符号,根据不同的符号而变化字节长度。

2.2 文件类型

2.2.1 文本文件

以 ASCII 码方式存储的文件

2.2.2 二进制文件

直接由比特 0 和比特 1 组成,没有统一字符编码

2.3 文件操作

2.3.1 打开文件

建立磁盘上的文件与程序中的对象相关联

  1. Python 通过解释器内置的 open() 函数打开一个文件,并实现该文件与一个程序变量的关联,open() 函数格式如下:
    <变量名>=open(<文件名>,<打开模式>)
  2. open() 函数有两个参数:文件名和打开模式。
  3. 文件名可以是文件的实际名字,也可以是包含完整路径的名字。
  4. 文件打开模式:只读,写入,追加等。这个参数是非强制的,默认文件访问模式为只读 (r)。
  5. open() 函数提供 7 种基本的打开模式
模式 说明
r 读模式(默认模式,可省略),如果文件不存在,抛出异常
w 写模式,如果文件已存在,先清空原有内容;如果文件不存在,创建新文件
x 写模式,创建新文件,如果文件已存在则抛出异常
a 追加模式,不覆盖文件中原有内容
b 二进制模式(可与 r、w、x 或 a 模式组合使用)
t 文本模式(默认模式,可省略)
+ 读、写模式(可与其他模式组合使用)
  1. 读写模式
模式 r r+ w w+ a a+
+ + + +
+ + + + +
创建 + + + +
覆盖 + +
指针在开始 + + + +
指针在结尾 + +
2.3.2 文件操作
  1. 读取

根据打开方式不同可以对文件进行相应的读写操作,Python提供4个常用的文件内容读取方法。

方法 含义
<file>.readall() 读入整个文件内容,返回一个字符串或字节流
<file>.read(size = -1) 从文件中读入整个文件内容,如果给出参数,读入前size长度的字符串或字节流
<file>.readline(size = -1) 从文件中读入一行内容,如果给出参数,读入前 size 长度的字符串或字节流
<file>.readlines(hint = -1) 从文件中读入所有行,以每行为元素形成一个列表,如果给出参数,读入 hint 行
  1. 写入

Python 提供 3 个与文件内容写入有关的方法

方法 含义
<file>. write(s) 向文件写入一个字符串或字节流
<file>. writelines(lines) 将一个元素为字符串的列表写入文件
<file>. seek(offset) 0:文件开头;1:当前位置;2:文件结尾
  1. 定位

  2. 其他:追加、计算等

  3. 上下文管理语句with

在实际开发中,读写文件应优先考虑使用上下文管理语句with。关键字with可以自动管理资源,不论因为什么原因跳出with块,总能保证文件被正确关闭。除了用于文件操作,with关键字还可以用于数据库连接、网络连接或类似场合。用于文件内容读写时,with语句的语法形式如下:

with open(filename, mode, encoding) as fp:
# 这里写通过文件对象 fp 读写文件内容的语句块
  1. 文件操作示例

编写程序将电话簿 teleAddressBook.txt 和电子邮件 emailAddressBook.txt 合并为一个完整的 addressBook.txt


姓名 电话号码
张伟 1534098751
王伟 1520878752
王芳 1520658753
李娜 1523098754
刘伟 1596098755

emailAddressBook.txt

姓名 邮箱
张伟 1534098751@qq.com
王伟 1520878752@qq.com
王芳 1520658753@qq.com
李伟 1520098754@qq.com

addressBook.txt

姓名 电话 邮箱
张伟 1534098751 1534098751@qq.com
王伟 1520878752 1520878752@qq.com
王芳 1520658753 1520658753@qq.com
李娜 1523098754
刘伟 1596098755
李伟 1520098754@qq.com
  1. 文件操作示例代码
with open('teleAddressBook.txt', 'rt') as ftele1:
    with open('emailAddressBook.txt', 'rt') as ftele2:
        ftele1.readline() # 跳过第一行
        ftele2.readline()
        lines1=ftele1.readlines()
        lines2=ftele2.readlines()
        # 建立空表用于存储姓名,电话,email
        list1_name=[]
        list1_tele=[]
        list2_name=[]
        list2_email=[]
        for line in lines1: # 获取第一个文本中的姓名和电话信息
            elements=line.split()
            list1_name.append(elements[0])
            list1_tele.append(elements[1])

        for line in lines2: # 获取第二个文本中的姓名和邮件信息
            elements=line.split()
            list2_name.append(elements[0])
            list2_email.append(elements[1])

        # 生成新的数据
        lines=[]
        lines.append('姓名\t电话\t\t邮箱\n')

        # 遍历列表1
        for i in range(len(list1_name)):
            s=''
            # 查看列表1中的名字是否在列表2中
            if list1_name[i] in list2_name:
                j=list2_name.index(list1_name[i])
                s='\t'.join([list1_name[i], list1_tele[i], list2_email[j]])
                s+='\n'
            else:
                s='\t'.join([list1_name[i], list1_tele[i], str('   ----   ')])
                s+='\n'
            lines.append(s)

        for i in range(len(list2_name)):
            s=''
            if list2_name[i] not in list1_name:
                s='\t'.join([list2_name[i], str('   ----   '), list2_email[i]])
                s+='\n'
                lines.append(s)

        # 写入文件
        ftele3=open('addressbook', 'w')
        ftele3.writelines(lines)

# 关闭文件
ftele3.close()
ftele1.close()
ftele2.close()
print('新的通讯录已合成')
2.3.3 关闭文件
  1. 切断文件与程序的联系
  2. 写入磁盘,并释放文件缓冲区

3、Excel 文件操作实例

3.1 Excel文件格式说明

  1. 一个 Excel 电子表格文档称为一个工作簿(workbook),一个工作簿保存在扩展名为 .xlsx 的文件中。
  2. 每个工作簿可以包含多个表(Sheet)。
  3. 用户当前查看的表(或关闭 Excel 前最后查看的表),称为活动表。
  4. 每个表都有一些列(地址是从 A 开始的字母)和一些行(地址是从1开始的数字)。
  5. 在特定行和列的方格称为单元格(cell)。
  6. 每个单元格都包含一个数字或文本值。

3.2 openpyxl 库

3.2.1 openpyxl 库特点
  1. 用于读取/写入 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。
  2. 使用 getter/setter 模式。你可以随时读取某个单元格的内容,并根据其内容进行相应的修改,openpyxl 会帮你记住每个单元格的状态。
  3. 虽然它支持修改已有文件,但由于其所支持的功能有限,读入文件时会忽略掉它所不支持的内容,再写入时,这些内容就丢失了。
3.2.2 openpyxl 库缺点
  1. 不支持 07 版本之前的 XLS 格式。
  2. 不支持 Excel 中的公式。
3.2.3 openpyxl 库常用操作
  1. 安装 openpyxl 库
  1. 导入 openpyxl 库
  1. 用 openpyxl 库打开 Excel 文档
  1. 从工作簿中取得工作表
  1. 从表中取得行和列

可以将 Worksheet 对象切片,取得 Excel 表格中一行、一列或一个矩形区域中的所有 Cell 对象,然后可以循环遍历这个切片中的所有单元格。

  1. 新建工作簿:新建工作簿不需要在系统中创建新文件,在内存中操作即可。
from openpyxl import Workbook
# 工作簿实例化
wb = Workbook()
  1. 从工作簿激活工作表
# 激活获取工作表,此方法调用 _active_sheet_index方法,默认索引为0,即第一个工作表
ws = wb.active
  1. 也可用 create_sheet() 方法创建工作表。
# 默认在最后添加工作表
ws1 = wb.create_sheet()
# 在指定位置添加工作表,位置0,即第一个
ws2 = wb.create_sheet(0)
  1. 可以通过工作表名称获取工作表,以下两种方式效果相同。
ws3 = wb["New Title"]
ws4 = wb.get_sheet_by_name("New Title")
  1. 通过 get_sheet_names() 获取工作簿所有工作表的名称,返回值为 list 类型。
>>> print(wb.get_sheet_names())
['Sheet2', 'New Title', 'Sheet1']
  1. 获取单元格
c = ws['A4'] # 利用坐标获取单元格,若单元格不存在,则被创建。
ws['A4'] = 4 # 对单元格的值直接赋值。

# 也可通过以下两种方式获取单元格,效果相同。
c = ws.cell('A4')
# 指定行和列获取,从 1 开始,不从 0 开始。
d = ws.cell(row = 4, column = 1)
  1. 利用切片方式获取指定区域的单元格
cell_range = ws['A1':'C2']
  1. 获取单元格后,写数据
c = ws.cell('A4’)
c.value = 'hello, world'
  1. 对实例化的工作簿调用 openpyxl.workbook.Workbook.save() 进行保存
wb.save('sample.xlsx')

3.3 Excel 文件(人口普查数据)处理实例

3.3.1 问题描述

处理2010年美国人口普查数据文件 censuspopdata.xlsx,Excle 文件中只有一张表,名为 ‘Population by Census Tract’。每一行都保存了一个普查区的数据。列分别是普查区的编号(A),州的简称(B),县的名称(C),普查区的人口(D)。

3.3.2 题目要求
  1. 编写程序,从人口普查 Excel 文件中读取数据,并计算出每个县的人口统计值。
  2. 题目要求以字典嵌套字典方式存储统计信息,最外层字典的键是州,州里的键是县,县里的键是 pop 和人口普查区数量。

dict = { ‘州’:{ ‘县1’: {‘pop’:9000, ‘人口普查区’:2}, }, }

3.3.3 求解步骤
  1. 从 Excel 电子表格中读取数据。
  2. 计算每个县中普查区的数目。
  3. 计算每个县的总人口。
  4. 打印结果。
3.3.4 待处理 Excel 文件
普查区编号 州(state) 乡/县(country) POP2010
01001020100 AL Autauge 1912
01001020200 AL Autauge 2170
01001020300 AL Autauge 3373
01001020400 AL Autauge 4386
01001020500 AL Autauge 10766
01001020600 AL Autauge 3668
01001020700 AL Autauge 2891
3.3.5 实例代码
import openpyxl, pprint
print('Opening workbook...')
wb = openpyxl.load_workbook('censuspopdata.xlsx')
sheet = wb.get_sheet_by_name('Population by Census Tract') # 获取人口统计Sheet工作表
countryData = {} # 定义统计结果保存字典
print('Reading rows...')

for row in range(2, sheet.max_row+1):# 从 Excel 文件第二行开始读取数据,至最后一行。前闭后开,不包括 max_row+1 行
    state = sheet['B' + str(row)].value # 读取州名
    country = sheet['C' + str(row)].value # 读取县名
    pop = sheet['D' + str(row)].value # 读取人口数量值

    countryData.setdefault(state, {})
    countryData[state].setdefault(country, {'tracts': 0, 'pop': 0})

    countryData[state][country]['tracts'] += 1 # 该县的人口普查次数+1
    countryData[state][country]['pop'] += int(pop) # 该县所有普查次区人口数量相加

print('Writing results...')
resultFile = open('census2010.py', 'w')
resultFile.write('allData = ' + pprint.pformat(countryData))
# pprint 生成一个字符串,格式化好的、有效的python代码
resultFile.close()
print('Done.')

运行结果

allData = {'AK':{'Aleutians East':{'pop': 3141, 'tracts': 1}, 'Aleutians West':{'pop': 5561, 'tracts': 2}, 'Anchorage':{'pop': 291826, 'tracts': 55},'Bethel':{'pop': 17013, 'tracts': 3},'Bristol Bay':{'pop': 997, 'tracts': 1},'Denali':{'pop': 1826, 'tracts': 1},'Dillingham':{'pop': 4847, 'tracts': 2},'Fairbanks North Star':{'pop': 97581, 'tracts': 19},'Haines':{'pop': 2508, 'tracts': 1},'Hoonah-Angoon':{'pop': 2150, 'tracts': 2},'Juneau':{'pop': 31275, 'tracts': 6},'Kenai Peninsula':{'pop': 55400, 'tracts': 13},'Ketchikan Gateway':{'pop': 13477, 'tracts': 4},'Kodiak Island':{'pop': 13592, 'tracts': 5},'Lake and Peninsula':{'pop': 1631, 'tracts': 1},'Matanuska-Susitna':{'pop': 88995, 'tracts': 24},'Nome':{'pop': 9492, 'tracts': 2},'North Slope':{'pop': 9430, 'tracts': 3},

4、自然语言处理实战

4.1 中文分词介绍

4.1.1 中文分词特点
  1. 词是最小的能够独立活动的有意义的语言成分。
  2. 汉语是以字为单位,不像西方语言,词与词之间没有空格之类的标志指示词的边界。
  3. 分词问题为中文文本处理的基础性工作,分词的好坏对后续中文信息处理其关键作用。
4.1.2 中文分词难点
  1. 分词规范,词的定义还不明确 (《统计自然语言处理》宗成庆)
  2. 歧义切分问题,交集型切分问题,多义组合型切分歧义等

结婚的和尚未结婚的 =>
结婚/的/和/尚未/结婚/的
结婚/的/和尚/未/结婚/的

  1. 未登录词问题有两种解释:

一是已有的词表中没有收录的词。
二是已有的训练语料中未曾出现过的词,一些网络新词,自造词一般都属于这些词。

4.1.3 中文分词方法
  1. 基于字典、词库匹配的分词方法(基于规则)

将待分的字符串与一个充分大的机器词典中的词条进行匹配。常用的有:正向最大匹配,逆向最大匹配,最少切分法。实际应用中,将机械分词作为初分手段,利用语言信息提高切分准确率。
2. 基于词频度统计的分词方法(基于统计)
相邻的字同时出现的次数越多,越有可能构成一个词语,对语料中的字组频度进行统计,基于词的频度统计的分词方法是一种全切分方法。jieba是基于统计的分词方法。
3. 基于知识理解的分词方法
该方法主要基于句法、语法分析,并结合语义分析,通过对上下文内容所提供信息的分析对词进行定界。由于汉语语言知识的笼统、复杂性,目前还处在试验阶段。

4.2 jieba 扩展库

4.2.1 jieba 是 Python 中一个重要的第三方中文分词函数库
  1. jieba分词,,有集成的python库,简单易用。
  2. 安装:

1)全自动安装: easy_install jieba 或者 pip install jieba / pip3 install jieba
2)半自动安装:先下载 https://pypi.python.org/pypi/jieba/ ,解压后运行 python setup.py install
3)手动安装:将 jieba 目录放置于当前目录或者 site-packages 目录
4)通过 import jieba 来引用

4.2.2 jieba 实现原理
  1. 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)。

例如:句子“抗日战争”生成的 DAG 中{0:[0,1,3]} 这样一个简单的 DAG,就是表示 0 位置开始,在 0,1,3 位置都是词,就是说 00,01,0~3 即 “抗”,“抗日”,“抗日战争”这三个词在dict.txt中是词。
2. 采用了动态规划查找最大概率路径,找出基于词频的最大切分组合。
根据动态规划查找最大概率路径的基本思路就是对句子从右往左反向计算最大概率,…依次类推, 最后得到最大概率路径,得到最大概率的切分组合。
3. 对于未登录词,采用了基于汉字成词能力的隐马尔科夫模型(HMM)模型,使用了 Viterbi 算法(一种最优路径算法)。

4.2.3 jieba 是 Python 中一个重要的第三方中文分词函数库
  1. 第三方库,需要安装

  2. 安装成功提示

Successfully installed jieba-0.39
3. 也可离线下载安装
个人推荐离线安装,因为网速,anaconda安装容易失败,我试了很多次了。
下载地址:https://pypi.org/project/jieba/#files)

4.2.4 jieba 支持三种分词模式
  1. 精确模式:试图将句子最精确地切开,适合文本分析。
  2. 全模式:把句子中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义。
  3. 搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
  4. 支持繁体分词
  5. 支持自定义词典
  6. MIT 授权协议(开源软件授权协议)
4.2.5 jieba 常用函数
  1. jieba.cut :

方法接受三个输入参数:
1)需要分词的字符串。
2)cut_all 参数用来控制是否采用全模式。
3)HMM 参数用来控制是否使用 HMM 模型。
2. jieba.cut_for_search :
方法接受两个参数:
1)需要分词的字符串。
2)是否使用 HMM 模型。
该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细。
3. jieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode),或者

4.3 jieba 扩展库示例

4.3.1 jieba 三种分词模式的区别
import jieba

'''
cut 方法有两个参数
1)第一个参数是我们想分词的字符串
2)第二个参数cut_all是用来控制是否采用全局模式
'''

# 全模式
word_list = jieba.cut("今天天气真好。亲爱的,我们去远足吧!", cut_all=True)
print("全模式:","|".join(word_list))

# 精确模式,默认就是精确模式
word_list = jieba.cut("今天天气真好。亲爱的,我们去远足吧!", cut_all=False)
print("精确模式:","|".join(word_list))

# 搜索引擎模式
word_list = jieba.cut_for_search("今天天气真好。亲爱的,我们去远足吧!")
print("搜索引擎模式:","|".join(word_list))

全模式: 今天|今天天气|天天|天气|真好|。|亲爱|的|,|我们|去|远足|吧|!
精确模式: 今天天气|真|好|。|亲爱|的|,|我们|去|远足|吧|!
搜索引擎模式: 今天|天天|天气|今天天气|真|好|。|亲爱|的|,|我们|去|远足|吧|!

4.3.2 TF-IDF 释义
  1. TF-IDF(term frequency–inverse document frequency)是一种用于的常用加权技术。
  2. TF意思是词频,指关键词在文中出现的次数除以全文总字数。
  3. IDF意思是逆文本频率指数,反映关键词的普遍程度——当一个词越普遍(即有大量文档包含这个词)时,其IDF值越低;反之,则IDF值越高。

TF-IDF=TF×IDF
$词频(TF)=\frac{某个词在文章中的出现次数}{文章的总词数}\times逆文档频率(IDF)=log(\frac{语料库的文档数}{包含该词的文档数+1})$

4.3.3 可以看出
  1. 当一个词在文档频率越高并且新鲜度高(即普遍度低),其TF-IDF值越高。
  2. TF-IDF兼顾词频与新鲜度,过滤一些常见词,保留能提供更多信息的重要词。
4.3.4 基于TF-IDF算法的关键词抽取
import jieba.analyse
jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
  1. sentence:待提取的文本。
  2. topK:返回几个 TF/IDF 权重最大的关键词,默认值为 20。
  3. withWeight:是否一并返回关键词权重值,默认值为 False。
  4. allowPOS:词性过滤,为空表示不过滤,若提供则仅返回符合词性要求的关键词。
4.3.5 基于TF-IDF算法的关键词抽取示例
import jieba.analyse
f = open("十九大报告节选.txt", "rb")
sentence = f.read()
keywords = jieba.analyse.extract_tags(sentence, topK=15, withWeight=True, allowPOS=('n','nr','ns'))
for item in keywords:
    print(item[0],item[1])

allowPOS词性过滤:n表示名词、nr表示人名、ns表示地名

4.3.6 基于TF-IDF算法的关键词抽取示例运行结果

十九大报告节选.txt 在目录C:\Users\用户名.spyder-py3下

(原始文档)
中国共产党第十九次全国代表大会,是在全面建成小康社会决胜阶段、中国特色社会主义进入新时代的关键时期召开的一次十分重要的大会。

大会的主题是:不忘初心,牢记使命,高举中国特色社会主义伟大旗帜,决胜全面建成小康社会,夺取新时代中国特色社会主义伟大胜利,为实现中华民族伟大复兴的中国梦不懈奋斗。

不忘初心,方得始终。中国共产党人的初心和使命,就是为中国人民谋幸福,为中华民族谋复兴。这个初心和使命是激励中国共产党人不断前进的根本动力。全党同志一定要永远与人民同呼吸、共命运、心连心,永远把人民对美好生活的向往作为奋斗目标,以永不懈怠的精神状态和一往无前的奋斗姿态,继续朝着实现中华民族伟大复兴的宏伟目标奋勇前进。

当前,国内外形势正在发生深刻复杂变化,我国发展仍处于重要战略机遇期,前景十分光明,挑战也十分严峻。全党同志一定要登高望远、居安思危,勇于变革、勇于创新,永不僵化、永不停滞,团结带领全国各族人民决胜全面建成小康社会,奋力夺取新时代中国特色社会主义伟大胜利。

初心 1.056602437712
小康社会 0.6097804820220001
特色 0.5239102226336
全党同志 0.512082614532
社会主义 0.50983069314
中国 0.3632784823992
全面 0.33744171159299996
时代 0.3303798174336
人民 0.3125617860198
大会 0.2465050141716
共命运 0.228315420044
机遇期 0.222561778594
伟大旗帜 0.214452476432
方得 0.1954708653386
牢记 0.18611115603679998

4.4 统计《三国演义》小说词频前20的词语

源代码

import jieba
f = open(".\三国演义.txt", "rb")
txt = f.read()
words = jieba.lcut(txt)
counts = {}

for word in words:
    if len(word) == 1: # 排除单个字的分词结果
        continue
    else:
        counts[word] = counts.get(word, 0) + 1

items = list(counts.items())
items.sort(key = lambda items: items[1], reverse = True)
for i in range(20):
    word, count = items[i]
    print("{0:<10}{1:>5}".format(word, count))

曹操 940
孔明 828
将军 762
却说 648
玄德 568
关公 508
丞相 489
二人 465
不可 436
荆州 420
玄德曰 385
孔明曰 385
不能 383
如此 376
张飞 350
商议 344
如何 337
主公 328
军士 311

4.5 统计《三国演义》分词后,词频数前50中,三国人物出现次数

源代码

import jieba
f = open(".\三国演义.txt", "rb")
txt = f.read()
words = jieba.lcut(txt)
counts = {}

for word in words:
    if len(word) == 1: # 排除单个字的分词结果
        continue
    elif word == "诸葛亮" or word == "孔明曰":
        rword = "孔明"
    elif word == "关公" or word == "云长":
        rword = "关羽"
    elif word == "玄德" or word == "玄德曰":
        rword = "刘备"    
    elif word == "孟德" or word == "丞相":
        rword = "曹操"    
    else:
        rword = word
        counts[word] = counts.get(word, 0) + 1

personlist = ["孔明","曹操","张飞","刘备","关羽","孙权","吕布","鲁肃","周瑜","赵云","马超","姜维","魏延","庞统","董卓","袁绍","孟获","陆逊","孙尚香","孙坚","孙策","司马懿","曹丕","张辽"]        


items = list(counts.items())
items.sort(key = lambda items: items[1], reverse = True)
for i in range(50):
    word, count = items[i]
    if personlist.count(word) > 0:
        print("{0:<10}{1:>5}".format(word, count))

曹操 940
孔明 828
张飞 350
吕布 302
刘备 278
孙权 266
赵云 257
司马懿 222
周瑜 218
袁绍 191
马超 185
魏延 177

5、图像处理实战

5.1 Pillow 扩展库

5.1.1 Pillow扩展库概述
  1. PIL(Python Imaging Library)是Python常用的图像处理库,功能非常强大,API 简单易用。
  2. 但 PIL 仅支持到 Python 2.7,加上年久失修。
  3. 一群志愿者在 PIL 的基础上创建了PIL的兼容版本,名字叫 Pillow,支持最新 Python 3.x,并加入许多新特性。
  4. Pillow 提供了广泛的文件格式支持,强大的图像处理能力,主要包括图像储存、图像显示、格式转换以及基本的图像处理操作等。
5.1.2 Pillow 扩展库主要功能
  1. 图像归档

对图像进行批处理、生成图像预览、图像格式转换等。

  1. 图像处理

图像基本处理、像素处理、颜色处理。

5.1.3 Pillow 扩展库主要操作
  1. 在 PIL 中,任何一个图像文件都可以用 Image 对象表示。

  2. Image 类的图像读取和创建方法

方法 描述
Image.open(filename) 根据参数加载图像文件
Image.new(mode, size, color) 根据给定参数创建一个新的图像
Image.open(StringIO.StringIO(buffer) 从字符串中获取图像
Image.frombytes(mode, size, data) 根据像素点data创建图像
Image.verify() 对图像文件完整性进行检查,返回异常
  1. Image 类有 4 个处理图片的常用属性
属性 描述
Image.format 标识图像格式或来源,如果图像不是从文件读取,值是None
Image.mode 图像的色彩模式,“L”灰度图像、“RGB”真彩色图像、“CMYK”出版图像
Image.size 图像宽度和高度,单位是像素(px),返回值是二元元组(tuple)
Image.palette 调色板属性,返回一个ImagePalette类型
  1. Image 类的图像转换和保存方法
方法 描述
Image.save(filename,format) 将图像保存为filename文件名,format是图片格式
Image.convert(mode) 使用不同的参数,转换图像为新的模式
Image.thumbnail(size) 创建图像的缩略图,size是缩略图尺寸的二元元组

生成图像的缩略图,其中(128,128)是缩略图的尺寸

from PIL import Image
im = Image.open("\img0.jpg") 
im.thumbnail((128, 128)) 
im.save("img0TN", "JPEG")
  1. Image 类能够对每个像素点或者一幅 RGB 图像的每个通道单独进行操作,split() 方法能够将 RGB 图像各颜色通道提取出来,merge() 方法能够将各独立通道再合成一幅新的图像。
方法 描述
Image.point(func) 根据函数 func 功能对每个元素进行运算,返回图像副本
Image.split() 提取 RGB 图像的每个颜色通道,返回图像副本
Image.merge(mode,bands) 合并通道,采用 mode 色彩,bands 是新色的色彩通道
Image.blend(img1, img2, alpha) 将两幅图片 img1 和 img2 按照如下公式插值后生成新的图像: img1 * (1.0 - alpha) + img2* alpha
  1. 颜色变换
from PIL import Image

im = Image.open('img1.jpg')
r,g,b = im.split()
om = Image.merge("RGB", (b, g, r)) om.save('img1BGR.jpg')
  1. 通道颜色变换
from PIL import Image

im = Image.open('img1.jpg')
r,g,b = im.split() # 获得RGB通道数据
newr = g.point(lambda i: i*0.9)
newg = g.point(lambda i: i<200) # 选择g通道值低于200的像素点
newb = b.point(lambda i: i)
om = Image.merge(im.mode, (newr, newg, b)) # 将3个通道合成新图像
om.save('img1Merge.jpg')
  1. PIL 库的 ImageFilter 提供的过滤图像方法
方法 描述
ImageFilter.BLUR 图像的模糊效果
ImageFilter.CONTOUR 图像的轮廓效果
ImageFilter.DETAIL 图像的细节效果
ImageFilter.EDGE_ENHANCE 图像的边界加强效果
ImageFilter.EDGE_ENHANCE_MORE 图像的阈值边界加强效果
ImageFilter.EMBOSS 图像的浮雕效果
ImageFilter.FIND_EDGES 图像的边界效果
ImageFilter.SMOOTH 图像的平滑效果
ImageFilter.SMOOTH_MORE 图像的阈值平滑效果
ImageFilter.SHARPEN 图像的锐化效果

生成图像模糊效果:套用滤镜

from PIL import Image
from PIL import ImageFilter

im = Image.open("img1.jpg")
om = im.filter(ImageFilter.BLUR) # 为图片使用模糊滤镜
om.save('img1_blur.jpg')
  1. PIL 库的 ImageEnhance 类提供了更高级的图像增强需求,提供调整色彩度、亮度、对比度、锐化等功能。
方法 描述
ImageEnhance.enhance(factor) 对选择属性的数值增强factor倍
ImageEnhance.Color(im) 调整图像的颜色平衡
ImageEnhance.Contrast(im) 调整图像的对比度
ImageEnhance.Brightness(im) 调整图像的亮度
ImageEnhance.Sharpness(im) 调整图像的锐度
  1. 高级图像增强示例
from PIL import Image
from PIL import ImageEnhance

im = Image.open("img1.jpg")

# 调整图像对比度
om = ImageEnhance.Contrast(im) 

# 图像对比度增强3倍
om.enhance(3).save('img1_EnContras t.jpg’)

5.2 验证码生成实战

5.2.1 题目要求

利用 PIL 的 ImageDraw 提供的绘图方法生成如下图的验证码,要求字母随机、填充颜色随机。

5.2.2 思路
  1. 使用库 PIL、random
  2. 画布:随机填充色
  3. 字母:指定字体(注意路径)、模糊滤镜 BLUR
5.2.3 验证码生成实战代码
from PIL import Image, ImageDraw, ImageFont, ImageFilter

import random

# 随机字母(65-90表示26个大写英文字母)
def rndChar():
    return chr(random.randint(65, 90))

# 随机颜色1(验证码背景颜色)
def rndColor():
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

# 随机颜色2(文字颜色)
def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

# 240*60
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))

# 创建 Font 对象
font = ImageFont.truetype('ARIALN.TTF', 36)

# 创建 Draw 对象
draw = ImageDraw.Draw(image)

# 填充每个像素
for x in range(width):
    for y in range(height):
        draw.point((x, y), fill=rndColor())

# 输出文字
for t in range(4):
    draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())

# 模糊
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')

验证码生成


文章作者: 谢舟
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 谢舟 !
 上一篇
第四章 Python 数据处理 第四章 Python 数据处理
第四章 Python 数据处理1、numpy 数组操作1.1 numpy 库概述1.1.1 引言 Python 中用列表(list)保存一组值,可用来当作数组使用,由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。为保存一个简单
2020-06-04
下一篇 
如何阅读一本书 如何阅读一本书
第一篇 阅读的层次第一章 阅读的活力与艺术1.1 主动的阅读阅读可以是一件多少主动的事。 阅读越主动,效果越好。 1.2 阅读的目标:为获得资讯而读,以及为求得理解而读1.3 阅读就是学习:指导型的学习,以及自我发现型的学习之间的差异只
2020-05-12
  目录