Форум сайта python.su
0
Здравствуйте, я чайник, но решил соорудить какую нибудь полезную прогу. Суть в том что из zip контейнера .docx файла берется document.xml, потом к примеру с ним выполняются некоторые операции(вроде замены слов и т.д.), но я столкнулся с проблемой. При использовании функции str() от прочтенных строк все русские слова превращаются в подобное.
\xd0\x9d\xd0\xb5\xd0\xba\xd0\xbe\xd1\x82\xd0\xbe\xd1\x80\xd1\x8b\xd0\xb9
А при использование метода .decode() все слова в порядке, но после записи xml файла, он не читается.
z = ZipFile("Some text.docx", "r") file = z.open("word/document.xml").read().decode() f = open('temp/document.xml', 'w') f.write(file)
Прикреплённый файлы:
document.xml (1,8 KБ)
Офлайн
.
Отредактировано J.R. (Фев. 28, 2016 12:45:43)
Офлайн
0
J.R.
Можете тогда подсказать как изменить то, в какой кодировке будет записываться файл, ибо я уже совершенно потерян.
Офлайн
0
Все решено, спасибо мануалам питона и J.R., нужно было всего лишь открыть файл для записи в определенной кодировке.
z = ZipFile("Some text.docx", "r") file = z.open("word/document.xml").read().decode("utf-8") f = open('temp/document.xml', 'w', encoding="utf-8") f.write(file)
Офлайн
253
1. open тоже допускает указание кодировки.
2. чтобы получилось что-то полезное надо xml назад запихать.
3. есть https://python-docx.readthedocs.org/en/latest/
4. заменить слово будет сложно. MS Word произвольно режет текст на так называемые раны. Легко может оказаться что ваше слово разорвано и в его середину напихано 10 к служебной информации.
Офлайн
0
doza_and
Благодарю, но у меня немного другая цель(заменить кодовые слова тем, что приходит из интерфейса) вроде, пока тестил всё получалось, как в полной программе работать будет не знаю, но за библиотеку все равно спасибо. 
Офлайн
253
Чем раньше вы выкинете форд из своего инструментария тем вам будет легче!!!
Эта фиговина заменяет ключевые слова в виде ${name} которые находятся в вордовом документе на значения из словаря в файле данных. (точнее это ограниченая версия mako templates).
Такой ход был выбран поскольку надо было работать и с doc и с docx. И собирать ошметки слов очень накладно.
Предупреждаю - эта штука медленная.
Посмотрите внимательно - не код а море заплаток. см. первое предложение поста.
По идее не хватает предопределенных функций для вставки табличных данных.
#!/usr/bin/env python # -*- coding: utf-8 -*- u""" mako templates by win32com in winword """ import mako from mako.lookup import TemplateLookup from mako.template import Template from mako.lexer import Lexer import argparse import codecs import os import re import win32com.client from win32com.client import constants as c import time import shutil import yaml def subst_doc(word,doc,reprule): word.Selection.HomeKey(c.wdStory) fnd= word.Selection.Find fnd.ClearFormatting() fnd.Forward = True fnd.Format = False fnd.MatchCase = False fnd.MatchWholeWord = False fnd.MatchWildcards = False fnd.MatchSoundsLike = False fnd.MatchAllWordForms = False for a,b in reprule: fnd.Text = a.replace(u"\n",u"\r") fnd.Execute() e=word.Selection.End word.Selection.InsertAfter(b.replace(u"\n",u"\r")) e1=word.Selection.End word.Selection.End=e word.Selection.Cut() # word.Selection.Collapse(c.wdCollapseEnd) #in_file = u"ref.docx" #out_file = u"ref1.docx" #data_file = u"data.yaml" def convert(in_file, out_file, data_file,show_word=0): if data_file: with codecs.open(data_file,"r",encoding='utf-8') as f: data =yaml.load(f) else: data={} if in_file!=out_file: if os.path.exists(out_file): os.remove(out_file) shutil.copy(in_file,out_file) word = win32com.client.gencache.EnsureDispatch("Word.Application") word.Visible = show_word time.sleep(1) word.Documents.Open(os.path.abspath(out_file)) doc = word.Documents(word.ActiveDocument()) from win32com.client import constants as c try: text_b = doc.Content.Text.replace(u"\r",u"\n") lk= Lexer(text_b) text_a = Template(text_b).render(**data) res=lk.parse() reprule=[]# что ищем и на что заменяем i0_b=0 i0_a=0 expr_beg_b=0 expr_beg_a=0 expr_end_b=0 expr_end_a=0 control_count=0 for i in res.nodes: if type(i) is mako.parsetree.Text: ct=i.content # нашли блок текста pos_b=text_b[i0_b:].find(ct) pos_a=text_a[i0_a:].find(ct) pos_b+=i0_b pos_a+=i0_a # если мы не внутри циклов то это конец предыдущего выражения if control_count==0: expr_end_b=pos_b expr_end_a=pos_a # если есть конец то сбрасываем выражения в список if expr_end_b>expr_beg_b: reprule.append([text_b[expr_beg_b:expr_end_b],text_a[expr_beg_a:expr_end_a]]) # передвинули стартовую позицию на конец текста i0_b=pos_b+len(ct) i0_a=pos_a+len(ct) if control_count==0: # ставим начало на конец найденного текста expr_beg_b=i0_b expr_beg_a=i0_a else: # тут контролирем только вложенность for и if if type(i) is mako.parsetree.ControlLine: if i.isend: control_count-=1 else: control_count+=1 # если последним был шаблон то добразываем и его if not type(res.nodes[-1]) is mako.parsetree.Text: reprule.append([text_b[expr_beg_b:],text_a[expr_beg_a:]]) subst_doc(word,doc,reprule) doc.Save() finally: word.Quit() if __name__ == '__main__': parser = argparse.ArgumentParser(prog="word_mako",description="substitute data to word_mako infile outfile") parser.add_argument("-d","--data",default="",help=u"dile with data") parser.add_argument("-o","--output", help=u"output file") parser.add_argument("-w","--word", action='store_true', help=u"output file") parser.add_argument("file",help=u"input file") args = parser.parse_args() convert(args.file, args.output, args.data, show_word=args.word)
Отредактировано doza_and (Сен. 10, 2015 22:56:29)
Офлайн