Merhaba. Web kazıma (web scraping) konusuna girdiğimizde, JavaScript'te yaygın olarak kullanılan yöntemler HTTP istemcileri, yani Fetch ve Axios gibi kütüphanelerdir. Ancak, HTTP istemcileri dinamik web sayfalarını kazımada pek verimli değiller. İşte bu noktada, Puppeteer adındaki headless browser (başsız tarayıcı) otomasyon aracı devreye giriyor.

Bu rehberde, Puppeteer ile web kazımaya bakacağız. İlk olarak Puppeteer API’sine genel bir bakış atacak ve kazıma sırasında nasıl kullanıldığını öğreneceğiz. Ardından, yaygın kullanım senaryoları için birçok Puppeteer web kazıyıcı oluşturacağız. Bu senaryolar arasında tarama, sonsuz kaydırma, butonlara tıklama ve formları doldurma gibi işlemler yer alacak.

Puppeteer Nedir ve Nasıl Çalışır?

Modern web tarayıcıları, otomasyon ve programlar arası iletişim için özel erişim araçları içerir. Özellikle Chrome Devtools Protocol (CDP olarak da bilinir), programların Chrome veya Firefox web tarayıcı örneklerini soket bağlantıları aracılığıyla kontrol etmesine olanak tanıyan yüksek seviyeli bir API protokolüdür.

Başka bir deyişle, Puppeteer web kazıma aracı, Chrome veya Firefox'ta otomasyon scriptleri oluşturmayı sağlar.

CDP program komutlarını web tarayıcısı komutlarına çevirir

 

Tahmin edebileceğiniz gibi, Puppeteer kullanarak web kazıma yapmak birkaç önemli avantaj sunar:

  • Puppeteer kazıyıcılar, dinamik veri çıkarmayı mümkün kılar. Başsız tarayıcı, JavaScript, görseller ve benzeri öğeleri tıpkı normal bir web tarayıcısı gibi işler.
  • Puppeteer ile yapılan web kazıma script'leri, tespit edilmesi ve engellenmesi daha zor olan otomasyonlardır. Bağlantı yapılandırması normal kullanıcılar gibi göründüğü için, bu script'leri otomatik olarak tanımlamak daha zordur.

Bununla birlikte, başsız tarayıcı otomasyon araçları kaynak tüketimi açısından oldukça yoğun çalışır. Bu nedenle, bu araçlar daha karmaşıktır ve sürekli bakım gerektirir.

Puppeteer Nasıl Kurulur?

Puppeteer NodeJS kütüphanesini kurmak için, NodeJS paket yöneticisi (npm) ile aşağıdaki terminal komutlarını kullanabilirsiniz:

$ mkdir myproject && cd myproject
$ npm init
$ npm install puppeteer

 

Not: Puppeteer ile yazacağımız web kazıma kodlarını, asenkron olarak, promises ve async/await programlama bağlamında çalıştıracağız. Eğer bu JavaScript kavramlarına aşina değilseniz, bu konuda hızlı bir giriş yapmak için MDN'nin sunduğu bu rehberi öneriyorum.

Puppeteer Temelleri

Şimdi, aşağıdaki işlemleri yapan temel bir Puppeteer koduyla başlayalım:

  • Chrome başsız tarayıcısını başlat (grafik kullanıcı arayüzü olmadan çalışan bir tarayıcı).
  • Yeni bir sayfa aç ve hedef bir web sitesine git.
  • Sayfanın yüklenmesini bekle ve HTML'yi al.
const puppeteer = require('puppeteer')

async function calistir(){
    // Öncelikle bir tarayıcı örneği başlatmamız gerekiyor
    const browser = await puppeteer.launch({
        // Headless seçeneği, görünür GUI'yi devre dışı bırakmamızı sağlar, bu sayede tarayıcı "arka planda" çalışır.
        // geliştirme aşamasında neler olup bittiğini görmek için bunu false olarak tutalım,
        // ancak bir sunucuda bunu true olarak ayarlamamız gerekiyor.
        headless: false,
        // Bu ayar, HTTPS olmayan web sitelerini daha kolay kazımamızı sağlar
        ignoreHTTPSErrors: true,
    })
    // ardından bir tarayıcı sekmesi açmamız gerekiyor
    let page = await browser.newPage();
    // ve belirli bir URL'ye gitmesini söylememiz gerekiyor
    await page.goto('http://httpbin.org/html', {
        waitUntil: 'domcontentloaded',
    });
    // web sitesinin HTML içeriğini yazdır
    console.log(await page.content());
    // her şeyi kapat
    await page.close();
    await browser.close();
}

calistir()

 

Yukarıdaki örnekte, görünen bir tarayıcı örneği oluşturuyoruz, yeni bir sekme açıyoruz, httpbin.org/html web sayfasına gidiyoruz ve sayfanın HTML içeriğini döndürüyoruz. Puppeteer ile web kazıma yaparken, çoğunlukla Page nesneleriyle çalışacağız. Bu nesne, bir tarayıcıyı temsil eder ve iki önemli yöntemini kullanırız:

  • 'goto()': Tarayıcı sekmesinde belirli bir URL'yi talep eder.
  • 'content()': Web sayfasının HTML kodunu döndürür.

Yukarıdaki kod parçacığı, verileri çıkarmak için kullanılan çoğu Puppeteer kazıyıcısının temel yapı taşıdır. Şimdi, bekleme mantığını ekleyelim.

İçeriği Beklemek

Önceki kodda, yaygın bir Puppeteer kazıma sorusuyla karşılaşıyoruz: Sayfanın yüklendiğini ve veriler için işlenmeye hazır olduğunu nasıl anlarız?

Önceki örnekte, waitUntil argümanını kullandık. Bu, tarayıcıya sayfanın HTML içeriğini okuduktan sonra tetiklenen domcontentloaded sinyalini beklemesini söyler. Ancak, bu yaklaşım tüm dinamik içerik kazıma senaryoları için uygun değildir çünkü bazı sayfa parçaları HTML okunduktan sonra bile yüklenmeye devam edebilir.

Web tarayıcılarının web sayfalarını nasıl yüklediğine dair bir gösterim.

 

JavaScript kullanan modern ve dinamik web siteleriyle uğraşırken, sadece sayfanın yüklenme sinyallerine güvenmek yerine, belirli içerikleri beklemek iyi bir uygulamadır.

await page.goto('http://httpbin.org/html');
await page.waitForSelector('h1', {timeout: 5_000})

 

Yukarıdaki temel örnekte, belge gövdesinde <h1> etiketinin görünmesini en fazla 5 saniye (5000 milisaniye) bekliyoruz.

Artık öğeleri etkili bir şekilde bekleyebildiğimize göre, Puppeteer rehberimizin bir sonraki bölümüne geçelim: İçerik seçimi.

İçerik Seçimi

Puppeteer, sayfanın tamamının verilerini döndürdüğünden, HTML'yi ayrıştırmak için hem XPath hem de CSS seçicilerini kullanabiliriz. Bu iki seçici, sayfanın belirli bölümlerini seçmemize ve görüntülenen verileri çıkarmamıza veya tıklama ve metin girişi gibi olayları göndermemize olanak tanır. Şimdi, Puppeteer ile HTML öğelerini nasıl ayrıştırabileceğimize bir göz atalım.

Page nesnesi, birkaç yöntemle birlikte gelir. Bu yöntemlerden biri olan ElementHandle, tıklama veya giriş hedefi olarak kullanabileceğimiz bir yapıdır:

const puppeteer = require('puppeteer');

async function calistir() {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    // .setContent kullanarak sayfanın HTML içeriğini belirli bir test değerine ayarlayabiliriz:
    await page.setContent(`
    <div class="links">
    <a href="https://twitter.com/@example">Twitter</a>
    <a href="https://www.linkedin.com/company/example/">LinkedIn</a>
    </div>
    `
);
    // .$ kullanarak ilk geçen değeri seçebilir ve iç metnini veya bir özniteliğini alabiliriz:
    await (await page.$('.links a')).evaluate( node => node.innerText);
    await (await page.$('.links a')).evaluate( node => node.getAttribute("href"));

    // .$$ kullanarak birden fazla değer seçebiliriz:
    let linkler = await page.$$('.links a');
    // ya da css seçicileri yerine xpath seçicilerini kullanabiliriz:
    // let linkler = await page.$x('//*[contains(@class, "links")]//a');
    for (const link of linkler){
        console.log(await link.evaluate( node => node.innerText));
        console.log(await link.evaluate( node => node.getAttribute("href")));
    }
    await browser.close();
}

calistir();

 

Yorumlar

Henüz yorum yapılmamış.

Yorum Yap

Email adresiniz görünmeyecektir. Zorunlu alanlar * ile belirtilmiştir.