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=''): ...