我想将docx文件中的文本提取到简单的txt文件中。 我知道这个问题可能看似简单或微不足道(我希望会是这样)但是我查看了几十个论坛主题,花了好几个小时试图自己解决并找不到解决方案......
我从Etienne's blog借用了以下代码。
如果我需要没有格式化的内容,它可以很好地工作。但... 由于我的文档包含简单的表格,因此我需要它们使用制表符来保持其格式。 所以不要这样:
Name Age Wage John 30 2000
这应该出现:
Name Age Wage John 30 2000
为了不相互滑动,我更喜欢使用双标签来获得更长的线条。 我稍微检查了一下XML结构,发现表中的新行用tr表示,列用tc表示。 所以我试图改变这一千种方法,但没有成功...... 虽然它没有真正起作用,但我复制了我接近解决方案的想法:
from lxml.html.defs import form_tags
try:
from xml.etree.cElementTree import XML
except ImportError:
from xml.etree.ElementTree import XML
import zipfile
WORD_NAMESPACE='{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
PARA = WORD_NAMESPACE + 'p'
TEXT = WORD_NAMESPACE + 't'
ROW = WORD_NAMESPACE + 'tr'
COL = WORD_NAMESPACE + 'tc'
def get_docx_text(path):
document = zipfile.ZipFile(path)
xml_content = document.read('word/document.xml')
document.close()
tree = XML(xml_content)
paragraphs = []
for item in tree.iter(ROW or COL or PARA):
texts = []
print(item)
if item is ROW:
texts.append('\n')
elif item is COL:
texts.append('\t\t')
elif item is PARA:
for node in item.iter(TEXT):
if node.text:
texts.append(node.text)
if texts:
paragraphs.append(''.join(texts))
return '\n\n'.join(paragraphs)
text_file = open("output.txt", "w")
text_file.write(get_docx_text('input.docx'))
text_file.close()
我不太清楚语法应该是什么样的。输出没有任何结果,并且在一些试验中它产生了一些东西,但它甚至比什么都没有。
我将print(item)
仅用于检查。但不是每一个ROW,COL和PARA项目都会列出我的ROWs。因此,似乎在for循环的条件下,程序似乎进入了术语的连接或连接。如果找不到ROW,它将不会执行剩下的2个选项,而是立即跳到下一个项目。我试着给出一个条款清单。
在其中if if / elif块我认为例如if item is ROW
应该检查'item'和'ROW'是否相同(实际上是它们)。
答案 0 :(得分:0)
上面的答案不会像你问的那样奏效。这适用于仅包含表格的文件;使用findall
进行一些额外的解析可以帮助您隔离非表数据,并使其适用于包含表和其他文本的文档:
TABLE = WORD_NAMESPACE + 'tbl'
for item in tree.iter(): # use this for loop instead
#print(item.tag)
if item.tag == TABLE:
for row in item.iter(ROW):
texts.append('\n')
for col in row.iter(COL):
texts.append('\t')
for ent in col.iter(TEXT):
if ent.text:
texts.append(ent.text)
return ''.join(texts)
答案 1 :(得分:0)
X or Y or Z
计算三个值中的第一个值,该值将转换为True
。非空字符串始终为True
。因此,for item in tree.iter(ROW or COL or PARA)
的计算结果为for item in tree.iter(ROW)
- 这就是为什么在循环中只获得行元素的原因。iter()
ElementTree
对象的方法只能接受一个标记名称,所以你应该只迭代整个树(如果文档不大则不会有问题)。is
不会在这里工作。它是一个身份运算符,只有在比较的对象相同时才返回True
(即变量比较指的是相同的 Python对象)。在你的if... elif...
中你比较了一个常量str(ROW,COL,PARA)和Element
对象,它在每次迭代中重新创建,所以,显然,这两个对象不是同一个对象比较将返回False
。if item.tag == ROW
。考虑到以上所有因素,你应该像这样重写你的循环部分:
for item in tree.iter():
texts = []
print(item)
if item.tag == ROW:
texts.append('\n')
elif item.tag == COL:
texts.append('\t\t')
elif item.tag == PARA:
for node in item.iter(TEXT):
if node.text:
texts.append(node.text)
if texts:
paragraphs.append(''.join(texts))