Pour les chasseurs d'emploi, les employeurs ou toute personne surveillant les tendances du marché de l'emploi, l'analyse de la liste des emplois disponibles d'Indeed peut fournir des informations utiles. Dans ce tutoriel, nous allons combiner Playwright pour le web scraping et lxml pour l'analyse du contenu HTML afin de collecter les détails de l'emploi, y compris son titre, le nom de l'entreprise qui recrute, le lieu, la description de l'emploi, le lien de l'offre d'emploi, et enfin présenter les résultats en enregistrant les informations dans un fichier CSV.
Pour réussir le scraping, les bibliothèques Python suivantes doivent être installées.
Playwright pour l'automatisation du navigateur :
pip install playwright
lxml pour l'analyse du langage HTML :
pip install lxml
pandas pour enregistrer les données dans un fichier CSV :
pip install pandas
Installer les navigateurs Playwright:
Après avoir installé Playwright, exécutez cette commande pour installer les binaires nécessaires au navigateur :
playwright install
Playwright vous permet d'automatiser et d'interagir avec les navigateurs web. Nous commençons par configurer Playwright pour lancer un navigateur Chromium, visiter une page web et en extraire le contenu. Ici, nous pouvons également passer des proxys à travers le playwright.
Pourquoi utiliser des proxys?
Les sites web ont souvent mis en place des mesures de limitation du débit ou d'anti-scraping afin de bloquer les requêtes répétées provenant de la même adresse IP. Les proxys vous permettent de :
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': ''
}
) # Navigateur à tête chercheuse
page = await browser.new_page()
await page.goto(url)
# Extraire le contenu de la page
content = await page.content()
await browser.close() # Fermez le navigateur une fois que vous avez terminé
return content
Dans ce code, async_playwright lance un navigateur à en-tête, navigue jusqu'à l'URL spécifiée et récupère le contenu de la page.
Ensuite, nous analyserons le contenu de la page pour en extraire des données significatives. lxml est utilisé à cette fin parce qu'il fournit un support robuste pour l'analyse et l'interrogation du contenu HTML à l'aide de XPath.
from lxml import html
def parse_job_listings(content):
# Analyse du contenu HTML
parser = html.fromstring(content)
# Extraire chaque offre d'emploi à l'aide de XPath
job_posting = parser.xpath('//ul[@class="css-zu9cdh eu4oa1w0"]/li')
jobs_data = []
for element in job_posting[:-1]: # Sauter le dernier élément s'il s'agit d'une publicité ou d'un élément non pertinent
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()'))
# Ajouter les données extraites à la liste jobs_data
jobs_data.append({
'Title': title,
'Link': f"https://www.indeed.com{link}",
'Location': location,
'Description': description,
'Company': company_name
})
return jobs_data
Maintenant que nous avons mis en place les étapes d'automatisation du navigateur et d'analyse, combinons-les pour récupérer les offres d'emploi de la page Indeed.
Explication :
import pandas as pd
async def scrape_indeed_jobs(url):
# Étape 1 : Obtenir le contenu de la page à l'aide de Playwright
content = await get_page_content(url)
# Étape 2 : Analyse du code HTML et extraction des détails de l'emploi
jobs_data = parse_job_listings(content)
return jobs_data
# URL à récupérer
url = 'https://www.indeed.com/q-usa-jobs.html'
# Récupérer et enregistrer des données
async def main():
# Récupérer les données d'un travail à partir de l'URL spécifiée
jobs = await scrape_indeed_jobs(url)
# Étape 3 : Enregistrer les données au format CSV à l'aide de pandas
df = pd.DataFrame(jobs)
df.to_csv('indeed_jobs.csv', index=False)
print("Data saved to indeed_jobs.csv")
# Exécuter la fonction principale
asyncio.run(main())
Indeed pagine ses offres d'emploi et vous pouvez facilement étendre le scraper pour qu'il prenne en charge plusieurs pages. L'URL de la page est ajustée à l'aide d'un paramètre de requête start, qui s'incrémente de 10 pour chaque nouvelle page.
Pour améliorer la fonctionnalité de votre scraper afin de collecter des données à partir de plusieurs pages, vous pouvez mettre en œuvre une fonction appelée scrape_multiple_pages. Cette fonction modifiera l'URL de base en ajustant progressivement le paramètre "start", ce qui permettra d'accéder aux pages suivantes. En progressant systématiquement sur chaque page, vous pouvez élargir la portée et la quantité des données collectées, telles que les offres d'emploi, ce qui permet d'obtenir un ensemble de données plus complet.
async def scrape_multiple_pages(base_url, pages=3):
all_jobs = []
for page_num in range(pages):
# Mise à jour de l'URL pour la pagination
url = f"{base_url}&start={page_num * 10}"
print(f"Scraping page: {url}")
# Récupérer les données relatives à l'emploi sur chaque page
jobs = await scrape_indeed_jobs(url)
all_jobs.extend(jobs)
# Enregistrer tous les emplois au format 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")
# Récupérer plusieurs pages d'offres d'emploi
asyncio.run(scrape_multiple_pages('https://www.indeed.com/jobs?q=usa', pages=3))
Pour cibler des titres d'emploi ou des mots-clés spécifiques dans vos efforts de scrapping, vous devrez configurer le paramètre de recherche de la requête dans l'URL utilisée par Indeed. Cette personnalisation permet au scraper de collecter des données spécifiques à des emplois ou des secteurs particuliers. Par exemple, si vous recherchez des postes de développeur Python sur http://www.indeed.com, vous devez ajuster le paramètre de recherche pour inclure "Python+développeur" ou des mots-clés pertinents.
query = "python+developer"
base_url = f"https://www.indeed.com/jobs?q={query}"
asyncio.run(scrape_multiple_pages(base_url, pages=3))
En modifiant ce paramètre en fonction de vos besoins en matière de collecte de données, vous pouvez concentrer votre scraping sur des emplois spécifiques, ce qui améliore la flexibilité et l'efficacité de votre processus de collecte de données. Cette approche est particulièrement utile pour s'adapter aux demandes dynamiques du marché de l'emploi.
import asyncio
from playwright.async_api import async_playwright
from lxml import html
import pandas as pd
# Étape 1 : Récupérer le contenu de la page à l'aide de Playwright
async def get_page_content(url):
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=False
proxy = {
'server': '',
'username': '',
'password': ''
}
) # Exécuter le navigateur en mode tête
page = await browser.new_page()
await page.goto(url, wait_until='networkidle')
# Extraire le contenu de la page
content = await page.content()
await browser.close() # Fermer le navigateur après utilisation
return content
# Étape 2 : Analyse du contenu HTML à l'aide de lxml
def parse_job_listings(content):
# Analyse du code HTML à l'aide de lxml
parser = html.fromstring(content)
# Sélectionner des offres d'emploi individuelles à l'aide de XPath
job_posting = parser.xpath('//ul[@class="css-zu9cdh eu4oa1w0"]/li')
# Extraire les données relatives à l'emploi
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()'))
# Ajouter les données extraites à la liste jobs_data
jobs_data.append({
'Title': title,
'Link': f"https://www.indeed.com{link}",
'Location': location,
'Description': description,
'Company': company_name
})
return jobs_data
# Étape 3 : Récupérer les offres d'emploi d'Indeed pour une seule page
async def scrape_indeed_jobs(url):
# Obtenir le contenu de la page à l'aide de Playwright
content = await get_page_content(url)
# Analyse du code HTML et extraction des données relatives aux emplois
jobs_data = parse_job_listings(content)
return jobs_data
# Étape 4 : Gérer la pagination et récupérer plusieurs pages
async def scrape_multiple_pages(base_url, query, pages=3):
all_jobs = []
for page_num in range(pages):
# Mettre à jour l'URL pour gérer la pagination et ajouter la requête de recherche
url = f"{base_url}?q={query}&start={page_num * 10}"
print(f"Scraping page: {url}")
# Récupérer les travaux pour la page en cours
jobs = await scrape_indeed_jobs(url)
all_jobs.extend(jobs)
# Enregistrer tous les travaux dans un fichier 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")
# Fonction permettant d'exécuter le scraper avec une entrée de requête dynamique
async def run_scraper():
# Étape 5 : Demander à l'utilisateur de saisir sa requête et le nombre de pages à récupérer
query = input("Enter the job title or keywords to search (e.g., python+developer): ")
pages = int(input("Enter the number of pages to scrape: "))
# Scraper les travaux sur plusieurs pages en fonction de la requête
base_url = 'https://www.indeed.com/jobs'
await scrape_multiple_pages(base_url, query, pages)
# Faire fonctionner le grattoir
asyncio.run(run_scraper())
Pour garantir un processus de scraping fluide et réduire le risque de blocages et d'apparitions de CAPTCHA, il est essentiel de choisir le bon serveur proxy. L'option la plus optimale pour le scraping sont les proxys des FAI, qui offrent une vitesse élevée et une stabilité de connexion, ainsi qu'un facteur de confiance élevé, ce qui fait qu'ils sont rarement bloqués par les plateformes. Ce type de proxy est statique, donc pour le scraping à grande échelle, il est nécessaire de créer un pool de proxys ISP et de configurer la rotation des IP pour qu'elles changent régulièrement. Une autre option serait les proxys résidentiels, qui sont dynamiques et ont la couverture géographique la plus large par rapport aux autres types de serveurs proxy.
Мы получили вашу заявку!
Ответ будет отправлен на почту в ближайшее время.
С уважением proxy-seller.com!
Commentaires: 0