Bonjour,
Je travaille depuis pas mal de temps sur un projet, mais je block sur la façon de créer un scraper qui vas tout seul chercher et retourner les Urls de site qu'il a trouver selon des paramètres précis, du genre le contenu du site ou encore sur un sujet précis ( ex : la maçonnerie )
Auriez-vous des idées à me proposer ?
Merci d'avance !
bonjour, bizarre que tu sois bloqué depuis pas mal de temps.
peux-tu nous montrer ce que tu as réalisé pendant tout ce temps? nous pourrons sans doute t'aider à l'améliorer!
Bonsoir,
Je pense que tu n'as pas comprie la question ;).
Je suis sur un gros projet et dans celui-ci j'aurais besoins d'un scraper un peux spéciale, comme je l'ai expliqué, mais je ne trouve rien sur sa.
Attention à puppeteer il utilise le mode headless, aucun webbrowser ne s'ouvrira ( donc tu ne verra pas les actions visuelles ) je te conseille celui là personnellement mais dès lors que tu maitrisera le sujet. Pour débuter essaie Sélénium, une fois prit en main toutes les Framework se ressembles et tu pourra passer en mode headless avec puppeteer.
Merci pour t'es conseils précieux !
Mais esque un framewrok permet de faire des recherches internet, et si oui comment ?
J'ai cherché toute la journée comment faire via tout les frameworks que tu mas conseiller mais j'ai pas trouvé...
Pourrais tu m'expliquer ?
Merci beaucoup
Yap, si tu est un bambi dans le domaine, je vais te prévenir d'avance sur ces Framework il y a peux de tuto de A-Z comme le site du zéro, la documentation est majoritairement en Anglais, beaucoup de code non structuré, il y a Page Object Pattern qui est une bonne pratique de mise en place mais peu mettre un certains temps à s'en approprié correctement et fonctionnellement.
Ton but est de réaliser une navigation sur un domaine et d'en extraire les liens si j'ai bien comprit et tout cela automatiquement ( après que les liens sont en lien avec la maçonnerie ou autre ça c'est ton algo qui va gérer ).
Sélénium va te permette de réaliser le comportement humain sur un site automatiquement afin d'en extraire les données souhaitées.
regarde le minimal exemple sur le site de Sélénium :
Tout marche niquel sauf le renvoie des liens j'ai un message d’erreur sur le ‘’srl’’ donc le string des liens je suppose, mais je n’arrive pas a trouver ou mettre la fonction .str() dans le code.
Pour t’aider je t’envoie le code et le message d’erreur.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
#This example requires Selenium WebDriver 3.13 or newer
with webdriver.Firefox() as driver:
wait = WebDriverWait(driver, 10)
driver.get("https://google.com/ncr")
driver.find_element(By.NAME("//a")).send_keys("cheese" + Keys.RETURN)
first_result = wait.until(presence_of_element_located((By.CSS_SELECTOR, "h3>div")))
print(first_result.get_attribute("textContent"))
Et le message d’erreur :
Traceback (most recent call last):
File "C:\Users\larde\Documents\[https://www.commentcamarche.net/python/ python]\test_scrapper.py", line 49, in <module>
driver.find_element(By.NAME("//a")).send_keys("cheese" + Keys.RETURN)
TypeError: 'str' object is not callable
La méthode send_keys : permet d'envoyer du texte dans une input, il remplie l'attribut value de celui-ci, Les balises a, n'ont pas d'attribut value du coup une exception est levée.
Dans ton cas ton WebElement est un lien de tag 'a' ta seule action non exhaustive avec cette élément sera une action :
- click() : qui va réaliser la navigation vers se lien.
Et tu cherchais tous les éléments de type 'a' sauf que tu utilise
find_element
qui va te retourner le premier élément trouvé de la page, c'est
find_elements
que tu devrais utiliser.
-
find_element
: WebElement
-
find_elements
Tableau de WebElement ( faut maitriser les tableaux en Python )
slt,
j'ai un petit problème j'ai réecrit tout le code en lisant bien le framwork ;)
mais j'ai quand même l'erreur "'str' object is not callable", y a t-il une erreur dans le code ?
Je t'envoie le code et l'erreur en entier pour que tu puisse comprendre.
import selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Firefox()
global str
driver.get('https://www.google.com')
inputElems = driver.find_elements_by_css_selector('input[name=q]')
for inputElem in inputElems:
inputElem.send_keys('Tableau de prospect')
inputElem.send_keys(Keys.ENTER)
time.sleep(5)
result = driver.current_url
#print(result)
driver.close()
drivers = webdriver.Firefox()
drivers.get(result)
time.sleep(4)
str(drivers.find_elements( By.XPATH("//a") ))
results = drivers.find_elements
print(results)
drivers.close()
et voici l'erreur
Traceback (most recent call last):
File "C:\Users\dell\Documents\scrapper_test.py", line 23, in <module>
str(drivers.find_elements( By.XPATH("//a") ))
TypeError: 'str' object is not callable
ligne 9, tu déclares str comme étant une variable globale, dans un contexte global, ce qui ne sert à rien. Comme Python de toutes façons n'en sait pas plus sur str, il est incapable de savoir quoi faire quand tu prétend vouloir l'appeler comme un objet avec les paramètres entre parenthèses en ligne 23.
Le plus simple est de retirer la ligne 9, qui ne sert à rien, et de remplacer la ligne 23 par juste
drivers.find_elements( By.XPATH("//a") )
qui semble appeler un objet une méthode find_elements d'un objet drivers que tu as déclaré et utilisé plus haut dans ton code.
Tu n'es pas un faon nouveau-né, sinon tu aurais du mal à taper au clavier avec tes pattes tremblantes, alors, prend le temps de comprendre un minimum Python et pour savoir ce que tu fais avec les codes que tu utilises.
Sinon, je n'ai jamais utilisé Selenium avec Python (mais plutôt avec Java, cela date de plusieurs années), mais je trouve bizarre que tu fermes le driver entre deux requêtes.
tu n'est pas obligé de fermer le Webdriver et d'en ré-instancier un nouveau Ligne 12, réutilise celui dèjà instancié. ce n'est pas 1 WebDriver par Url. Tu as le droit d'enchainer les urls. Comme l'as stipulé [Dal]
driver.close()
drivers = webdriver.Firefox()
Si je suis la logique du code by steps :
- tu navigue sur https://www.google.com/ - tu veux récupérer input de recherche et d'y envoyer 'Tableau de prospect'
- puis réaliser la recherche
- tu attend 5 seconde
- met adresse https://www.google.com/ dans result
- ferme
- ....
Ta boucle ne sert à rien puisque dans la page tu aura q'un seul élément de type
input[name=q]
récupère simplement le premier élément du tableau.
J'instancie mon driver
Je navigue vers google.com
Tableau varElements ← getElementsByCss( input[name=q] ) Element input ← varElements[0]
input.sendKeys( "...." ) input.sendKeys( Keys.ENTER ); // si le enter ne fonctionne pas click button recherche
// si tout fonctionne le webdriver va gérer la redirection tout seul pas besoin de fermer ou ré-ouvrir un nouveau
Tableau varLiens ← drivers.find_elements( By.XPATH("//a") ) Nombre i ← 0
boucle varLiens tant que i < varLiens.length
string varLink ← varLiens[ i ].getAttributes( "href" ) // record lien dans un fichier
fin
Fermeture
Et pour éviter les sleep utilise, les
Waiter
, tu prend une balise dans le code qui est unique à la pages ( genre : il y a 300000 recherches en 0.005 secondes ) , tu tu fait une expectedCondition visibilityOfElementLocated sur l'élément, quand l'élément est trouvé est visible c'est que tu est sur la page sinon une exception sera levé de l'inexistence ou non-visibilité de l'élément. Tu optimise ton code, au lieu d'un simple sleep, l' expectedCondition s'assure de la bonne continuité des prochaines étapes.
Slt,
Merci pour vos conseils précieux !
Cependant, j'ai testé les modifs que vous m'aviez suggérer, mais ça n'a pas marcher.
Heureusement, j'ai pu trouver une autre solution qui fonctionne, mais j'ai quand même eux un problème sur le retour des urls.
J'ai reçus tout plein d'urls comme je l'espérais, mais se sont des urls qui redirige vers google ou autre chose, en bref ça me donne tout sauf ce dont j'ai besoins (les urls des sites internets).
Comment es que je pourrais trier les urls pour avoir que celle dont j'ai besoins ?
Je vous envoie le code pour que vous puissiez jeter un coup d'oeuil.
import selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Firefox()
driver.get('https://www.google.com')
inputElems = driver.find_elements_by_css_selector('input[name=q]')
for inputElem in inputElems:
inputElem.send_keys('Tableau de prospect')
inputElem.send_keys(Keys.ENTER)
time.sleep(5)
result = driver.current_url
time.sleep(4)
elems = driver.find_elements( By.XPATH, "//a[@href]" )
for elem in elems:
print (elem.get_attribute("href"))
time.sleep(3)
driver.close()
Tu demande tous les éléments de type "a" donc en retour tu n'auras pas que les éléments de la zone de recherche, mais tout les éléments button, lien de header, lien du footer etc....., tu dois mieux préciser ton sélecteur, mais avant ça :
- Où est-ce que dans ton code tu t'assure que lorsque tu demande tout les éléments a Sélénium que tu est bien sur la bonne page ?
( une redirection un peu longue supérieur à 4 secondes ou qui ne se fait pas, et il va récupérer tout les éléments '
a
' de la page d'accueil ).
- Le problème avec google si tu veux mieux préciser le sélecteur cela peut vite devenir difficile, les class sont randomisé, très peu d'ID voir aucun, il faut se dire qu'il n'a pas été mise à dispo pour être automatisé encore moins pour un scraper, et google n'aime pas ça, si tu t'acharne sur lui tu va te retrouver avec une belle captcha.
Recherche google : Ethernet
//div[contains(@id,'search')]//a[@href and @data-ved and contains(@href,'http')]
c'est le plus précis que j'aurais utilisé sans trop me faire de mal pour la suite. Pour avoir un visuel des éléments concerné dans la console web → onglets 'Element' → clavier CTRL+F une input va s'afficher tu colle le finder dedans.
Merci beaucoup pour ta réponse, je vais tester sa se soire et je te tiendrait au courent.
Et le la ligne de code
result = driver.current_url
devait servir à récupérer l'url de la page pour pouvoir la rouvrir dans une autre page mais vus que je nan n'ai plus besoins je vais la supprimer (petite erreur de ma part).
Je pense que tu n'as pas comprie la question ;).
Je suis sur un gros projet et dans celui-ci j'aurais besoins d'un scraper un peux spéciale, comme je l'ai expliqué, mais je ne trouve rien sur sa.