PDF が英語でフォントが埋め込まれていない場合、PDF からテキストを抽出するのは通常簡単です。ただし、これらの前提が取り除かれると、pdfminer や pdfplumber などの基本的な Python ライブラリを使用するのが難しくなります。先月、私はグジャラート語の PDF からテキストを抽出し、名前、住所、都市などのデータ フィールドを JSON 形式にインポートするという任務を負いました。
フォントが PDF 自体に埋め込まれている場合、単純なコピー&ペーストは機能せず、pdfplumber を使用すると、判読できないジャンク テキストが返されます。したがって、各 PDF ページを画像に変換し、pytesseract ライブラリを使用して OCR を適用して、単にページを読み取るのではなく「スキャン」する必要がありました。このチュートリアルでは、その方法を説明します。
以下に示すように、pip コマンドを使用して Python ライブラリをインストールできます。 Tesseract-OCR の場合は、公式サイトからソフトウェアをダウンロードしてインストールします。 pytesseract は、tesseract ソフトウェアの単なるラッパーです。
pip install pdfplumber pip install pdf2image pip install pytesseract
最初のステップは、PDF ページを画像に変換することです。この extract_text_from_pdf() 関数はまさにそれを行います。PDF パスと page_num (インデックスはゼロ) をパラメータとして渡します。わかりやすくするために最初にページを白黒に変換していることに注意してください。これはオプションです。
# Extract text from a specific page of a PDF def extract_text_from_pdf(pdf_path, page_num): # Use pdfplumber to open the PDF pdf = pdfplumber.open(pdf_path) print(f"extracting page {page_num}..") page = pdf.pages[page_num] images = convert_from_path(pdf_path, first_page=page_num+1, last_page=page_num+1) image = images[0] # Convert to black and white bw_image = convert_to_bw(image) # Save the B&W image for debugging (optional) #bw_image.save("bw_page.png") # Perform OCR on the B&W image e_text = ocr_image(bw_image) open('out.txt', 'w', encoding='utf-8').write(e_text) #print("output written to file.") try: process_text(page_num, e_text) except Exception as e: print("Error occurred:", e) print("done..") # Convert image to black and white def convert_to_bw(image): # Convert to grayscale gray = image.convert('L') # Apply threshold to convert to pure black and white bw = gray.point(lambda x: 0 if x < 128 else 255, '1') return bw # Perform OCR using Tesseract on a given image def ocr_image(image_path): try: # Perform OCR custom_config = r'--oem 3 --psm 6 -l guj+eng' text = pytesseract.image_to_string(image_path, config=custom_config) # --psm 6 treats the image as a block of text return text except Exception as e: print(f"Error during OCR: {e}") return None
ocr_image() 関数は、pytesseract を使用して、OCR を通じて画像からテキストを抽出します。 --oem や --psm などの技術パラメータは画像の処理方法を制御し、-l guj eng パラメータは読み取られる言語を設定します。この PDF には英語のテキストが含まれているため、guj eng を使用しました。
OCR を使用してテキストをインポートしたら、必要な形式で解析できます。これは、pdfplumber や pypdf2 などの他の PDF ライブラリと同様に機能します。
nums = ['0', '૧', '૨', '૩', '૪', '૫', '૬', '૭', '૮', '૯'] def process_text(page_num, e_text): obj = None last_surname = None last_kramank = None print(f"processing page {page_num}..") for line in e_text.splitlines(): line = line.replace('|', '').replace('[', '').replace(']', '') parts = [word for word in line.split(' ') if word] if len(parts) == 0: continue new_rec = True for char in parts[0]: if char not in nums: new_rec = False break if len(parts) < 2: continue if new_rec and len(parts[0]) >= 2: # numbered line if len(parts) < 9: continue if obj: records.append(obj) obj = {} last_surname = parts[1] obj['kramank'] = parts[0] last_kramank = parts[0] obj['full_name'] = ' '.join(parts[1:4]) obj['surname'] = parts[1] obj['pdf_page_num'] = page_num + 1 obj['registered_by'] = parts[4] obj['village_vatan'] = parts[5] obj['village_mosal'] = parts[6] if parts[8] == 'વર્ષ': idx = 7 obj['dob'] = parts[idx] + ' વર્ષ' idx += 1 elif len(parts[7]) == 8 and parts[7][2] == '-': idx = 7 obj['dob'] = parts[idx] else: print("warning: no date") idx = 6 obj['marital_status'] = parts[idx+1] obj['extra_fields'] = '::'.join(parts[idx+2:-2]) obj['blood_group'] = parts[-1] elif parts[0] == last_surname: # new member in existing family if obj: records.append(obj) obj = {} obj['kramank'] = last_kramank obj['surname'] = last_surname obj['full_name'] = ' '.join(parts[0:3]) obj['pdf_page_num'] = page_num + 1 obj['registered_by'] = parts[3] obj['village_vatan'] = parts[4] obj['village_mosal'] = parts[5] if len(parts) <= 6: continue if parts[7] == 'વર્ષ': # date exists idx = 6 obj['dob'] = parts[idx] + ' વર્ષ' idx += 1 elif len(parts[6]) == 8 and parts[6][2] == '-': idx = 6 obj['dob'] = parts[idx] else: print("warning: no date") idx = 5 obj['marital_status'] = parts[idx+1] obj['extra_fields'] = '::'.join(parts[idx+2:-2]) obj['blood_group'] = parts[-1] elif obj: # continuation lines if ("(" in line and ")" in line) or "મો.ઃ" in line: obj['extra_fields'] += ' ' + '::'.join(parts[0:]) if obj: records.append(obj) jstr = json.dumps(records, indent=4) open("guj.json", 'w', encoding='utf-8').write(jstr) print(f"written page {page_num} to json..")
すべての PDF には、考慮する必要がある独自のニュアンスがあります。この場合、最初のフィールドの新しいシリアル番号 (0૧ や 0૨ など) は、後続のフィールド (姓) が変更されたときに新しいグループを示しました。
pytesseract は、IT テクノロジーの進化と進歩の証です。約 10 年前、適度な構成の PC またはラップトップで、英語以外の言語で OCR を使用して PDF 画像を読んだり解析したりすることは、ほぼ不可能でした。これはまさに進歩です!コーディングを楽しんでください。以下のコメントで仕上がり具合を教えてください。
以上が埋め込みフォント PDF からテキストのロックを解除する: pytesseract OCR チュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。