Je suis tombé sur un script sur Internet qui permet d'analyser les fiches produits d'Amazon. Et j'avais juste besoin d'une solution à un problème comme celui-là.
Je me suis creusé la tête en cherchant un moyen d'analyser les fiches produits d'Amazon. Le problème est qu'Amazon utilise différentes options de conception pour différentes sorties, en particulier – si vous devez analyser les cartes avec la requête de recherche « sacs » – les cartes seront disposées verticalement, comme j'en ai besoin, mais si vous prenez, par exemple , "t-shirts" – alors les cartes seront disposées horizontalement, et de cette manière le script tombe dans une erreur, il parvient à ouvrir la page, mais ne veut pas faire défiler.
De plus, après avoir lu divers articles dans lesquels les utilisateurs se demandent comment contourner le captcha sur Amazon, j'ai mis à jour le script et il peut désormais contourner le captcha s'il se produit (il fonctionne avec 2captcha). Le script vérifie la présence d'un captcha sur la page après chaque chargement d'une nouvelle page, et si le captcha se produit, il envoie une requête au serveur 2capcha, et après avoir reçu la solution, le remplace et continue de fonctionner.
Cependant, comment contourner le captcha n'est pas le problème le plus difficile, car c'est une tâche triviale de nos jours. La question la plus urgente est de savoir comment faire fonctionner le script non seulement avec la disposition verticale des fiches produits, mais aussi avec la disposition horizontale.
Ci-dessous, je vais décrire en détail ce que le script comprend, démontrer son travail et si vous pouvez aider à résoudre le problème, si vous savez quoi ajouter (modifier) dans le script pour qu'il fonctionne sur une configuration horizontale des cartes, Je vous en serai reconnaissant.
Et pour l'instant, le script peut aider quelqu'un au moins dans ses fonctionnalités limitées.
Alors, démontons le script morceau par morceau !
Tout d'abord, le script importe les modules nécessaires à la réalisation de la tâche
à partir du pilote Web d'importation de sélénium
à partir de selenium.webdriver.common.keys importer des clés
à partir de selenium.webdriver.common.action_chains, importez ActionChains
depuis selenium.webdriver.support.ui importer WebDriverWait
à partir de selenium.webdriver.support, importez les conditions_attendues en tant que EC
importer csv
importer un système d'exploitation
à partir du temps importer le sommeil
demandes d'importation
Démontons-le en plusieurs parties :
à partir du pilote Web d'importation de sélénium
Cela importe la classe webdriver, qui vous permet de contrôler le navigateur (dans mon cas Firefox) via le script
depuis selenium.webdriver.common.by import By
Cela importe la classe By, avec laquelle le script recherchera les éléments à analyser par XPath (il peut rechercher d'autres attributs, mais dans ce cas, XPath sera utilisé)
à partir de selenium.webdriver.common.keys importer des clés
Cela importe la classe Keys, qui sera utilisée pour simuler les frappes au clavier, dans le cas de ce script, il fera défiler la page vers le bas Keys.PAGE_DOWN
depuis selenium.webdriver.common.action_chains importez ActionChains
Cela importe la classe ActionChains pour créer des actions séquentielles complexes, dans notre cas – en cliquant sur le bouton PAGE_DOWN et en attendant que tous les éléments de la page se chargent (puisque sur Amazon, les cartes sont chargées au fur et à mesure qu'elles défilent)
depuis selenium.webdriver.support.ui importez WebDriverWait
Cela importe la classe WebDriverWait, qui attend que l'information que nous recherchons soit chargée, par exemple une description de produit, que nous rechercherons par Xpath
à partir de selenium.webdriver.support, importez les conditions_attendues en tant que EC
Cela importe la classe Expected_conditions (en abrégé EC) qui fonctionne en conjonction avec la classe précédente et indique à WebDriverWait quelle condition spécifique il doit attendre. Cela augmente la fiabilité du script afin qu'il ne commence pas à interagir avec le contenu encore déchargé.
importer csv
Cela importe le module csv pour travailler avec les fichiers csv.
importer le système d'exploitation
Cela importe le module os pour fonctionner avec le système d'exploitation (création de répertoires, vérification de la présence de fichiers, etc.).
à partir du temps d'importation du sommeil
Nous importons la fonction sleep – c'est la fonction qui mettra le script en pause pendant une durée précise (dans mon cas, 2 secondes, mais vous pouvez en définir plus) afin que les éléments se chargent pendant le défilement.
demandes d'importation
Cela importe la bibliothèque de requêtes pour l'envoi de requêtes HTTP, pour interagir avec le service de reconnaissance 2captcha.
Une fois tout importé, le script commence à configurer le navigateur pour le travail, notamment :
Installation de la clé API pour accéder au service 2captcha
# Clé API pour 2Captcha
API_KEY =
Le script contient un agent utilisateur (il peut bien sûr être modifié), qui est installé pour le navigateur. Après cela, le navigateur démarre avec les paramètres spécifiés.
`user_agent = "Mozilla/5.0 (Windows NT 10.0 ; Win64 ; x64) AppleWebKit/537.36 (KHTML, comme Gecko) Chrome/91.0.4472.124 Safari/537.36"
options = webdriver.FirefoxOptions()
options.add_argument(f"user-agent={user_agent}")
driver = webdriver.Firefox(options=options)
`
Vient ensuite le module de solution captcha. C’est exactement l’endroit que recherchent les utilisateurs lorsqu’ils cherchent comment résoudre un captcha. Nous n'analyserons pas ce morceau de code avant longtemps, car il n'a posé aucun problème particulier.
En bref, le script, après chaque chargement de page, vérifie la présence d'un captcha sur la page et s'il l'y trouve, le résout en l'envoyant au serveur 2captcha. S'il n'y a pas de captcha, l'exécution continue simplement.
`def solve_captcha(pilote) :
# Vérifier la présence d'un captcha sur la page
essayez :
captcha_element = driver.find_element(By.CLASS_NAME, 'g-recaptcha')
si captcha_element :
print("Captcha détecté. Résolution...")
site_key = captcha_element.get_attribute('data-sitekey')
current_url = driver.current_url
# Send captcha request to 2Captcha captcha_id = requests.post( 'http://2captcha.com/in.php', data={ 'key': API_KEY, 'method': 'userrecaptcha', 'googlekey': site_key, 'pageurl': current_url } ).text.split('|')[1] # Wait for the captcha to be solved recaptcha_answer = '' while True: sleep(5) response = requests.get(f"http://2captcha.com/res.php?key={API_KEY}&action=get&id={captcha_id}") if response.text == 'CAPCHA_NOT_READY': continue if 'OK|' in response.text: recaptcha_answer = response.text.split('|')[1] break # Inject the captcha answer into the page driver.execute_script(f'document.getElementById("g-recaptcha-response").innerHTML = "{recaptcha_answer}";') driver.find_element(By.ID, 'submit').click() sleep(5) print("Captcha solved.") except Exception as e: print("No captcha found or error occurred:", e)
Analyse
Vient ensuite une section du code chargée de trier les pages, de les charger et de les faire défiler
essayez :
base_url = "https://www.amazon.in/s?k=bags"
for page_number in range(1, 10): page_url = f"{base_url}&page={page_number}" driver.get(page_url) driver.implicitly_wait(10) solve_captcha(driver) WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//span[@class="a-size-medium a-color-base a-text-normal"]'))) for _ in range(5): ActionChains(driver).send_keys(Keys.PAGE_DOWN).perform() sleep(2)
`
L'élément suivant est la collecte de données sur les produits. La partie la plus importante. Dans cette partie, le script examine la page chargée et récupère les données qui y sont spécifiées. Dans notre cas, il s'agit du nom du produit, du nombre d'avis, du prix, de l'URL, de la note du produit.
`product_name_elements = driver.find_elements(By.XPATH, '//span[@class="a-size-medium a-color-base a-text-normal"]')
rating_number_elements = driver.find_elements(By.XPATH, '//span[@class="a-size-base s-underline-text"]')
star_rating_elements = driver.find_elements(By.XPATH, '//span[@class="a-icon-alt"]')
price_elements = driver.find_elements(By.XPATH, '//span[@class="a-price-whole"]')
product_urls = driver.find_elements(By.XPATH, '//a[@class="a-link-normal s-underline-text s-underline-link-text s-link-style a-text-normal"]')
product_names = [element.text for element in product_name_elements] rating_numbers = [element.text for element in rating_number_elements] star_ratings = [element.get_attribute('innerHTML') for element in star_rating_elements] prices = [element.text for element in price_elements] urls = [element.get_attribute('href') for element in product_urls]
`
Ensuite, les données spécifiées sont téléchargées dans un dossier (un fichier csv est créé pour chaque page, qui est enregistré dans le dossier des fichiers de sortie). Si le dossier est manquant, le script le crée.
`output_directory = "fichiers de sortie"
sinon os.path.exists(output_directory):
os.makedirs(output_directory)
with open(os.path.join(output_directory, f'product_details_page_{page_number}.csv'), 'w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(['Product Urls', 'Product Name', 'Product Price', 'Rating', 'Number of Reviews']) for url, name, price, star_rating, num_ratings in zip(urls, product_names, prices, star_ratings, rating_numbers): csv_writer.writerow([url, name, price, star_rating, num_ratings])
`
Et la dernière étape est l'achèvement des travaux et la libération des ressources.
enfin :
driver.quit()
Le scénario complet
`à partir du pilote Web d'importation de sélénium
à partir de selenium.webdriver.common.by import By
à partir de selenium.webdriver.common.keys importer des clés
à partir de selenium.webdriver.common.action_chains, importez ActionChains
depuis selenium.webdriver.support.ui importer WebDriverWait
à partir de selenium.webdriver.support, importez les conditions_attendues en tant que EC
importer csv
importer un système d'exploitation
à partir du temps importer le sommeil
demandes d'importation
API_KEY = "Votre clé API"
user_agent = "Mozilla/5.0 (Windows NT 10.0 ; Win64 ; x64) AppleWebKit/537.36 (KHTML, comme Gecko) Chrome/91.0.4472.124 Safari/537.36"
options = webdriver.FirefoxOptions()
options.add_argument(f"user-agent={user_agent}")
driver = webdriver.Firefox(options=options)
def solve_captcha (pilote) :
# Vérifier la présence d'un captcha sur la page
essayez :
captcha_element = driver.find_element(By.CLASS_NAME, 'g-recaptcha')
si captcha_element :
print("Captcha détecté. Résolution...")
site_key = captcha_element.get_attribute('data-sitekey')
current_url = driver.current_url
# Send captcha request to 2Captcha captcha_id = requests.post( 'http://2captcha.com/in.php', data={ 'key': API_KEY, 'method': 'userrecaptcha', 'googlekey': site_key, 'pageurl': current_url } ).text.split('|')[1] # Wait for the captcha to be solved recaptcha_answer = '' while True: sleep(5) response = requests.get(f"http://2captcha.com/res.php?key={API_KEY}&action=get&id={captcha_id}") if response.text == 'CAPCHA_NOT_READY': continue if 'OK|' in response.text: recaptcha_answer = response.text.split('|')[1] break # Inject the captcha answer into the page driver.execute_script(f'document.getElementById("g-recaptcha-response").innerHTML = "{recaptcha_answer}";') driver.find_element(By.ID, 'submit').click() sleep(5) print("Captcha solved.") except Exception as e: print("No captcha found or error occurred:", e)
essayez :
# URL de la page de démarrage
base_url = "https://www.amazon.in/s?k=bags"
for page_number in range(1, 2): page_url = f"{base_url}&page={page_number}" driver.get(page_url) driver.implicitly_wait(10) # Attempt to solve captcha if detected solve_captcha(driver) # Explicit Wait WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//span[@class="a-size-medium a-color-base a-text-normal"]'))) for _ in range(5): ActionChains(driver).send_keys(Keys.PAGE_DOWN).perform() sleep(2) product_name_elements = driver.find_elements(By.XPATH, '//span[@class="a-size-medium a-color-base a-text-normal"]') rating_number_elements = driver.find_elements(By.XPATH, '//span[@class="a-size-base s-underline-text"]') star_rating_elements = driver.find_elements(By.XPATH, '//span[@class="a-icon-alt"]') price_elements = driver.find_elements(By.XPATH, '//span[@class="a-price-whole"]') product_urls = driver.find_elements(By.XPATH, '//a[@class="a-link-normal s-underline-text s-underline-link-text s-link-style a-text-normal"]') # Extract and print the text content of each product name, number of ratings, and star rating, urls product_names = [element.text for element in product_name_elements] rating_numbers = [element.text for element in rating_number_elements] star_ratings = [element.get_attribute('innerHTML') for element in star_rating_elements] prices = [element.text for element in price_elements] urls = [element.get_attribute('href') for element in product_urls] sleep(5) output_directory = "output files" if not os.path.exists(output_directory): os.makedirs(output_directory) with open(os.path.join(output_directory, f'product_details_page_{page_number}.csv'), 'w', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(['Product Urls', 'Product Name', 'Product Price', 'Rating', 'Number of Reviews']) for url, name, price, star_rating, num_ratings in zip(urls, product_names, prices, star_ratings, rating_numbers): csv_writer.writerow([url, name, price, star_rating, num_ratings])
enfin :
driver.quit()
`
De cette façon, le script fonctionne sans erreur, mais uniquement pour les fiches produits verticales. Voici un exemple du fonctionnement du script.
Je serai ravi d'en discuter dans les commentaires si vous avez quelque chose à dire à ce sujet.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!