Search code examples
pythonpdfencodingpdfminer

Replace (cid:<number>) with chars using Python when extracting text from PDF files


I wrote a code in Python that extracts text from PDF files. But for some files Im getting some strange output. This is my code:

import requests

from io import BytesIO
from pdfminer.high_level import extract_text, extract_pages

pdf_link = 'https://www.neerach.ch/public/upload/assets/1417/MTB0321.pdf'

response = requests.get(pdf_link)
with BytesIO(response.content) as data:
        
    num_of_pages = len(list(extract_pages(data)))
    print('number of pages', num_of_pages)

    #extract first 5 pages
    text = extract_text(data, password='', page_numbers = None, maxpages = 5, caching=True, codec='utf-8', laparams=None)
    text = str(text)
    text = text.replace('\n\n\n', '\n\n').strip()
    print(text)

The result that im getting:

cid:3)
(cid:3)
(cid:3)
(cid:3)

(cid:3)
(cid:3)
(cid:3)

Nr. 3 | 2021

März 2021

(cid:3)
(cid:57)(cid:72)(cid:85)(cid:75)(cid:68)(cid:81)(cid:71)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:71)(cid:72)(cid:86)(cid:3)(cid:42)(cid:72)(cid:80)(cid:72)(cid:76)(cid:81)(cid:71)(cid:72)(cid:85)(cid:68)(cid:87)(cid:72)(cid:86)(cid:3)
(cid:3)
(cid:54)(cid:70)(cid:75)(cid:88)(cid:79)(cid:72)(cid:81)(cid:3)
(cid:3)
(cid:54)(cid:82)(cid:93)(cid:76)(cid:68)(cid:79)(cid:72)(cid:3)(cid:39)(cid:76)(cid:72)(cid:81)(cid:86)(cid:87)(cid:72)(cid:3)
(cid:3)
(cid:48)(cid:76)(cid:87)(cid:87)(cid:72)(cid:76)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:39)(cid:82)(cid:85)(cid:73)(cid:89)(cid:72)(cid:85)(cid:72)(cid:76)(cid:81)(cid:72)(cid:3)
(cid:3)
(cid:48)(cid:76)(cid:87)(cid:87)(cid:72)(cid:76)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:68)(cid:88)(cid:86)(cid:90)(cid:108)(cid:85)(cid:87)(cid:76)(cid:74)(cid:72)(cid:85)(cid:3)(cid:57)(cid:72)(cid:85)(cid:72)(cid:76)(cid:81)(cid:72)(cid:3)
(cid:3)
(cid:48)(cid:76)(cid:87)(cid:87)(cid:72)(cid:76)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:46)(cid:76)(cid:85)(cid:70)(cid:75)(cid:74)(cid:72)(cid:80)(cid:72)(cid:76)(cid:81)(cid:71)(cid:72)(cid:81)(cid:3)

(cid:20)(cid:3)

(cid:23)(cid:3)

(cid:20)(cid:21)(cid:3)

(cid:21)(cid:20)(cid:3)

(cid:21)(cid:24)(cid:3)

Mitteilungsblatt Neerach | Gemeindeverwaltung Neerach | Binzmühlestrasse 14 | 8173 Neerach
044 859 16 16 | [email protected] | www.neerach.ch

(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)
(cid:3)
(cid:3)
(cid:3)

Basically each char is replaced with (cid:<number>). But also, as you can see, I have some string values. I have also tried different types of encoding such as:

encodings = ["Adobe-GB1-0", "Adobe-GB1-1", "Adobe-GB1-2", "Adobe-GB1-3", "Adobe-GB1-4", "Adobe-GB1-5", "GB-EUC-H", "GB-EUC-V", "GB-H", "GB-V", "GBK-EUC-H", "GBK-EUC-V", "GBK2K-H", "GBK2K-V", 'utf-8',
           "GBKp-EUC-H", "GBKp-EUC-V", "GBT-EUC-H", "GBT-EUC-V", "GBT-H", "GBT-V", "GBTpc-EUC-H", "GBTpc-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V", "UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", 'utf-16',
          "UniGB-UTF16-V", "UniGB-UTF32-H", "UniGB-UTF32-V", "UniGB-UTF8-H", "UniGB-UTF8-V", "78-EUC-V", "78-H", "78-RKSJ-H", "78-RKSJ-V", "78-V", "78ms-RKSJ-H", "78ms-RKSJ-V", "83pv-RKSJ-H", 'utf-32',
          "90ms-RKSJ-H", "90ms-RKSJ-V", "90msp-RKSJ-H", "90msp-RKSJ-V", "90pv-RKSJ-H", "90pv-RKSJ-V", "Add-H", "Add-RKSJ-H", "Add-RKSJ-V", "Add-V", "Adobe-Japan1-0", "Adobe-Japan1-1", "Adobe-Japan1-2",
          "Adobe-Japan1-3", "Adobe-Japan1-4", "Adobe-Japan1-5", "Adobe-Japan1-6", "Adobe-Japan1-7", "EUC-H", "EUC-V", "Ext-H", "Ext-RKSJ-H", "Ext-RKSJ-V", "Ext-V", "H", "Hankaku", "Hiragana",  "HKm471-B5-H",
          "Adobe-KR-9", "UniAKR-UTF16-H", "UniAKR-UTF32-H", "UniAKR-UTF8-H", "ETenms-B5-V", "HKdla-B5-H", "HKdla-B5-V", "HKdlb-B5-H", "HKdlb-B5-V", "HKgccs-B5-H", "HKgccs-B5-V", "HKm314-B5-H", "HKm314-B5-V"]

How can I encode this type of response? What should I add/change in my code in order to get text resonse?


Solution

  • With more caveats (some of them told in Life is complex's comments) and using your sample data:

    import re
    def cidToChar(cidx):
        return chr(int(re.findall(r'\(cid\:(\d+)\)',cidx)[0]) + 29)
    
    xx = '''
    (cid:3)
    (cid:3)
    (cid:3)
    (cid:3)
    
    (cid:3)
    (cid:3)
    (cid:3)
    
    Nr. 3 | 2021
    
    März 2021
    
    (cid:3)
    (cid:57)(cid:72)(cid:85)(cid:75)(cid:68)(cid:81)(cid:71)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:71)(cid:72)(cid:86)(cid:3)(cid:42)(cid:72)(cid:80)(cid:72)(cid:76)(cid:81)(cid:71)(cid:72)(cid:85)(cid:68)(cid:87)(cid:72)(cid:86)(cid:3)
    (cid:3)
    (cid:54)(cid:70)(cid:75)(cid:88)(cid:79)(cid:72)(cid:81)(cid:3)
    (cid:3)
    (cid:54)(cid:82)(cid:93)(cid:76)(cid:68)(cid:79)(cid:72)(cid:3)(cid:39)(cid:76)(cid:72)(cid:81)(cid:86)(cid:87)(cid:72)(cid:3)
    (cid:3)
    (cid:48)(cid:76)(cid:87)(cid:87)(cid:72)(cid:76)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:39)(cid:82)(cid:85)(cid:73)(cid:89)(cid:72)(cid:85)(cid:72)(cid:76)(cid:81)(cid:72)(cid:3)
    (cid:3)
    (cid:48)(cid:76)(cid:87)(cid:87)(cid:72)(cid:76)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:68)(cid:88)(cid:86)(cid:90)(cid:108)(cid:85)(cid:87)(cid:76)(cid:74)(cid:72)(cid:85)(cid:3)(cid:57)(cid:72)(cid:85)(cid:72)(cid:76)(cid:81)(cid:72)(cid:3)
    (cid:3)
    (cid:48)(cid:76)(cid:87)(cid:87)(cid:72)(cid:76)(cid:79)(cid:88)(cid:81)(cid:74)(cid:72)(cid:81)(cid:3)(cid:46)(cid:76)(cid:85)(cid:70)(cid:75)(cid:74)(cid:72)(cid:80)(cid:72)(cid:76)(cid:81)(cid:71)(cid:72)(cid:81)(cid:3)
    
    (cid:20)(cid:3)
    
    (cid:23)(cid:3)
    
    (cid:20)(cid:21)(cid:3)
    
    (cid:21)(cid:20)(cid:3)
    
    (cid:21)(cid:24)(cid:3)
    
    Mitteilungsblatt Neerach | Gemeindeverwaltung Neerach | Binzmühlestrasse 14 | 8173 Neerach
    044 859 16 16 | [email protected] | www.neerach.ch
    
    (cid:3)(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)(cid:3)
    (cid:3)
    (cid:3)
    (cid:3)
    '''
    for x in xx.split('\n'):
      if x != '' and x != '(cid:3)':         # merely to compact the output
        abc = re.findall(r'\(cid\:\d+\)',x)
        if len(abc) > 0:
            for cid in abc: x=x.replace(cid, cidToChar(cid))
        print(repr(x).strip("'"))
    

    Output shows that cidToChar algorithm fails e.g. for German letters with umlaut/diaeresis (e.g. ausw\x89rtiger instead of auswärtiger): .\SO\66656067.py

    Nr. 3 | 2021
    März 2021
    Verhandlungen des Gemeinderates
    Schulen
    Soziale Dienste
    Mitteilungen Dorfvereine
    Mitteilungen ausw\x89rtiger Vereine
    Mitteilungen Kirchgemeinden
    1
    4
    12
    21
    25
    Mitteilungsblatt Neerach | Gemeindeverwaltung Neerach | Binzmühlestrasse 14 | 8173 Neerach
    044 859 16 16 | [email protected] | www.neerach.ch