---
title: "PDF'den Veri Çıkarma: Tablolar, Metin ve OCR"
description: "Önce PDF'te metin katmanı olup olmadığına bakın. Varsa Excel ya da pdfplumber tabloları okur; taranmış sayfalar OCR ister. Test edilmiş Python kodu yazıda."
url: https://proxynet.io/tr/blog/extract-data-from-pdf
date: 2026-09-28
author: "Acar Diveroli"
category: "Nasıl Yapılır, Web Scraping"
lang: tr
---

# PDF'den Veri Çıkarma: Tablolar, Metin ve OCR

Tedarikçiniz fiyat listesini her ay 40 sayfalık bir PDF olarak gönderiyor. Finans ekibi banka ekstrelerini aynı biçimde alıyor, geçen hafta satın aldığınız pazar raporunun en işe yarar tablosu da 17. sayfada duruyor. Bu satırları bir elektronik tabloya aktarmanız gerekiyor. Elle kopyalamak sütunları bozuyor, eksi işaretlerini düşürüyor ve bir saatinizi alıyor; üstelik gelecek ay aynı saati yeniden harcayacaksınız.

Bu yazı, yöntemi belirleyen soruyla, yani dosyada metin katmanı olup olmadığıyla başlıyor. Ardından Excel'in PDF bağlayıcısını, pdfplumber'ı, Camelot ile tabula-py'ı, taranmış belgeler için Tesseract ile OCR'ı ve bir klasör dolusu PDF'i tek bir CSV'ye dönüştüren toplu işlem betiğini anlatıyoruz. Örneklerin hepsini ReportLab ile ürettiğimiz örnek PDF'ler üzerinde çalıştırdık.

> **Not: Kısa cevap**
>
> Önce PDF'teki metni seçip seçemediğinize bakın. Seçebiliyorsanız dosyada metin katmanı vardır: birkaç dosya için Excel'deki **Veri > Veri Al > Dosyadan > PDF'den** yolu tabloları doğrudan yükler, düzenli tekrarlanan işlerde ise `pdfplumber` kullanan bir Python betiği bütün bir klasördeki metni ve tabloları CSV'ye aktarır. Metni seçemiyorsanız sayfalar görüntüden ibarettir: sayfaları resme dönüştürüp OCR uygulayın (`pytesseract` üzerinden Tesseract), ardından rakamları kontrol edin, çünkü OCR çıktısı birebir kopya değil, en iyi tahmindir.

## PDF'den veri çıkarma ne demek?

PDF'den veri çıkarma, baskı için dizilmiş içeriği sıralayabileceğiniz ve başka bir yere yükleyebileceğiniz satırlara ve alanlara dönüştürmektir. Bir PDF "dört sütunlu bir tablo" saklamaz. "`1,007.50` değerini bu konuma, bu yazı tipiyle çiz" ve "buradan şuraya bir çizgi çek" gibi talimatlar saklar. Her veri çıkarma aracı tabloyu bu koordinatlardan yeniden kurar; aynı dosyanın bir araçta temiz, başka bir araçta karmakarışık çıkmasının nedeni budur.

Yapılan iş, bir web sayfasından alanları ayıklamakla aynıdır ([Web Sitesinden Veri Çekme](/tr/blog/extract-data-from-website)); tek fark, HTML etiketlerinin yerini konumu belli karakterlerin almasıdır. Web sitelerinden çok sayıda PDF toplamak da daha geniş bir [veri kazıma](/tr/data-scraping) akışının parçasıdır.

## Metin PDF'i mi, taranmış PDF mi: nasıl anlaşılır?

- **Metin (dijital) PDF.** Word'den, bir muhasebe sisteminden ya da raporlama aracından dışa aktarılmıştır. Karakterler metin olarak saklanır, dolayısıyla veri çıkarma dosyadaki rakamları birebir okur.
- **Taranmış (görüntü) PDF.** Her sayfa bir kâğıdın fotoğrafıdır. OCR (optik karakter tanıma) karakterleri piksellerden tahmin edene kadar ortada metin yoktur.

Hızlı test: Ctrl+F'ye basın ve ekranda gördüğünüz bir kelimeyi arayın. Kelime bulunuyorsa metin katmanı vardır. Kodda, pdfplumber'daki `page.chars` listesinin boş gelmesi o sayfanın taranmış olduğunu gösterir. Bazı dosyalarda ikisi bir arada bulunur (örneğin imza sayfası taranmış dijital bir rapor); bu yüzden kontrolü dosya başına değil, sayfa başına yapın.

## PDF'den tablo çıkarma nasıl çalışır?

Excel, pdfplumber ya da Camelot kullanmanız fark etmez, arka planda aynı adımlar işler:

1. **Sayfa ayrıştırılır.** Her karakter konumu, yazı tipi ve boyutuyla birlikte okunur; çizilen çizgiler ve dikdörtgenler de alınır.
2. **Karakterler kelimelere ve satırlara dönüşür.** Aynı taban çizgisi üzerindeki yakın karakterler kelimeleri, aynı yükseklikteki kelimeler satırı oluşturur.
3. **Tablo alanları bulunur.** Bunun için ızgara oluşturan çizgilere ya da aralarında boşluk bulunan hizalı kelime sütunlarına bakılır.
4. **Hücreler kurulur.** Çizgi kesişimleri ya da sütun aralıkları hücre sınırlarını belirler, her kelime kendisini içeren hücreye yerleşir.
5. **Satırlar döndürülür.** Sonuç, temizleyip kaydedeceğiniz bir satır listesi (ya da DataFrame) olur.

Sorunların çoğu 3. adımda çıkar. Tam ızgaralı bir tablo kolaydır; kenarlıksız bir tabloda araç sütunları boşluklardan tahmin etmek zorunda kalır ve tek bir uzun ürün adı bütün sütunları kaydırabilir.

## PDF veri çıkarma yöntemlerinin karşılaştırması

| Yöntem | Kod gerekir mi? | Taranmış sayfaları okur mu? | En uygun olduğu iş | Nerede tıkanır |
|---|---|---|---|---|
| Kopyala yapıştır | Hayır | Hayır | Bir kez, tek bir küçük tablo | Sütunlar tek hücrede birleşir, çok sayfalı tablolar |
| Excel, Veri Al > PDF'den | Hayır | Hayır | Ayda birkaç dosya, analiz Excel'de | Kenarlıksız tablolar, düzeni farklı çok sayıda dosya |
| pdfplumber (Python) | Evet | Hayır | Metin ve tablo birlikte, toplu işler, ince ayar | Kenarlıksız tablolarda ayar ister |
| Camelot (Python) | Evet | İsteğe bağlı ek paketle | Çizgili tablolar, tablo başına doğruluk raporu | Tabloların çevresindeki serbest metin |
| tabula-py (Python) | Evet | Hayır | Tablo ağırlıklı dosyalardan hızlıca DataFrame | Makinede Java kurulu olmalı |
| pytesseract ile Tesseract | Evet | Evet | Taranmış sayfalar, belge fotoğrafları | Doğruluk tarama kalitesine bağlı; tablolar yapısını kaybeder |

## Kodsuz yöntemler: kopyalama ve Excel

**Kopyalama.** Tek bir küçük tablo için tabloyu görüntüleyicide seçip yapıştırın. Her satır tek bir hücreye düşüyorsa **Veri > Metni Sütunlara Dönüştür** komutunu kullanın. Bir ürün adında boşluk olduğu anda bu yöntem de bozulur.

**Excel'in PDF bağlayıcısı.** Windows'taki Microsoft 365 için Excel, PDF dosyalarını Power Query üzerinden okuyabilir:

1. Boş bir çalışma kitabı açın ve **Veri > Veri Al > Dosyadan > PDF'den** yolunu izleyin.
2. PDF'i seçip **Aç**'a tıklayın.
3. **Gezgin** penceresi Power Query'nin bulduklarını listeler: algılanan her tablo (Table001, Table002…) ve her sayfanın tamamı (Page001…). Önizlemek için bir öğeye tıklayın.
4. Tabloyu bir sayfaya almak için **Yükle**'yi, önce Power Query Düzenleyicisi'nde temizlemek için **Verileri Dönüştür**'ü seçin (tekrarlanan başlık satırlarını kaldırın, fiyat sütununun türünü sayıya çevirin).
5. Gelecek ay dosyayı değiştirip **Veri > Tümünü Yenile**'ye tıklayın; aynı adımlar yeniden çalışır.

Microsoft'un [PDF bağlayıcısı belgeleri](https://learn.microsoft.com/tr-tr/power-query/connectors/pdf) arka plandaki seçenekleri listeler: `Pdf.Tables`, büyük dosyalar için `StartPage` ve `EndPage` parametrelerini, sayfalar boyunca devam eden bir tabloyu birleştiren `MultiPageTables` seçeneğini de kabul eder. Bağlayıcı OCR yapmaz ve Mac için Excel'deki Power Query'de de kaynaklar arasında PDF yer almaz. Klasör bağlayıcısı aynı düzendeki PDF'leri birleştirir; düzenler farklılaştığında bir betiğin bakımı daha kolaydır.

## pdfplumber ile metin ve tablo çıkarma

[pdfplumber](https://github.com/jsvine/pdfplumber), pdfminer.six üzerine kurulu ve kendi tablo bulucusu olan bir Python kütüphanesidir. Güncel sürüm 0.11.10'dur (Haziran 2026); README dosyasına göre en iyi sonucu makinede üretilmiş PDF'lerde verir ve OCR yapmaz. Bir sanal ortama kurun:

```bash
python -m venv .venv
.venv\Scripts\activate        # macOS/Linux: source .venv/bin/activate
pip install pdfplumber pandas
```

Temel kullanım birkaç satıra sığar:

```python
import pdfplumber

with pdfplumber.open("pdfs/price-list-2026-08.pdf") as pdf:
    page = pdf.pages[0]
    print(page.extract_text())          # tüm metin, satır satır
    table = page.extract_table()        # sayfadaki en büyük tablo
    print(table[:2])
# [['SKU', 'Product', 'Unit', 'Price'], ['B-001', 'Cable set 1', 'box', '13.40']]
```

`extract_tables()`, sayfadaki her tabloyu hücre metinlerinden oluşan listeler olarak döndürür. pdfplumber varsayılan olarak çizilmiş çizgileri arar; kenarlıksız bir tabloda metin stratejisine geçin:

```python
settings = {"vertical_strategy": "text", "horizontal_strategy": "text"}
rows = page.extract_tables(table_settings=settings)
```

Stratejiyi tabloya göre seçin. Çizgili fiyat listemizde metin stratejisi "Cable set 1" değerini iki sütuna böldü, "Unit" ile "Price" sütunlarını da birleştirdi; çünkü çizgilerin zaten gösterdiği sınırları kelime aralıklarından tahmin etmeye çalıştı. Sayfanın yalnızca bir bölümü tabloysa önce `page.crop((x0, top, x1, bottom))` ile kırpın.

## Eksiksiz bir betik: PDF klasöründen tek CSV'ye

Aşağıdaki betik bir klasördeki her PDF'i okur, belge numarasını ilk sayfanın metninden alır, her sayfadan tablo satırlarını çeker, tekrarlanan başlıkları atlar, fiyatları sayıya çevirir ve tek bir CSV yazar. Metin katmanı olmayan sayfalar OCR için günlüğe kaydedilir; bozuk bir dosya da toplu işlemi durdurmaz.

```python
import csv
import logging
import re
from pathlib import Path

import pdfplumber

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")

IN_DIR = Path("pdfs")
OUT_CSV = Path("price_lists.csv")
HEADER = ["SKU", "Product", "Unit", "Price"]
DOC_NO = re.compile(r"price list (\S+)", re.IGNORECASE)

def to_number(text):
    """'1,007.50' -> 1007.5; boş ya da bozuk hücrelerde None döndürür."""
    if not text:
        return None
    try:
        return float(text.replace(",", "").strip())
    except ValueError:
        return None

def rows_from_pdf(path):
    with pdfplumber.open(path) as pdf:
        first_text = pdf.pages[0].extract_text() or ""
        match = DOC_NO.search(first_text)
        doc_no = match.group(1) if match else path.stem

        for page in pdf.pages:
            if not page.chars:  # metin katmanı yok: büyük olasılıkla taranmış
                logging.warning("%s p.%d has no text layer, needs OCR", path.name, page.page_number)
                continue
            for table in page.extract_tables():
                for row in table:
                    cells = [(c or "").strip() for c in row]
                    if cells == HEADER:  # her sayfada tekrarlanan başlık
                        continue
                    if len(cells) != len(HEADER):
                        logging.warning("%s p.%d skipped row %r", path.name, page.page_number, cells)
                        continue
                    sku, product, unit, price = cells
                    yield {
                        "file": path.name,
                        "doc_no": doc_no,
                        "page": page.page_number,
                        "sku": sku,
                        "product": product,
                        "unit": unit,
                        "price": to_number(price),
                    }

def main():
    fields = ["file", "doc_no", "page", "sku", "product", "unit", "price"]
    count = 0
    with OUT_CSV.open("w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for path in sorted(IN_DIR.glob("*.pdf")):
            try:
                for row in rows_from_pdf(path):
                    writer.writerow(row)
                    count += 1
            except Exception as exc:  # bozuk bir dosya toplu işlemi durdurmamalı
                logging.error("%s failed: %s", path.name, exc)
    logging.info("wrote %d rows to %s", count, OUT_CSV)

if __name__ == "__main__":
    main()
```

Test klasörümüzde (iki sayfaya yayılan 70 satırlık bir fiyat listesi, 8 satırlık bir fiyat listesi ve taranmış bir kopya) çıktı şöyleydi:

```bash
WARNING price-list-scan.pdf p.1 has no text layer, needs OCR
INFO wrote 78 rows to price_lists.csv
```

`utf-8-sig`, Excel'in "Café" gibi aksanlı adları doğru göstermesini sağlar; her satırdaki `file`, `doc_no` ve `page` alanları da her rakamın hangi dosyanın hangi sayfasından geldiğini gösterir. Satırları bundan sonra nerede saklayacağınızı [Kazınan Veri CSV, JSON ve SQLite'a Nasıl Kaydedilir?](/tr/blog/save-scraped-data-csv-json-sqlite) yazısında, temizlik adımını da [Kazınan Veri Pandas ile Nasıl Temizlenir?](/tr/blog/clean-scraped-data-with-pandas) yazısında anlatıyoruz.

## Camelot ve tabula-py: ne zaman kullanılır?

İki kütüphane daha var; ikisi de yalnızca tablolara odaklanır.

**Camelot**, Haziran 2026'da 2.0.0 sürümüne ulaştı. `read_pdf()` varsayılan olarak çizgili tablolar için `lattice` yöntemini kullanır; `stream` ve `network` kenarlıksız tabloları işler, `auto` ise her sayfa için seçimi kendisi yapar. Her tablonun, sorunlu sayfaları işaretlemeye yarayan bir doğruluk puanı içeren `parsing_report` alanı vardır. Ayrıntılar için [Camelot belgelerine](https://camelot-py.readthedocs.io/en/latest/) bakın.

**tabula-py**, tabula-java için yazılmış bir Python sarmalayıcısıdır; bu yüzden Java kurulu olmalıdır. `tabula.read_pdf()` doğrudan pandas DataFrame'lerinden oluşan bir liste döndürür.

```python
import camelot
import tabula

PDF = "pdfs/price-list-2026-09.pdf"

tables = camelot.read_pdf(PDF, pages="1-end", flavor="lattice")
for t in tables:
    print(t.page, t.shape, t.parsing_report["accuracy"])
tables[0].df.to_csv("camelot_page1.csv", index=False)

dfs = tabula.read_pdf(PDF, pages="all", lattice=True)
print(len(dfs), [df.shape for df in dfs])
```

İki sayfalık fiyat listemizde ikisi de sayfa başına bir tablo buldu. Camelot 100.0 doğruluk bildirdi ve başlığı ilk satır olarak tuttu; tabula ise başlığı sütun adı olarak kullandı. Çizgili tabloyu üç kütüphane de doğru okudu. Bu durumda seçimi işin geri kalanı belirler: serbest metin de gerekiyorsa pdfplumber, tablo başına puan istiyorsanız Camelot, Java kuruluysa en az kodla DataFrame için tabula-py.

## Taranmış PDF'ler: Tesseract ile OCR

Bir sayfada metin katmanı yoksa karakterleri görüntüden tanımanız gerekir. Tesseract yaygın kullanılan açık kaynaklı OCR motorudur; [pytesseract](https://github.com/h/pytesseract) ise onun Python sarmalayıcısıdır. Sarmalayıcı motoru içermez: önce Tesseract'ın kendisini kurun (kurulumdan sonra PATH'te değilse aşağıda gösterildiği gibi `tesseract_cmd` değerini ayarlayın), ardından:

```bash
pip install pytesseract pypdfium2
```

Betik her sayfayı 300 DPI çözünürlükte gri tonlamalı bir görüntüye dönüştürür, OCR uygular ve ortalama kelime güven puanını yazdırır; bu puan hangi sayfalara bir insanın bakması gerektiğini gösterir:

```python
import sys

import pypdfium2 as pdfium
import pytesseract

# Windows'ta PATH'te değilse pytesseract'a çalıştırılabilir dosyanın yolunu gösterin:
# pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

def ocr_pdf(path, lang="eng", dpi=300):
    pdf = pdfium.PdfDocument(path)
    pages = []
    for i, page in enumerate(pdf, start=1):
        image = page.render(scale=dpi / 72).to_pil().convert("L")  # gri tonlama işe yarar
        text = pytesseract.image_to_string(image, lang=lang, config="--psm 6")
        pages.append(text)
        # Kelime düzeyinde güven: -1 "kelime değil" demektir, aksi hâlde 0-100.
        data = pytesseract.image_to_data(image, lang=lang, output_type=pytesseract.Output.DICT)
        confs = [float(c) for c in data["conf"] if float(c) >= 0]
        if confs:
            print(f"page {i}: mean confidence {sum(confs) / len(confs):.1f}")
    return pages

if __name__ == "__main__":
    try:
        for text in ocr_pdf(sys.argv[1] if len(sys.argv) > 1 else "scans/price-list-scan.pdf"):
            print(text)
    except pytesseract.TesseractNotFoundError:
        sys.exit("Tesseract is not installed or not on PATH")
```

300 DPI değeri Tesseract'ın [kaliteyi artırma rehberinden](https://tesseract-ocr.github.io/tessdoc/ImproveQuality.html) geliyor. `--psm 6` sayfayı tek ve düzgün bir metin bloğu olarak ele alır. Aynı rehber, tablolar için özel bölütleme gerektiğini ve tarama kenarlarının karakter olarak okunabileceğini de belirtir.

OCR `0` ile `O`'yu, `1` ile `l`'yi, bir fiyattaki virgülle noktayı karıştırır; soluk ya da eğik taramalarda durum kötüleşir. Önemli rakamlarda kalemlerin toplamı tutup tutmadığını kontrol edin ve güven puanı düşük sayfaları bir kişiye inceletin. OCR tablo yapısını değil, metni döndürür: sütunları her satıra uygulanan bir düzenli ifadeyle yeniden kurun ya da Camelot'un isteğe bağlı `ocr` ek paketini deneyin.

## PDF'den veri çıkarma nerelerde kullanılır?

- **Tedarikçi fiyat listeleri.** Aylık PDF'ler, zaman içinde karşılaştırabileceğiniz bir fiyat geçmişine dönüşür; bu da [fiyat takibi](/tr/price-monitoring) işinin girdisidir.
- **Pazar ve sektör raporları.** Kamuya açık raporlardaki tablolar yeniden yazılmak yerine bir [pazar araştırması](/tr/market-research) modeline aktarılır.
- **Faturalar ve ekstreler.** Toplamlar, tarihler ve referans numaraları muhasebeye ya da mutabakata aktarılır; bu, [finans](/tr/finance) ekiplerinde sık görülen bir iştir.
- **Kamuya açık resmî belgeler ve istatistikler.** Birçok kurum tablolarını hâlâ yalnızca PDF olarak yayımlıyor; bir betik yılların birikimini tek bir veri setine çevirir. Bu, [veri madenciliği](/tr/blog/what-is-data-mining) öncesindeki tipik ilk adımdır.
- **ETL akışları.** PDF ayrıştırma, daha büyük bir akıştaki "extract" (çıkarma) adımıdır; dönüştürme ve yükleme adımlarının bunun etrafına nasıl yerleştiğini [ETL Nedir?](/tr/blog/what-is-etl) yazısında anlatıyoruz.

## Web sitelerinden çok sayıda PDF indirme

PDF'ler çoğu zaman bir tedarikçi portalında ya da düzenleyici bir kurumun yayın sayfasında durur. Yüzlercesini indirmek bir veri kazıma işidir: resmî bir indirme yolu ya da API varsa onu kullanın, robots.txt dosyasını ve kullanım koşullarını okuyun, istekleri aralıklı gönderin. Aşağıdaki indirici daha önce indirilmiş dosyaları atlar, 4xx hatalarında yeniden denemez, HTTP 429'da `Retry-After` başlığına uyar ve yanıtın gerçekten PDF olup olmadığını kontrol eder:

```python
import os
import time
from pathlib import Path
from urllib.parse import urlparse

import requests

PROXY = os.environ.get("PROXY_URL", "http://user:pass@pr.proxynet.io:8000")
URLS = os.environ.get("PDF_URLS", "https://example.com/reports/price-list.pdf").split()
OUT = Path("pdfs")
OUT.mkdir(exist_ok=True)

session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = "price-list-archiver/1.0 (contact: data@example.com)"

def download(url, retries=3):
    target = OUT / Path(urlparse(url).path).name
    if target.exists():  # önceki bir çalıştırmada zaten indirildi
        return target
    for attempt in range(1, retries + 1):
        try:
            r = session.get(url, timeout=30)
            if r.status_code == 429:
                time.sleep(int(r.headers.get("Retry-After", 30)))
                continue
            if 400 <= r.status_code < 500:  # 403, 404...: yeniden denemek işe yaramaz
                print(f"{url} returned {r.status_code}, skipped")
                return None
            r.raise_for_status()
            if not r.content.startswith(b"%PDF"):  # PDF değil, bir HTML hata sayfası
                print(f"{url} did not return a PDF, skipped")
                return None
            target.write_bytes(r.content)
            return target
        except requests.RequestException as exc:
            print(f"attempt {attempt} failed: {exc}")
            time.sleep(2 ** attempt)
    return None

for url in URLS:
    print(url, "->", download(url))
    time.sleep(2)  # sunucuyu yormayın
```

user:pass isteyen yerel bir test proxy'siyle yaptığımız denemede geçerli PDF kaydedildi, sahte bir `.pdf` ile 404 veren adres atlandı, ikinci çalıştırmada da hiçbir dosya yeniden indirilmedi. Kaynak ülkeye göre farklı belgeler sunuyorsa (hedef ülke seçilen bir [Residential Proxy](https://proxynet.io/tr/residential-proxy)) ya da uzun bir arşiv indirmesi IP başına sınırlara takılıyorsa (bir [Rotating Proxy](https://proxynet.io/tr/rotating-proxy)) proxy işe yarar. Yine de önce hızınızı düşürün; nedenini [HTTP 429 Too Many Requests](/tr/blog/http-429-too-many-requests) yazısında anlatıyoruz.

## Sık karşılaşılan sorunlar ve çözümleri

- **Birleştirilmiş hücreler `None` olarak geliyor.** pdfplumber birleştirilmiş hücrenin yalnızca ilk satırını doldurur; pandas'taki `ffill()` değeri aşağıya kopyalar (örnek aşağıda).
- **Tablo sonraki sayfada devam ediyor.** Sayfa sayfa çıkarın, tekrarlanan başlık satırlarını atın (yukarıdaki betiğin yaptığı gibi) ve birleştirin. Excel'de `MultiPageTables` seçeneği bunu sizin yerinize yapar.
- **Rakamlar metin olarak geliyor.** `"1,007.50"`, negatifler için `"(250.00)"`, Almanca bir dosyada `"1.007,50"`. Her biçimi kendi kuralıyla normalleştirin; ondalık ayracını tek bir değere bakarak tahmin etmeyin.
- **Aksanlı harfler bozuk görünüyor.** Genellikle sorun metinde değil, görüntüleyicidedir: bir Windows konsolu ya da UTF-8 dosyayı BOM olmadan açan Excel ([Python Unicode kodlama hataları](/tr/blog/python-unicode-encoding-errors) yazısına bakın). `extract_text()` çıktısında tuhaf simgeler varsa yazı tipinin Unicode eşlemesi yoktur ve güvenilir yol OCR'dır.
- **Kenarlıksız tablolarda sütunlar kayıyor.** Metin stratejisine geçin, tablo alanını kırpın ya da `"vertical_strategy": "explicit"` ve `"explicit_vertical_lines"` ile sütun konumlarını açıkça verin.
- **Hata yok ama satır da yok.** Sayfa taranmıştır, tablo bir görüntüdür ya da dosya parola korumalıdır (açma yetkiniz olan dosyalar için `pdfplumber.open(path, password="...")`).

Birleştirilmiş hücre çözümünün tamamı aşağıda; "North" değerinin iki satırı kapladığı bir tablo üzerinde test edildi:

```python
import pandas as pd
import pdfplumber

with pdfplumber.open("merged.pdf") as pdf:
    rows = pdf.pages[0].extract_table()

df = pd.DataFrame(rows[1:], columns=rows[0])
df["Region"] = df["Region"].ffill()  # birleştirilmiş hücre, ilk satırının altında None olarak gelir
df["Price"] = pd.to_numeric(df["Price"].str.replace(",", ""), errors="coerce")
print(df)
```

## Hangi yöntemi seçmelisiniz?

| İhtiyaç | Öneri |
|---|---|
| Tek dosyadan bir kez tek tablo | Kopyala yapıştır, ardından Metni Sütunlara Dönüştür |
| Ayda birkaç metin PDF'i, analiz Excel'de | Excel, Veri > Veri Al > Dosyadan > PDF'den |
| Bir klasörden metin ve tablolar, her ay tekrar | CSV yazan pdfplumber betiği |
| Tablo başına kalite puanıyla çizgili tablolar | Camelot, `lattice` yöntemi |
| En az kodla DataFrame, Java kurulu | tabula-py |
| Taranmış sayfalar ya da fotoğraflar | pypdfium2 ile 300 DPI görüntü + Tesseract, rakamların insan tarafından kontrolüyle |
| Bir web sitesinden yüzlerce PDF | Önce resmî indirme ya da API; yoksa aralıklı çalışan bir indirici, kaynak bölgeselse proxy ile |

## Sıkça sorulan sorular

### PDF'den ücretsiz veri çıkarılabilir mi?

Evet. pdfplumber, Camelot, tabula-py ve Tesseract açık kaynaklıdır; PDF bağlayıcısı da Windows'taki Microsoft 365 için Excel'in bir parçasıdır. Ücretli araçlar çoğunlukla şablon düzenleyicileri ve kötü taramalarda daha iyi OCR ekler.

### PDF'deki bir tabloyu Excel'e nasıl aktarırım?

Windows'taki Microsoft 365 için Excel'de Veri > Veri Al > Dosyadan > PDF'den yolunu izleyin, Gezgin'de tabloyu seçin ve Yükle'ye tıklayın. Python'da satırları pdfplumber ile çıkarın, ardından pandas `to_excel()` ile ya da Excel'in açabileceği bir CSV olarak yazın.

### PDF'den veri çıkarırken neden boş metin geliyor?

Sayfada büyük olasılıkla metin katmanı yoktur. pdfplumber'da `page.chars` değerine bakın ya da bir görüntüleyicide Ctrl+F ile arama yapın; hiçbir şey bulunmuyorsa OCR uygulayın.

### Tablolar için pdfplumber, PyPDF'ten daha mı iyi?

Tablolar için evet. pypdf, PDF bölme, birleştirme ve düz metin okuma işlerinde başarılıdır ama tablo bulucusu yoktur. pdfplumber her karakterin konumunu tutar ve hücreleri çizgilerden ya da hizalamadan yeniden kurar; tablo çıkarmanın ihtiyacı da tam olarak budur.

### Taranmış PDF'lerde OCR ne kadar doğru?

Taramaya bağlıdır. 300 DPI'da taranmış temiz basılı sayfalar genellikle iyi sonuç verir; eğik, soluk ya da düşük çözünürlüklü taramalar, el yazısı ve küçük yazı tipleri vermez. Güven puanlarına bakın ve toplamları doğrulayın.

### İndirdiğim PDF'lerden veri çıkarmak yasal mı?

Kullanma hakkınız olan dosyalardan (kendi faturalarınız, kamuya açık raporlar) veri çıkarmak normalde sorun değildir; ancak içerik yine de telif hakkıyla korunuyor olabilir, içindeki kişisel veriler de GDPR ya da KVKK gibi yasalara tabi olmaya devam eder. Toplu indirmeden önce kaynağın kullanım koşullarını okuyun; genel çerçeveyi [web scraping'in yasallığı](/tr/blog/web-scraping-legal) yazımızda anlatıyoruz. Bu bir hukuki tavsiye değildir.

## Özet

Her PDF işi tek bir kontrolle başlar: metin katmanı var mı? Varsa ara sıra gereken tablolar için Excel'in PDF bağlayıcısı, bütün bir klasörü tek CSV'ye çevirmek için bir pdfplumber betiği yeter; yalnızca tablo gereken işlerde Camelot ya da tabula-py devreye girer. Yoksa sayfaları 300 DPI görüntüye dönüştürün, Tesseract'ı çalıştırın ve rakamları doğrulayın. Her satırda kaynak dosyayı ve sayfayı tutun, toplu PDF indirmelerini de diğer veri kazıma işleri gibi ele alın. Bu indirmeler bölgesel ya da hız sınırı uygulayan kaynaklardan geliyorsa [proxy](/tr/proxy) paketlerimiz akışın ihtiyaç duyduğu adresleri sağlar.
