r.a*_*.aj 6 pdf reportlab persian python-3.x farsi
我一直在尝试从可以是英语、波斯语、数字或它们的组合的内容创建 PDF 文件。
波斯语文本存在一些问题,例如:“??? ?? ??? ??????? ???”
?- 文字必须从右到左书写
2-单词中不同位置的字符之间存在差异(意味着字符会根据周围的字符改变形状)
3- 因为句子是从右到左阅读的,所以普通的 textwrap 不能正常工作。
我使用 reportlab 来创建 PDf,但不幸的是,reportlab 不支持阿拉伯语和波斯语字母表,所以我使用了 Vahid Mardani 的“rtl”库和 Meir Kriheli 的“pybidi”库来使文本在 PDF 结果中看起来正确。
首先我们需要在reportlab中添加一个支持波斯语的字体:
在 Ubuntu 14.04 中:
copy Bahij-Nazanin-Regular.ttf into
/usr/local/lib/python3.4/dist-packages/reportlab/fonts folder
Run Code Online (Sandbox Code Playgroud)将字体和样式添加到 reportlab:
from reportlab.lib.enums import TA_RIGHT
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont('Persian', 'Bahij-Nazanin-Regular.ttf'))
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='Right', alignment=TA_RIGHT, fontName='Persian', fontSize=10))
Run Code Online (Sandbox Code Playgroud)在下一步中,我们需要将波斯文本 Letters 重塑为正确的形状,并使每个单词的方向从右到左:
from bidi.algorithm import get_display
from rtl import reshaper
import textwrap
def get_farsi_text(text):
if reshaper.has_arabic_letters(text):
words = text.split()
reshaped_words = []
for word in words:
if reshaper.has_arabic_letters(word):
# for reshaping and concating words
reshaped_text = reshaper.reshape(word)
# for right to left
bidi_text = get_display(reshaped_text)
reshaped_words.append(bidi_text)
else:
reshaped_words.append(word)
reshaped_words.reverse()
return ' '.join(reshaped_words)
return text
Run Code Online (Sandbox Code Playgroud)
对于添加项目符号或包装文本,我们可以使用以下功能:
def get_farsi_bulleted_text(text, wrap_length=None):
farsi_text = get_farsi_text(text)
if wrap_length:
line_list = textwrap.wrap(farsi_text, wrap_length)
line_list.reverse()
line_list[0] = '{} •'.format(line_list[0])
farsi_text = '<br/>'.join(line_list)
return '<font>%s</font>' % farsi_text
return '<font>%s •</font>' % farsi_text
Run Code Online (Sandbox Code Playgroud)
为了测试我们可以编写的代码:
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
doc = SimpleDocTemplate("farsi_wrap.pdf", pagesize=letter, rightMargin=72, leftMargin=72, topMargin=72,
bottomMargin=18)
Story = []
text = '???? ???? ??????? ???? ???? ???? ???????? ???????? ???? ???? ????? ??? ??? ???? ??? ?? ???????? ????? ?? ???' \
'?? ????? ??????? ?? ???? ???? ????? ????? ?? ?? ????? ?????? ??????? ???? ????????. ??? ?? ??? ?? ??????? ????' \
' ???? ???? ???????? ?? ????????? ?? ????? ????? ?? ?? ?? ???? ?? ????????? ?????? ????? ??? ? ??? ?? ????? ??' \
' ????? ????. ????? ?? ?????? ?? ??? ?????? ?? ???? ???????? ??????? ?? ????????? ??????? ????. ??????? ?????? iOS ' \
'??? ??????? ????? ?? ??????? ?? ???????? ? ???????????? ????? ????? ??? ??????. ???????? ????? ?? ?????? ????? ???' \
'? ?? ?????? ?? ??? ????? ??????? ????. ?? ??? ??? ???? ??????? ????? ???? ???? ?? ???? ??? ??? ?? ?? ??? ????? ??' \
' ?????????.'
tw = get_farsi_bulleted_text(text, wrap_length=120)
p = Paragraph(tw, styles['Right'])
Story.append(p)
doc.build(Story)
Run Code Online (Sandbox Code Playgroud)
在使用 Reportlab 工作一段时间后,我们在组织和格式化它时遇到了一些问题。这花了很多时间,而且有点复杂。所以我们决定使用 pdfkit 和 jinja2。这样我们就可以在 html 和 CSS 中格式化和组织,而且我们也不需要重新格式化波斯文本。
首先我们可以设计一个像下面这样的html模板文件:
<!DOCTYPE html> <html> <head lang="fa-IR"> <meta charset="UTF-8"> <title></title> </头> <身体> <p dir="rtl">???????</p> <ul dir="rtl"> {% 体验经验 %} <li><a href="{{ Experience.url }}">{{ Experience.title }}</a></li> {% 结束为 %} </ul> </正文> </html>
然后我们使用 jinja2 库将我们的数据渲染到模板中,然后使用 pdfkit 从渲染结果创建一个 pdf:
from jinja2 import Template
from pdfkit import pdfkit
sample_data = [{'url': 'http://www.google.com/', 'title': '????'},
{'url': 'http://www.yahoo.com/fa/', 'title': '????'},
{'url': 'http://www.amazon.com/', 'title': '??????'}]
with open('template.html', 'r') as template_file:
template_str = template_file.read()
template = Template(template_str)
resume_str = template.render({'experiences': sample_data})
options = {'encoding': "UTF-8", 'quiet': ''}
bytes_array = pdfkit.PDFKit(resume_str, 'string', options=options).to_pdf()
with open('result.pdf', 'wb') as output:
output.write(bytes_array)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2729 次 |
最近记录: |