Jak wyodrębnić tekst, linki i obrazy z plików PDF za pomocą języka Python

Python jest bardzo wszechstronnym językiem i programiści Pythona często muszą pracować z różnymi plikami i uzyskiwać zapisane w nich informacje w celu przetworzenia. Jednym z popularnych formatów plików, z którym na pewno spotkasz się jako programista Pythona, jest przenośny format dokumentu, popularnie znany jako PDF

Pliki PDF mogą zawierać tekst, obrazy i łącza. Podczas przetwarzania danych w programie w języku Python może zaistnieć potrzeba wyodrębnienia danych przechowywanych w dokumencie PDF. W przeciwieństwie do struktur danych, takich jak krotki, listy i słowniki, uzyskanie informacji przechowywanych w dokumencie PDF może wydawać się trudne.

Na szczęście istnieje wiele bibliotek, które ułatwiają pracę z plikami PDF i wyodrębnianie danych przechowywanych w plikach PDF. Aby poznać te różne biblioteki, przyjrzyjmy się, jak wyodrębnić teksty, linki i obrazy z plików PDF. Aby śledzić dalej, pobierz następujący plik PDF i zapisz go w tym samym katalogu, co plik programu w języku Python.

Aby wyodrębnić tekst z plików PDF za pomocą Pythona, użyjemy metody PyPDF2 biblioteka. PyPDF2 to bezpłatna biblioteka Pythona typu open source, której można używać do scalania, przycinania i przekształcania stron plików PDF. Może dodawać niestandardowe dane, opcje przeglądania i hasła do plików PDF. Co ważne, PyPDF2 może pobierać tekst z plików PDF.

Aby użyć PyPDF2 do wyodrębnienia tekstu z plików PDF, zainstaluj go za pomocą pip, który jest instalatorem pakietu dla Pythona. pip pozwala zainstalować różne pakiety Pythona na twoim komputerze:

1. Sprawdź, czy masz już zainstalowany pip, uruchamiając:

pip --version

Jeśli nie otrzymasz numeru wersji, oznacza to, że pip nie jest zainstalowany.

2. Aby zainstalować pip, kliknij zdobądź pipa aby pobrać skrypt instalacyjny.

Link otwiera stronę ze skryptem instalującym pip, jak pokazano poniżej:

Kliknij stronę prawym przyciskiem myszy i kliknij Zapisz jako, aby zapisać plik. Domyślna nazwa pliku to get-pip.py

Otwórz terminal i przejdź do katalogu z właśnie pobranym plikiem get-pip.py, a następnie uruchom polecenie:

sudo python3 get-pip.py

To powinno zainstalować pip, jak pokazano poniżej:

3. Sprawdź, czy pip został pomyślnie zainstalowany, uruchamiając:

pip --version

Jeśli się powiedzie, powinieneś otrzymać numer wersji:

Po zainstalowaniu pip możemy teraz rozpocząć pracę z PyPDF2.

1. Zainstaluj PyPDF2, wykonując następujące polecenie w terminalu:

pip install PyPDF2

2. Utwórz plik Python i zaimportuj PdfReader z PyPDF2, używając następującego wiersza:

from PyPDF2 import PdfReader

Biblioteka PyPDF2 udostępnia różnorodne klasy do pracy z plikami PDF. Jedną z takich klas jest PdfReader, której można używać między innymi do otwierania plików PDF, odczytywania ich zawartości i wyodrębniania tekstu z plików PDF.

3. Aby rozpocząć pracę z plikiem PDF, należy najpierw otworzyć plik. Aby to zrobić, utwórz instancję klasy PdfReader i przekaż plik PDF, z którym chcesz pracować:

reader = PdfReader('games.pdf')

Powyższa linia tworzy instancję PdfReadera i przygotowuje ją do dostępu do zawartości określonego pliku PDF. Instancja jest przechowywana w zmiennej o nazwie reader, która będzie musiała uzyskać dostęp do różnych metod i właściwości dostępnych w klasie PdfReader.

4. Aby sprawdzić, czy wszystko działa prawidłowo, wydrukuj liczbę stron przekazanego pliku PDF, korzystając z następującego kodu:

print(len(reader.pages))

Wyjście:

5

5. Ponieważ nasz plik PDF ma 5 stron, możemy uzyskać dostęp do każdej strony dostępnej w pliku PDF. Jednak liczenie zaczyna się od 0, podobnie jak konwencja indeksowania w Pythonie. Dlatego pierwszą stroną pliku PDF będzie strona o numerze 0. Aby pobrać pierwszą stronę pliku PDF, dodaj następujący wiersz do swojego kodu:

page1 = reader.pages[0]

Powyższa linia pobiera pierwszą stronę pliku PDF i zapisuje ją w zmiennej o nazwie page1.

6. Aby wyodrębnić tekst z pierwszej strony pliku PDF, dodaj następujący wiersz:

textPage1 = page1.extract_text()

Spowoduje to wyodrębnienie tekstu z pierwszej strony pliku PDF i zapisanie zawartości w zmiennej o nazwie textPage1. W ten sposób masz dostęp do tekstu na pierwszej stronie pliku PDF poprzez zmienną textPage1.

7. Aby potwierdzić pomyślne wyodrębnienie tekstu, możesz wydrukować zawartość zmiennej tekstPage1. Cały nasz kod, który drukuje również tekst na pierwszej stronie pliku PDF, pokazano poniżej:

# import the PdfReader class from PyPDF2
from PyPDF2 import PdfReader

# create an instance of the PdfReader class
reader = PdfReader('games.pdf')

# get the number of pages available in the pdf file
print(len(reader.pages))

# access the first page in the pdf
page1 = reader.pages[0]

# extract the text in page 1 of the pdf file
textPage1 = page1.extract_text()

# print out the extracted text
print(textPage1)

Wyjście:

Aby wyodrębnić łącza z plików PDF, przejdziemy do PyMuPDF, która jest biblioteką Pythona służącą do wyodrębniania, analizowania, konwertowania i manipulowania danymi przechowywanymi w dokumentach takich jak pliki PDF. Aby korzystać z PyMuPDF, powinieneś mieć Pythona 3.8 lub nowszego. Rozpocząć:

1. Zainstaluj PyMuPDF, wykonując następujący wiersz w terminalu:

pip install PyMuPDF

2. Zaimportuj PyMuPDF do pliku Pythona, używając następującej instrukcji:

import fitz

3. Aby uzyskać dostęp do pliku PDF, z którego chcesz wyodrębnić linki, musisz go najpierw otworzyć. Aby go otworzyć, wpisz następujący wiersz:

doc = fitz.open("games.pdf")

4. Po otwarciu pliku PDF wydrukuj liczbę stron pliku PDF, korzystając z następującej linii:

print(doc.page_count)

Wyjście:

5

4. Aby wyodrębnić linki ze strony w pliku PDF, musimy załadować stronę, z której chcemy wyodrębnić linki. Aby załadować stronę, wpisz poniższą linię, w której podasz numer strony, którą chcesz załadować, do funkcji o nazwie loading_page()

page = doc.load_page(0)

Aby wyodrębnić linki z pierwszej strony, przekazujemy 0 (zero). Liczenie stron zaczyna się od zera, podobnie jak w strukturach danych, takich jak tablice i słowniki.

5. Wyodrębnij linki ze strony, używając następującego wiersza:

links = page.get_links()

Wszystkie linki na podanej stronie, w naszym przypadku na stronie 1, zostaną wyodrębnione i zapisane w zmiennej zwanej linkami

6. Aby zobaczyć zawartość zmiennejlinks, wydrukuj ją w następujący sposób:

print(links)

Wyjście:

Na wydruku zwróć uwagę, że łącza do zmiennych zawierają listę słowników z parami klucz-wartość. Każdy link na stronie jest reprezentowany przez słownik, a rzeczywisty link jest przechowywany pod kluczem „uri”

7. Aby uzyskać łącza z listy obiektów przechowywanych pod nazwą zmiennejlinks, należy iterować po liście za pomocą instrukcji for in i wydrukować konkretne łącza przechowywane pod kluczem uri. Cały kod, który to robi, pokazano poniżej:

import fitz

# Open the PDF file
doc = fitz.open("games.pdf")

# Print out the number of pages
print(doc.page_count)

# load the first page from the PDF
page = doc.load_page(0)

# extract all links from the page and store it under - links
links = page.get_links()

# print the links object
#print(links) 

# print the actual links stored under the key "uri"
for obj in links:
  print(obj["uri"])

Wyjście:

5
https://www.statista.com/statistics/1292243/software-developers-average-age-when-first-coding/
https://sparkian.com/
https://www.codemonkey.com/

8. Aby uczynić nasz kod bardziej możliwym do ponownego wykorzystania, możemy go zrefaktoryzować, definiując funkcję wyodrębniającą wszystkie linki z pliku PDF oraz funkcję wydrukującą wszystkie linki znalezione w pliku PDF. W ten sposób możesz wywołać funkcje w dowolnym pliku PDF i odzyskać wszystkie linki w pliku PDF. Kod, który to robi, pokazano poniżej:

import fitz

# Extract all the links in a PDF document
def extract_link(path_to_pdf):
  links = []
  doc = fitz.open(path_to_pdf)

  for page_num in range(doc.page_count):
    page = doc.load_page(page_num)
    page_links = page.get_links()
    links.extend(page_links)
  return links

# print out all the links returned from the PDF document
def print_all_links(links):
  for link in links:
    print(link["uri"])

# Call the function to extract all the links in a pdf
# all the return links are stored under all_links
all_links = extract_link("games.pdf")

# call the function to print all links in the PDF
print_all_links(all_links)

Wyjście:

https://www.statista.com/statistics/1292243/software-developers-average-age-when-first-coding/
https://sparkian.com/
https://www.codemonkey.com/
https://scratch.mit.edu/
https://www.tynker.com/
https://codecombat.com/
https://lightbot.com/
https://sparkian.com

Z powyższego kodu funkcja ekstrakt_link() odbiera plik PDF, przegląda wszystkie strony w pliku PDF, wyodrębnia wszystkie linki i zwraca je. Wynik tej funkcji jest przechowywany w zmiennej o nazwie all_links

Funkcja print_all_links() pobiera wynik ekstraktu_link(), iteruje po liście i drukuje wszystkie rzeczywiste łącza znalezione w pliku PDF przekazanym do funkcji ekstrakt_link().

Aby wyodrębnić obrazy z pliku PDF, nadal będziemy używać PyMuPDF. Aby wyodrębnić obrazy z pliku PDF:

1. Zaimportuj PyMuPDF, io i PIL. Python Imaging Library (PIL) udostępnia narzędzia, które między innymi ułatwiają tworzenie i zapisywanie obrazów. io udostępnia klasy umożliwiające łatwą i wydajną obsługę danych binarnych.

import fitz
from io import BytesIO
from PIL import Image

2. Otwórz plik PDF, z którego chcesz wyodrębnić obrazy:

doc = fitz.open("games.pdf")

3. Załaduj stronę, z której chcesz wyodrębnić obrazy:

page = doc.load_page(0)

4. PyMuPdf identyfikuje obrazy w pliku PDF za pomocą numeru odniesienia (xref), który zwykle jest liczbą całkowitą. Każdy obraz w pliku PDF ma unikalny odnośnik zewnętrzny. Dlatego, aby wyodrębnić obraz z pliku PDF, musimy najpierw uzyskać numer odnośnika zewnętrznego, który go identyfikuje. Aby uzyskać numer odnośnika zewnętrznego obrazów na stronie, używamy funkcji get_images() w następujący sposób:

image_xref = page.get_images()
print(image_xref)

Wyjście:

[(7, 0, 699, 407, 8, 'DeviceRGB', '', 'X7', 'FlateDecode')]

get_images() zwraca listę krotek z informacjami o obrazie. Ponieważ na pierwszej stronie mamy tylko jeden obraz, jest tylko jedna krotka. Pierwszy element krotki reprezentuje odnośnik zewnętrzny obrazu na stronie. Dlatego odnośnik zewnętrzny obrazu na pierwszej stronie wynosi 7.

5. Aby wyodrębnić wartość odnośnika zewnętrznego dla obrazu z listy krotek, używamy poniższego kodu:

# get xref value of the image
xref_value = image_xref[0][0]
print(xref_value)

Wyjście:

[(7, 0, 699, 407, 8, 'DeviceRGB', '', 'X7', 'FlateDecode')]
7

6. Ponieważ masz już odnośnik identyfikujący obraz w pliku PDF, możesz wyodrębnić obraz za pomocą funkcji ekstrakt_image() w następujący sposób:

img_dictionary = doc.extract_image(xref_value)

Funkcja ta nie zwraca jednak rzeczywistego obrazu. Zamiast tego zwraca słownik zawierający między innymi binarne dane obrazu i metadane dotyczące obrazu.

7. Sprawdź w słowniku zwróconym przez funkcję ekstrakt_image() rozszerzenie pliku wyodrębnionego obrazu. Rozszerzenie pliku jest zapisane pod kluczem „ext”:

# get file extenstion
img_extension = img_dictionary["ext"]
print(img_extension)

Wyjście:

png

8. Wyodrębnij pliki binarne obrazu ze słownika zapisanego w img_dictionary. Pliki binarne obrazów są przechowywane pod kluczem „obraz”

# get the actual image binary data
img_binary = img_dictionary["image"]

9. Utwórz obiekt BytesIO i zainicjuj go binarnymi danymi obrazu reprezentującymi obraz. Tworzy to obiekt podobny do pliku, który może być przetwarzany przez biblioteki Pythona, takie jak PIL, dzięki czemu można zapisać obraz.

# create a BytesIO object to work with the image bytes
image_io = BytesIO(img_binary)

10. Otwórz i przeanalizuj dane obrazu zapisane w obiekcie BytesIO o nazwie image_io, korzystając z biblioteki PIL. Jest to ważne, ponieważ pozwala bibliotece PIL określić format obrazu, z którym próbujesz pracować, w tym przypadku PNG. Po wykryciu formatu obrazu PIL tworzy obiekt obrazu, którym można manipulować za pomocą funkcji i metod PIL, takich jak metoda save(), w celu zapisania obrazu w pamięci lokalnej.

# open the image using Pillow
image = Image.open(image_io)

11. Określ ścieżkę, w której chcesz zapisać obraz.

output_path = "image_1.png"

Ponieważ powyższa ścieżka zawiera tylko nazwę pliku wraz z rozszerzeniem, wyodrębniony obraz zostanie zapisany w tym samym katalogu, co plik Pythona zawierający ten program. Obraz zostanie zapisany jako image_1.png. Rozszerzenie PNG jest ważne, aby pasowało do oryginalnego rozszerzenia obrazu.

12. Zapisz obraz i zamknij obiekt ByteIO.

# save the image
image.save(output_path)

# Close the BytesIO object 
image_io.close()

Cały kod wyodrębniający obraz z pliku PDF pokazano poniżej:

import fitz
from io import BytesIO
from PIL import Image

doc = fitz.open("games.pdf")
page = doc.load_page(0)

# get a cross reference(xref) to the image
image_xref = page.get_images()

# get the actual xref value of the image
xref_value = image_xref[0][0]

# extract the image
img_dictionary = doc.extract_image(xref_value)

# get file extenstion
img_extension = img_dictionary["ext"]

# get the actual image binary data
img_binary = img_dictionary["image"]

# create a BytesIO object to work with the image bytes
image_io = BytesIO(img_binary)

# open the image using PIL library 
image = Image.open(image_io)

#specify the path where you want to save the image
output_path = "image_1.png"

# save the image
image.save(output_path)

# Close the BytesIO object 
image_io.close()

Uruchom kod i przejdź do folderu zawierającego plik Pythona; powinieneś zobaczyć wyodrębniony obraz o nazwie image_1.png, jak pokazano poniżej:

Wniosek

Aby uzyskać więcej praktyki w wyodrębnianiu linków, obrazów i tekstów z plików PDF, spróbuj refaktoryzować kod w przykładach, aby ułatwić ich ponowne użycie, jak pokazano w przykładzie z linkami. W ten sposób wystarczy przekazać plik PDF, a program w języku Python wyodrębni wszystkie łącza, obrazy i tekst z całego pliku PDF. Miłego kodowania!

Możesz także zapoznać się z najlepszymi interfejsami API plików PDF dla każdej potrzeby biznesowej.