Dla osób poszukujących pracy, pracodawców lub innych osób monitorujących trendy na rynku pracy, skrobanie listy dostępnych ofert pracy Indeed może dostarczyć pomocnych informacji. W tym konkretnym samouczku połączymy Playwright do skrobania stron internetowych i lxml do analizowania treści HTML w celu zebrania szczegółów oferty pracy, w tym jej tytułu, nazwy firmy rekrutującej, lokalizacji, opisu stanowiska, linku do oferty pracy, a na koniec przedstawimy wyniki, zapisując informacje w pliku CSV.
Aby pomyślnie wykonać scraping, należy zainstalować następujące biblioteki Python.
Playwright do automatyzacji przeglądarki:
pip install playwright
lxml do parsowania HTML:
pip install lxml
pandas do zapisywania danych do pliku CSV:
pip install pandas
Zainstaluj przeglądarki Playwright:
Po zainstalowaniu Playwright, uruchom to polecenie, aby zainstalować niezbędne pliki binarne przeglądarki:
playwright install
Playwright umożliwia automatyzację i interakcję z przeglądarkami internetowymi. Zaczynamy od skonfigurowania Playwright, aby uruchomić przeglądarkę Chromium, odwiedzić stronę internetową i wyodrębnić jej zawartość. Tutaj możemy również przekazywać proxy przez Playwright.
Dlaczego warto korzystać z serwerów proxy?
Strony internetowe często stosują środki ograniczające szybkość lub zapobiegające skrobaniu, aby zablokować powtarzające się żądania z tego samego adresu IP. Serwery proxy pozwalają na:
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': ''
}
) # Przeglądarka z nagłówkiem
page = await browser.new_page()
await page.goto(url)
# Wyodrębnij zawartość strony
content = await page.content()
await browser.close() # Po zakończeniu zamknij przeglądarkę
return content
W tym kodzie async_playwright uruchamia przeglądarkę z nagłówkiem, nawiguje do określonego adresu URL i pobiera zawartość strony.
Następnie przeanalizujemy zawartość strony, aby wyodrębnić znaczące dane. lxml jest używany do tego celu, ponieważ zapewnia solidne wsparcie dla analizowania i odpytywania treści HTML za pomocą XPath.
from lxml import html
def parse_job_listings(content):
# Analizowanie zawartości HTML
parser = html.fromstring(content)
# Wyodrębnij każdą ofertę pracy za pomocą XPath
job_posting = parser.xpath('//ul[@class="css-zu9cdh eu4oa1w0"]/li')
jobs_data = []
for element in job_posting[:-1]: # Pomiń ostatni element, jeśli jest to reklama lub nie ma znaczenia.
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()'))
# Dodanie wyodrębnionych danych do listy jobs_data
jobs_data.append({
'Title': title,
'Link': f"https://www.indeed.com{link}",
'Location': location,
'Description': description,
'Company': company_name
})
return jobs_data
Teraz, gdy mamy już skonfigurowane zarówno kroki automatyzacji przeglądarki, jak i parsowania, połączmy je, aby zeskrobać oferty pracy ze strony Indeed.
Wyjaśnienie:
import pandas as pd
async def scrape_indeed_jobs(url):
# Krok 1: Pobierz zawartość strony za pomocą Playwright
content = await get_page_content(url)
# Krok 2: Analiza kodu HTML i wyodrębnienie szczegółów zadania
jobs_data = parse_job_listings(content)
return jobs_data
# Adres URL do zeskrobania
url = 'https://www.indeed.com/q-usa-jobs.html'
# Skrobanie i zapisywanie danych
async def main():
# Skrobanie danych zadania z określonego adresu URL
jobs = await scrape_indeed_jobs(url)
# Krok 3: Zapisywanie danych do CSV przy użyciu pandas
df = pd.DataFrame(jobs)
df.to_csv('indeed_jobs.csv', index=False)
print("Data saved to indeed_jobs.csv")
# Uruchom główną funkcję
asyncio.run(main())
Indeed paginuje swoje oferty pracy i można łatwo rozszerzyć scraper, aby obsługiwał wiele stron. Adres URL strony jest dostosowywany za pomocą parametru zapytania start, który zwiększa się o 10 dla każdej nowej strony.
Aby rozszerzyć funkcjonalność scrapera do zbierania danych z wielu stron, można zaimplementować funkcję o nazwie scrape_multiple_pages. Funkcja ta zmodyfikuje podstawowy adres URL poprzez stopniowe dostosowywanie parametru start, umożliwiając dostęp do kolejnych stron. Systematycznie przechodząc przez każdą stronę, można rozszerzyć zakres i ilość gromadzonych danych, takich jak oferty pracy, zapewniając bardziej kompleksowy zestaw danych.
async def scrape_multiple_pages(base_url, pages=3):
all_jobs = []
for page_num in range(pages):
# Aktualizacja adresu URL dla paginacji
url = f"{base_url}&start={page_num * 10}"
print(f"Scraping page: {url}")
# Skrobanie danych zadań z każdej strony
jobs = await scrape_indeed_jobs(url)
all_jobs.extend(jobs)
# Zapisz wszystkie zadania do pliku CSV
df = pd.DataFrame(all_jobs)
df.to_csv('indeed_jobs_all_pages.csv', index=False)
print("Data saved to indeed_jobs_all_pages.csv")
# Skrobanie wielu stron z ofertami pracy
asyncio.run(scrape_multiple_pages('https://www.indeed.com/jobs?q=usa', pages=3))
Aby ukierunkować swoje działania na określone stanowiska lub słowa kluczowe, należy skonfigurować parametr wyszukiwania zapytań w adresie URL używanym przez Indeed. To dostosowanie pozwala scraperowi zbierać dane specyficzne dla określonych stanowisk lub sektorów. Na przykład, jeśli szukasz stanowisk programisty Python na http://www.indeed.com, dostosuj parametr zapytania, aby zawierał "Python+developer" lub odpowiednie słowa kluczowe.
query = "python+developer"
base_url = f"https://www.indeed.com/jobs?q={query}"
asyncio.run(scrape_multiple_pages(base_url, pages=3))
Modyfikując ten parametr zgodnie z potrzebami gromadzenia danych, można skupić się na skrobaniu konkretnych ofert pracy, zwiększając elastyczność i wydajność procesu gromadzenia danych. Takie podejście jest szczególnie przydatne w przypadku dostosowywania się do dynamicznych wymagań rynku pracy.
import asyncio
from playwright.async_api import async_playwright
from lxml import html
import pandas as pd
# Krok 1: Pobieranie zawartości strony za pomocą Playwright
async def get_page_content(url):
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=False
proxy = {
'server': '',
'username': '',
'password': ''
}
) # Uruchom przeglądarkę w trybie nagłówkowym
page = await browser.new_page()
await page.goto(url, wait_until='networkidle')
# Wyodrębnianie zawartości strony
content = await page.content()
await browser.close() # Zamknij przeglądarkę po użyciu
return content
# Krok 2: Parsowanie zawartości HTML przy użyciu lxml
def parse_job_listings(content):
# Parsowanie HTML przy użyciu lxml
parser = html.fromstring(content)
# Wybieranie poszczególnych ofert pracy za pomocą XPath
job_posting = parser.xpath('//ul[@class="css-zu9cdh eu4oa1w0"]/li')
# Wyodrębnianie danych zadania
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()'))
# Dodanie wyodrębnionych danych do listy jobs_data
jobs_data.append({
'Title': title,
'Link': f"https://www.indeed.com{link}",
'Location': location,
'Description': description,
'Company': company_name
})
return jobs_data
# Krok 3: Skrobanie ofert pracy Indeed dla pojedynczej strony
async def scrape_indeed_jobs(url):
# Pobierz zawartość strony za pomocą Playwright
content = await get_page_content(url)
# Analizowanie HTML i wyodrębnianie danych zadań
jobs_data = parse_job_listings(content)
return jobs_data
# Krok 4: Obsługa paginacji i skrobanie wielu stron
async def scrape_multiple_pages(base_url, query, pages=3):
all_jobs = []
for page_num in range(pages):
# Zaktualizuj adres URL, aby obsługiwał paginację i dodaj zapytanie wyszukiwania
url = f"{base_url}?q={query}&start={page_num * 10}"
print(f"Scraping page: {url}")
# Zadania scrape dla bieżącej strony
jobs = await scrape_indeed_jobs(url)
all_jobs.extend(jobs)
# Zapisywanie wszystkich zadań w pliku CSV
df = pd.DataFrame(all_jobs)
df.to_csv(f'indeed_jobs_{query}.csv', index=False)
print(f"Data saved to indeed_jobs_{query}.csv")
# Funkcja uruchamiająca scrapera z dynamicznym zapytaniem wejściowym
async def run_scraper():
# Krok 5: Poproś użytkownika o podanie zapytania wejściowego i liczby stron do zeskrobania
query = input("Enter the job title or keywords to search (e.g., python+developer): ")
pages = int(input("Enter the number of pages to scrape: "))
# Skrobanie zadań na wielu stronach na podstawie zapytania
base_url = 'https://www.indeed.com/jobs'
await scrape_multiple_pages(base_url, query, pages)
# Uruchom skrobak
asyncio.run(run_scraper())
Aby zapewnić płynny proces scrapingu i zmniejszyć ryzyko blokad i pojawienia się CAPTCHA, kluczowy jest wybór odpowiedniego serwera proxy. Najbardziej optymalną opcją do scrapingu są serwery proxy ISP, które zapewniają wysoką prędkość i stabilność połączenia, a także wysoki współczynnik zaufania, dzięki czemu rzadko są blokowane przez platformy. Ten typ serwera proxy jest statyczny, więc w przypadku skrobania na dużą skalę konieczne jest utworzenie puli serwerów proxy ISP i skonfigurowanie rotacji adresów IP w celu ich regularnej zmiany. Alternatywną opcją są rezydencjalne serwery proxy, które są dynamiczne i mają najszerszy zasięg geograficzny w porównaniu do innych typów serwerów proxy.
Komentarze: 0