Python Kullanarak Indeed İş İlanları Nasıl Kazınır?

Yorumlar: 0

İş avcıları, işverenler veya iş piyasasındaki eğilimleri izleyen herhangi bir kişi için Indeed'in mevcut işler listesini kazımak yararlı bilgiler sağlayabilir. Bu özel eğitimde, web kazıma için Playwright ve HTML içerik ayrıştırma için lxml'yi birleştirerek, başlığı, işe alan şirketin adı, konumu, iş tanımı, iş ilanı bağlantısı dahil olmak üzere işin ayrıntılarını toplayacağız ve son olarak bilgileri bir CSV dosyasına kaydederek bulguları sunacağız.

Önkoşullar

Kazıma işlemini başarıyla gerçekleştirmek için aşağıdaki Python kütüphanelerinin yüklenmesi gerekir.

Tarayıcı otomasyonu için Playwright:


pip install playwright

HTML ayrıştırmak için lxml:


pip install lxml

pandas verileri bir CSV dosyasına kaydetmek için:


pip install pandas

Playwright tarayıcılarını yükleyin:

Playwright'ı yükledikten sonra, gerekli tarayıcı ikili dosyalarını yüklemek için bu komutu çalıştırın:


playwright install

Adım 1: Playwright'ı web kazıma için ayarlama

Playwright, web tarayıcılarını otomatikleştirmenize ve bunlarla etkileşim kurmanıza olanak tanır. Playwright'ı bir Chromium tarayıcısı başlatacak, bir web sayfasını ziyaret edecek ve içeriğini çıkaracak şekilde ayarlayarak başlıyoruz. Burada proxy'leri oyun yazarı üzerinden de geçirebiliriz.

Neden proxy kullanmalı?

Web siteleri genellikle aynı IP adresinden tekrarlanan istekleri engellemek için hız sınırlayıcı veya kazıma önleyici önlemlere sahiptir. Proxy'ler şunları yapmanızı sağlar:

  • IP engellemesinden kaçının: tespit edilmekten kaçınmak için isteklerinizi farklı IP'ler üzerinden dağıtın.
  • Geolokasyon atlama: coğrafi konumlara göre kısıtlanmış olabilecek iş ilanlarına erişin.
  • Anonimlik: gerçek IP'nizi gizleyin ve kazıma işlemi sırasında anonim kalın.

import asyncio
from playwright.async_api import async_playwright

async def get_page_content(url):
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=False,
            proxy = {
                'server': '',
                'username': '',
                'password': ''
            }
        )  # Başlıklı tarayıcı
        page = await browser.new_page()
        await page.goto(url)
        
        # Sayfanın içeriğini ayıklayın
        content = await page.content()
        
        await browser.close()  # İşiniz bittiğinde tarayıcıyı kapatın
        return content

Bu kodda, async_playwright başlı bir tarayıcı başlatır, belirtilen URL'ye gider ve sayfanın içeriğini alır.

Lxml kullanarak HTML içeriğini ayrıştırma

Daha sonra, anlamlı verileri ayıklamak için sayfa içeriğini ayrıştıracağız. lxml bu amaç için kullanılır çünkü XPath kullanarak HTML içeriğini ayrıştırmak ve sorgulamak için sağlam destek sağlar.


from lxml import html

def parse_job_listings(content):
    # HTML içeriğini ayrıştırma
    parser = html.fromstring(content)
    
    # XPath kullanarak her bir iş ilanını ayıklayın
    job_posting = parser.xpath('//ul[@class="css-zu9cdh eu4oa1w0"]/li')
    
    jobs_data = []
    for element in job_posting[:-1]:  # Reklamsa veya alakasızsa son öğeyi atlayın
        title = ''.join(element.xpath('.//h2/a/span/@title'))
        if title:
            link = ''.join(element.xpath('.//h2/a/@href'))
            location = ''.join(element.xpath('.//div[@data-testid="text-location"]/text()'))
            description = ', '.join(element.xpath('.//div[@class="css-9446fg eu4oa1w0"]/ul//li/text()'))
            company_name = ''.join(element.xpath('.//span[@data-testid="company-name"]/text()'))

            # Çıkarılan verileri jobs_data listesine ekler
            jobs_data.append({
                'Title': title,
                'Link': f"https://www.indeed.com{link}",
                'Location': location,
                'Description': description,
                'Company': company_name
            })
    
    return jobs_data

Adım 2: İş ilanlarını kazıma

Şimdi hem tarayıcı otomasyonunu hem de ayrıştırma adımlarını ayarladığımıza göre, Indeed sayfasından iş ilanlarını kazımak için bunları birleştirelim.

Açıklama:

  • get_page_content(url): Playwright kullanarak sayfa içeriğini getirir.
  • parse_job_listings(content): İçeriği lxml kullanarak ayrıştırır ve iş verilerini çıkarır.
  • main(): Kazıma işlemini düzenler, verileri alır ve bir CSV dosyasına kaydeder.

import pandas as pd

async def scrape_indeed_jobs(url):
    # Adım 1: Playwright kullanarak sayfa içeriğini alın
    content = await get_page_content(url)
    
    # Adım 2: HTML'yi ayrıştırın ve iş ayrıntılarını çıkarın
    jobs_data = parse_job_listings(content)
    
    return jobs_data

# Kazınacak URL
url = 'https://www.indeed.com/q-usa-jobs.html'

# Verileri kazıma ve kaydetme
async def main():
    # Belirtilen URL'den iş verilerini kazıyın
    jobs = await scrape_indeed_jobs(url)
    
    # Adım 3: Pandas kullanarak verileri CSV'ye kaydedin
    df = pd.DataFrame(jobs)
    df.to_csv('indeed_jobs.csv', index=False)
    
    print("Data saved to indeed_jobs.csv")

# Ana işlevi çalıştırın
asyncio.run(main())

Adım 3: Sayfalandırma desteği ekleme

Indeed iş ilanlarını sayfalandırır ve kazıyıcıyı birden fazla sayfayı işleyecek şekilde kolayca genişletebilirsiniz. Sayfa URL'si, her yeni sayfa için 10'ar artan bir sorgu parametresi başlangıcı kullanılarak ayarlanır.

Kazıyıcınızın birden fazla sayfadan veri toplama işlevini geliştirmek için scrape_multiple_pages adlı bir işlev uygulayabilirsiniz. Bu işlev, başlangıç parametresini kademeli olarak ayarlayarak temel URL'yi değiştirecek ve sonraki sayfalara erişim sağlayacaktır. Her sayfada sistematik olarak ilerleyerek, boş pozisyonlar gibi toplanan verilerin kapsamını ve miktarını genişletebilir ve daha kapsamlı bir veri seti elde edebilirsiniz.


async def scrape_multiple_pages(base_url, pages=3):
    all_jobs = []
    
    for page_num in range(pages):
        # Sayfalandırma için URL'yi güncelleme
        url = f"{base_url}&start={page_num * 10}"
        print(f"Scraping page: {url}")
        
        # Her sayfadan iş verilerini kazıyın
        jobs = await scrape_indeed_jobs(url)
        all_jobs.extend(jobs)
    
    # Tüm işleri CSV'ye kaydet
    df = pd.DataFrame(all_jobs)
    df.to_csv('indeed_jobs_all_pages.csv', index=False)
    print("Data saved to indeed_jobs_all_pages.csv")

# İş ilanlarının birden fazla sayfasını kazıyın
asyncio.run(scrape_multiple_pages('https://www.indeed.com/jobs?q=usa', pages=3))

Adım 4: İş arama sorgularını özelleştirme

Kazıma çalışmalarınızda belirli iş unvanlarını veya anahtar kelimeleri hedeflemek için Indeed tarafından kullanılan URL'deki sorgu arama parametresini yapılandırmanız gerekir. Bu özelleştirme, kazıyıcının belirli işlere veya sektörlere özgü verileri toplamasına olanak tanır. Örneğin, http://www.indeed.com adresinde Python geliştirici pozisyonları arıyorsanız, sorgu parametresini "Python+geliştirici" veya ilgili anahtar kelimeleri içerecek şekilde ayarlarsınız.


query = "python+developer"
base_url = f"https://www.indeed.com/jobs?q={query}"
asyncio.run(scrape_multiple_pages(base_url, pages=3))

Bu parametreyi veri toplama ihtiyaçlarınıza göre değiştirerek, kazıma işleminizi belirli işlere odaklayabilir, veri toplama sürecinizin esnekliğini ve verimliliğini artırabilirsiniz. Bu yaklaşım özellikle iş piyasasının dinamik taleplerine uyum sağlamak için kullanışlıdır.

Kodu tamamlayın


import asyncio
from playwright.async_api import async_playwright
from lxml import html
import pandas as pd

# Adım 1: Playwright kullanarak sayfa içeriğini getirin
async def get_page_content(url):
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=False
            proxy = {
                'server': '',
                'username': '',
                'password': ''
            }
        )  # Tarayıcıyı başlı modda çalıştırma
        page = await browser.new_page()
        await page.goto(url, wait_until='networkidle')
        
        # Sayfa içeriğini çıkarma
        content = await page.content()
        await browser.close()  # Kullandıktan sonra tarayıcıyı kapatın
        return content

# Adım 2: lxml kullanarak HTML içeriğini ayrıştırın
def parse_job_listings(content):
    # HTML'yi lxml kullanarak ayrıştırma
    parser = html.fromstring(content)
    
    # XPath kullanarak tek tek iş ilanlarını seçme
    job_posting = parser.xpath('//ul[@class="css-zu9cdh eu4oa1w0"]/li')
    
    #  İş verilerini ayıklayın
    jobs_data = []
    for element in job_posting[:-1]:
        title = ''.join(element.xpath('.//h2/a/span/@title'))
        if title:
            link = ''.join(element.xpath('.//h2/a/@href'))
            location = ''.join(element.xpath('.//div[@data-testid="text-location"]/text()'))
            description = ', '.join(element.xpath('.//div[@class="css-9446fg eu4oa1w0"]/ul//li/text()'))
            company_name = ''.join(element.xpath('.//span[@data-testid="company-name"]/text()'))

            # Çıkarılan verileri jobs_data listesine ekler
            jobs_data.append({
                'Title': title,
                'Link': f"https://www.indeed.com{link}",
                'Location': location,
                'Description': description,
                'Company': company_name
            })
    
    return jobs_data

# Adım 3: Indeed iş ilanlarını tek bir sayfa için kazıyın
async def scrape_indeed_jobs(url):
    # Playwright kullanarak sayfa içeriğini alma
    content = await get_page_content(url)
    
    # HTML'yi ayrıştırma ve iş verilerini çıkarma
    jobs_data = parse_job_listings(content)
    
    return jobs_data

# Adım 4: Sayfalandırma işlemini gerçekleştirin ve birden fazla sayfayı kazıyın
async def scrape_multiple_pages(base_url, query, pages=3):
    all_jobs = []
    
    for page_num in range(pages):
        # Sayfalandırmayı işlemek için URL'yi güncelleyin ve arama sorgusunu ekleyin
        url = f"{base_url}?q={query}&start={page_num * 10}"
        print(f"Scraping page: {url}")
        
        # Geçerli sayfa için işleri kazıyın
        jobs = await scrape_indeed_jobs(url)
        all_jobs.extend(jobs)
    
    # Tüm işleri bir CSV dosyasına kaydetme
    df = pd.DataFrame(all_jobs)
    df.to_csv(f'indeed_jobs_{query}.csv', index=False)
    print(f"Data saved to indeed_jobs_{query}.csv")

# Kazıyıcıyı dinamik sorgu girdisi ile çalıştırma işlevi
async def run_scraper():
    # Adım 5: Kullanıcıdan giriş sorgusunu ve kazınacak sayfa sayısını isteyin
    query = input("Enter the job title or keywords to search (e.g., python+developer): ")
    pages = int(input("Enter the number of pages to scrape: "))
    
    # Sorguya dayalı olarak birden çok sayfadaki işleri kazıyın
    base_url = 'https://www.indeed.com/jobs'
    await scrape_multiple_pages(base_url, query, pages)

# Sıyırıcıyı çalıştırın
asyncio.run(run_scraper())

Sorunsuz bir kazıma süreci sağlamak ve engelleme ve CAPTCHA görünme riskini azaltmak için doğru proxy sunucusunu seçmek çok önemlidir. Kazıma için en uygun seçenek, yüksek hız ve bağlantı kararlılığının yanı sıra yüksek bir güven faktörü sağlayan ve platformlar tarafından nadiren engellenmelerini sağlayan ISP proxy'leridir. Bu tür bir proxy statiktir, bu nedenle büyük ölçekli kazıma için bir ISP proxy havuzu oluşturmak ve düzenli değişimleri için IP rotasyonunu yapılandırmak gerekir. Alternatif bir seçenek, dinamik olan ve diğer proxy sunucu türlerine kıyasla en geniş coğrafi kapsama alanına sahip olan konut proxy'leri olabilir.

Yorumlar:

0 yorumlar