J'ai créé un script pour obtenir le titre de différentes boutiques à partir de pages Web identiques. Le script fonctionne bien.
J'essaie maintenant de créer une logique dans le script pour le laisser essayer plusieurs fois s'il ne parvient pas à récupérer les titres de ces pages.
À titre de test, si je définis la ligne avec selector autrement, comme dans name = soup.select_one (". sales-info> h"). text
, le script ira en boucle indéfiniment.
J'ai essayé jusqu'à présent avec:
import requests from bs4 import BeautifulSoup links = ( 'https://www.yellowpages.com/san-francisco-ca/mip/nizarios-pizza-481135933', 'https://www.yellowpages.com/nationwide/mip/credo-452182701' ) def get_title(s,link): r = s.get(link) soup = BeautifulSoup(r.text,"lxml") try: name = soup.select_one(".sales-info > h1").text except Exception: print("trying again") return get_title(s,link) #I wish to bring about any change here to let the script try few times other than trying indefinitely return name if __name__ == '__main__': with requests.Session() as s: s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36' for link in links: print(get_title(s,link))
Comment puis-je laisser le script essayer plusieurs fois lorsqu'il ne parvient pas à récupérer le titre d'une page Web?
PS Les pages Web que j'ai utilisées dans le script sont des espaces réservés.
4 Réponses :
Je pense que le moyen le plus simple serait de passer de la récursion à une boucle:
def get_title(s,link): failed = 0 while failed < 5: try: r = s.get(link) soup = BeautifulSoup(r.text,"lxml") name = soup.select_one(".sales-info > h1").text return name except Exception: # Best to specify which one, by the way failed += 1 print('Failed too many times') return None
J'ai ajouté des paramètres pour spécifier le nombre de tentatives, la mise en veille entre les tentatives et la valeur par défaut à renvoyer si tout échoue:
Retry 1/3 Retry 2/3 Retry 3/3 Failed to grab https://www.webscraper.io/test-sites/e-commerce/allinone Retry 1/3 Retry 2/3 Retry 3/3 Failed to grab https://www.webscraper.io/test-sites/e-commerce/static
Impressions:
import time import requests from bs4 import BeautifulSoup links = ( 'https://www.webscraper.io/test-sites/e-commerce/allinone', 'https://www.webscraper.io/test-sites/e-commerce/static' ) def get_title(s, link, retries=3, sleep=1, default=''): """ s -> session link -> url retries -> number of retries before return default value sleep -> sleep between tries (in seconds) default -> default value to return if every retry fails """ name, current_retry = default, 0 while current_retry != retries: r = s.get(link) soup = BeautifulSoup(r.text,"lxml") try: name = soup.select_one("h8").text except Exception: print("Retry {}/{}".format(current_retry + 1, retries)) time.sleep(sleep) current_retry += 1 return name if __name__ == '__main__': with requests.Session() as s: s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36' for link in links: print(get_title(s, link, 3, 1, 'Failed to grab {}'.format(link)))
Vous pouvez réaliser la même chose de différentes manières. En voici une autre que vous voudrez peut-être essayer:
import time import requests from bs4 import BeautifulSoup links = [ "https://www.yellowpages.com/san-francisco-ca/mip/nizarios-pizza-481135933", "https://www.yellowpages.com/nationwide/mip/credo-452182701" ] def get_title(s,link,counter=0): r = s.get(link) soup = BeautifulSoup(r.text,"lxml") try: name = soup.select_one(".sales-info > h").text except Exception: if counter<=3: time.sleep(1) print("done trying {} times".format(counter)) counter += 1 return get_title(s,link,counter) else: return None return name if __name__ == '__main__': with requests.Session() as s: s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36' for link in links: print(get_title(s,link))
Vous pouvez essayer d'utiliser n'importe quelle bibliothèque de nouvelle tentative, telle que ténacité , backoff . Notez que ces bibliothèques fonctionnent généralement comme des décorateurs et que votre fonction devra simplement effectuez l'importation, puis appelez le décorateur de la même manière que:
import requests from bs4 import BeautifulSoup from tenacity import retry ###or import backoff ... @retry ###or @backoff.on_exception(backoff.expo, requests.exceptions.RequestException) def get_title(s, link, retries=3, sleep=1, default=''): ...