如何在python中使用reportlab,rtl和bidi创建包含波斯语(波斯语)文本的PDF

时间:2016-12-27 12:42:54

标签: python-3.x pdf reportlab persian farsi

我一直在努力根据内容创建PDF文件,这些内容可以是英文,波斯文,数字或其组合。

波斯文本存在一些问题,如:“اینیکمتنفارسیاست”

1-文本必须从右向左书写

2-单词中不同位置的字符之间存在差异(意味着字符根据周围的字符改变形状)

3-因为从右到左读取了句子,所以正常的textwrap无法正常工作。

3 个答案:

答案 0 :(得分:4)

使用Reportlab工作一段时间后,我们在组织和格式化方面遇到了一些问题。花了很多时间,有点复杂。 所以我们决定使用pdfkit和jinja2。这样我们就可以在html和CSS中进行格式化和组织,我们也不需要重新格式化波斯文本。

首先我们可以设计一个类似下面的html模板文件:

    <!DOCTYPE html>
        <html>
        <head lang="fa-IR">
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body >
            <p dir="rtl">سوابق کاری</p>
            <ul dir="rtl">
                {% for experience in experiences %}
                <li><a href="{{ experience.url }}">{{ experience.title }}</a></li>
                {% endfor %}
            </ul>
        </body>
        </html>

然后我们使用jinja2库将我们的数据渲染为Template,然后使用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)

答案 1 :(得分:2)

我使用reportlab创建PDf,但遗憾的是reportlab不支持阿拉伯语和波斯语字母,因此我使用了Vahid Mardani的'rtl'库和Meir Kriheli的'pybidi'库,使文本在PDF结果中看起来正确。

首先我们需要添加一个支持波斯语的字体来报告:

  1. 在ubuntu 14.04中:

    copy Bahij-Nazanin-Regular.ttf into
    /usr/local/lib/python3.4/dist-packages/reportlab/fonts folder
    
  2. 为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))
    
  3. 在下一步中,我们需要将波斯语文本字母重塑为正确的形状,并从右到左制作每个单词的方向:

        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
    

    并且为了添加项目符号或包装文本,我们可以使用以下函数:

        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] = '{} &#x02022;'.format(line_list[0])
               farsi_text = '<br/>'.join(line_list)
               return '<font>%s</font>' % farsi_text
           return '<font>%s &#x02022;</font>' % farsi_text
    

    用于测试我们可以编写的代码:

        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)
    

答案 2 :(得分:2)

如果有人想使用if( isset($_GET['count'])){ $username = $_GET['username']; $_SESSION['count'] = $_SESSION['count']+1; if(file_exists('countClick_images.txt')){ $myFile = fopen('countClick_images.txt', 'w') or die('unable to open file'); $txt = 'Username: ' .$username.' | Number of download: '.$_SESSION['count'].' | File Downloaded:'.$path ; fwrite($myFile,"\n". $txt); fclose($myFile); }else { $myfile = fopen("countClick_images.txt", "a") or die("Unable to open file!"); $txt = 'Username: ' .$username.' | Number of download: '.$_SESSION['count'].' | File Downloaded:'.$path ; fwrite($myfile, "\n". $txt); fclose($myfile); } } 从html模板生成pdf,可以这样做:

Django