最近做了一个”浙江省高中信息技术高考题库系统”,后台用django框架,前端vue.js。其中有个功能模块就是把练习题目docx格式,批量导入数据库。具体做法就是前端上传word版的题目,后台批量逐段读取里面的题目,包括图片。
网络上搜索到的大部分的一次性读取docx中的所有图片。这样在我系统里行不通,因为我需要某段的图片属于哪一题的。图片要跟相应的题目一起写入数据库。
先上图吧

最终的目标就是把题目的内容、答案、解析、图片、题型等提取出来,其中图片以base64格式编码成字符,统一json格式,把多个题目的信息返回给前端确认题目时候识别正确,以列表形式返回给前端;形式如下:
[{“content”:”按照二叉树的定义,具有3个节点的二叉树形态有( )A.3种B.4种C.5种D.6种”,”answer”:”C”,”explain”:”略”,”type”:”选择题”,”pictures”:”data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAwADAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAw”}]
因为题库系统中题目的模型如下:
class Questions(models.Model):
QUESTION_TYPE_CHOICES = (
('选择题','选择题'),
('填空题','填空题'),
('简答题','简答题')
)
DIFFICULTY_LEVEL_CHOICES = (
('入门', '入门'),
('中级', '中级'),
('高级', '高级')
)
content = models.CharField(max_length=1000,verbose_name='内容')
# overview = models.CharField(max_length=100,verbose_name='内容概述,取内容的前25个字符',default='')
answer = models.CharField(max_length=200,verbose_name='正确答案')
explain = models.CharField(max_length=200,verbose_name='解析')
reference = models.CharField(max_length=20,verbose_name='引用哪里',help_text="比如引用5年高考3年模拟,写作53")
type = models.CharField(verbose_name='题型',max_length=10, choices=QUESTION_TYPE_CHOICES)
difficulty_level = models.CharField(verbose_name='难度', max_length=10, choices=DIFFICULTY_LEVEL_CHOICES,default=DIFFICULTY_LEVEL_CHOICES[0][0])
owner = models.ForeignKey(User, verbose_name='录入者',on_delete=models.CASCADE,related_name="questions")
add_time = models.DateTimeField(auto_now_add=True, verbose_name='录入时间')
last_edit_time = models.DateTimeField(auto_now_add=True, verbose_name='修改时间')
open_level = models.CharField(verbose_name='开放程度',choices=OPEN_LEVEL_CHOICES, max_length=10, default=OPEN_LEVEL_CHOICES[0][0])
#tags = TaggableManager()
top = models.BooleanField(default=False, verbose_name='置顶')
knowledgepoint = models.ForeignKey(KnowledgePoint,on_delete=models.CASCADE,verbose_name='知识点', related_name="questions")
order = OrderField(blank=True, for_fields=['knowledgepoint'], verbose_name='排序序号',
help_text="决定各节之间的排序序号,升序排序比如第一章为1,第二章为2;1.1为1;1.3为了3")
pictures = models.CharField(max_length=200000, blank=True)
class Meta:
verbose_name = '题目'
verbose_name_plural = verbose_name
ordering = ['order']
def __str__(self):
return self.content[len(self.content)//10]
前端确认无误或者修改后,把所有题目信息的列表重新post给后端,写入数据库
言归正传:其中如何逐段读取word内的图片
多说无益,先附上代码:
import docx
from docx.document import Document
from docx.text.paragraph import Paragraph
from docx.image.image import Image
from docx.parts.image import ImagePart
from docx.oxml.shape import CT_Picture
from PIL import Image
from io import BytesIO
import sys
def get_picture(document: Document, paragraph:Paragraph):
"""
document 为文档对象
paragraph 为内嵌图片的段落对象,比如第1段内
"""
result_list=[]
img_list = paragraph._element.xpath('.//pic:pic')
if len(img_list)==0 or not img_list:
return
for i in range(len(img_list)):
img: CT_Picture = img_list[i]
embed = img.xpath('.//a:blip/@r:embed')[0]
related_part: ImagePart = document.part.related_parts
image: Image = related_part.image
result_list.append(image)
return result_list
if __name__ =="__main__":
d = docx.Document('test.docx')
for i in range(len(d.paragraphs)):
paragraph = d.paragraphs[i]
image_list = get_picture(d, paragraph)
if not image_list:
continue
for image in image_list:
if image:
# 后缀
ext = image.ext
# 二进制内容
blob = image.blob
# 显示图片
Image.open(BytesIO(blob)).show()
效果如下:依次逐行读每张图片,并显示出来。这里只是测试,跟项目结合读取题目内容的部分空,下次再发出来

解说下源代码的关键地方:
import docx
from docx.document import Document #读取word的docx文件
from docx.text.paragraph import Paragraph #读取段落
from docx.image.image import Image #读取图片
for i in range(len(d.paragraphs)):
paragraph = d.paragraphs[i] #逐行读取第i自然段
img_list = paragraph._element.xpath(‘.//pic:pic’) #读取该自然段内的所有图片,返回列表
for i in range(len(img_list)):
img: CT_Picture = img_list[i]
embed = img.xpath(‘.//a:blip/@r:embed’)[0] #读取该自然段内的内嵌图片
if image:
后缀
ext = image.ext
二进制内容
blob = image.blob #blob方法获取二进制流文件
显示图片
Image.open(BytesIO(blob)).show() #BytesIO 转成字节流显示出来
本文章引用以下:
Original: https://blog.csdn.net/zhuwoqing/article/details/124854914
Author: 智者无言
Title: python逐段读取docx文件中的图片(高中信息技术题库系统)
相关阅读
Title: 皮尔逊相关系数python实现
一、皮尔逊相关系数
常见公式:

公式转换:

有关皮尔逊相关系数的具体内容可以在之前的文章中看到。
[En]
Specific content related to Pearson correlation coefficient can be seen in a previous article.
; 二、python实现
方法1:直接按公式算
import numpy as np
x=np.array([1,3,5])
y=np.array([1,3,4])
n=len(x)
sum_xy = np.sum(np.sum(x*y))
sum_x = np.sum(np.sum(x))
sum_y = np.sum(np.sum(y))
sum_x2 = np.sum(np.sum(x*x))
sum_y2 = np.sum(np.sum(y*y))
pc = (n*sum_xy-sum_x*sum_y)/np.sqrt((n*sum_x2-sum_x*sum_x)*(n*sum_y2-sum_y*sum_y))
print(pc)
方法2:调用numpy中的corrcoef方法
方法:
corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue)
参数:
x:array_like,包含多个变量和观测值的1-D或2-D数组,x的每一行代表一个变量,每一列都是对所有这些变量的单一观察。
y:array_like,可选,另外一组变量和观察,y具有与x相同的形状。
rowvar:bool, 可选,如果rowvar为True(默认值),则每行代表一个变量,并在列中显示。否则,转换关系:每列代表一个变量,而行包含观察。
bias:_NoValue,可选,没有效果,请勿使用
ddof:_NoValue,可选,没有效果,请勿使用
返回值:
R : ndarray,变量的相关系数矩阵。
代码:
import numpy as np
x=np.array([1,3,5])
y=np.array([1,3,4])
pc=np.corrcoef(x,y)
print(pc)
方法3:调用scipy.stats中的pearsonr方法
方法:
pearsonr(x, y)
参数:
x:(N,) array_like,Input array。
y:(N,) array_like,Input array。
返回值:
r : float,皮尔逊相关系数,[-1,1]之间。
p-value : float,Two-tailed p-value(双尾P值)。
注: p值越小,表示相关系数越显著,一般p值在500个样本以上时有较高的可靠性。可以理解为显著性水平。
代码:
from scipy.stats import pearsonr
import numpy as np
x=np.array([1,3,5])
y=np.array([1,3,4])
pc = pearsonr(x,y)
print("相关系数:",pc[0])
print("显著性水平:",pc[1])
方法4:调用pandas.Dataframe中的corr方法
方法:
def corr(self,method,min_periods)
参数:
method:可选值为{‘pearson’, ‘kendall’, ‘spearman’}
pearson:皮尔逊相关系数
kendall:肯德尔等级相关系数
spearman:斯皮尔曼等级相关系数
min_periods:样本最少的数据量,最少为1。
返回值:
返回值:各类型之间的相关系数DataFrame表格。
代码:
import pandas as pd
data=pd.DataFrame({"x":[1,3,5],"y":[1,3,4]})
print(data.corr("pearson"))
Original: https://blog.csdn.net/weixin_43876625/article/details/123919665
Author: 回一幻
Title: 皮尔逊相关系数python实现
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/287254/
转载文章受原作者版权保护。转载请注明原作者出处!