2017-09-16 2 views
0

Je dois créer une fonction en python qui recherche des liens dans une page HTML et ensuite pour chaque lien, vérifiez si le lien est cassé ou non.un vérificateur de liens en python

Tout d'abord j'ai créé une fonction qui recherche chaque lien (cassé ou non), pas de problème et les stocke dans un tableau appelé "g".

Deuxièmement, j'ai pensé à créer un tableau "a" qui ne contient que les liens rompus en vérifiant chaque élément/élément dans le tableau "g".

Je ne sais pas pourquoi, le lien de vérification par lien ne fonctionne pas dans la fonction. Mais si je copie un lien et le colle comme un paramètre dans la fonction sur le shell, cela fonctionne.

import urllib.request 
import re 
import urllib.error 

def check(url): 
    try: 
     f= urllib.request.urlopen(url) 
    except urllib.error.HTTPError : 
      return False 
    return True 
def trouveurdurls(url): 
    f= urllib.request.urlopen(url) 
    b=(f.read().decode('utf-8')) 
    d=re.findall('<a href=".*</a>',b) 
    liste=[] 
    f.close() 
    for el in d: 
     g=re.findall('"https?://.*\.*"',el) 
     liste.append(g) 
    a=[] 
    for el in liste: 
     chaine= ''.join(map(str,el)) 
     url=chaine.replace('\'','') 
     print(url) 
     #check(url) 


b=trouveurdurls("http://127.0.0.1/") 
+2

Comment ça ne marche pas exactement? Est-ce que votre URL est correcte quand elle est imprimée ...? Notez que 're.findall' renvoie une liste (et probablement plus que vous ne le pensez), vous ajoutez ensuite' list' à 'liste' ... Mettez des instructions d'impression à chaque étape et identifiez le plus tôt Les choses commencent à avoir l'air "fausses" ... –

+0

De plus, ajouter des commentaires à votre code peut aider les gens à comprendre le fonctionnement de votre code. – admcfajn

Répondre

0

Voici une version qui utilise "demandes". Il gratte la page pour les URL, puis vérifie chacune des URL pour leurs codes de réponse (200 signifie que cela a fonctionné, etc).

import requests 
from bs4 import BeautifulSoup 

page = 'http://the.web.site' 

r = requests.get(page) 

data = r.text 

soup = BeautifulSoup(data, 'lxml') 

urls = [] 

for a in soup.find_all('a'): 
    urls.append(a.get('href')) 

url_responses = {} 

for url in urls: 
    temp_r = requests.get(url) 
    url_responses[url] = temp_r.status_code 
+0

Je pense que vous voulez l'attribut 'href' des éléments' a' - pas tout le contenu ... Aussi, vous pouvez aussi bien utiliser 'requests.head' pour afficher la bande passante que vous voulez seulement vérifier si le serveur fournira une réponse car vous ne vous souciez pas du contenu. –

+0

Merci d'avoir rattrapé mon erreur @Jon Clements, j'ai changé la partie 'href'. Je ne l'ai pas modifié pour demander seulement la tête, mais vous avez absolument raison pour les pages où la bande passante serait un problème. –

0

Je serais très surpris si la ligne

d=re.findall('<a href=".*</a>',b) 

a fonctionné correctement. L'astérisque fait un match gourmand, ce qui signifie qu'il trouve le match le plus long possible. Si vous avez plus d'un lien dans votre document, cette regex engloutira tout entre le premier et le dernier lien.

Vous devriez probablement utiliser la version non gourmande de l'astérisque, par ex. * ?.

En outre, vous êtes seulement intéressé par l'attribut href, si

d = re.findall('<a href=".*?"', b) 

est probablement ce que vous voulez. Cela rendra le code suivant plus facile; Vous n'aurez pas besoin d'essayer de rechercher les URL commençant par http: // car vous les avez déjà dans le tableau d. Votre code tel qu'il est trouverait également des URL qui ne faisaient pas partie de l'attribut href d'un a mais juste une partie du texte normal, ou une partie d'une référence d'image, etc.

Notez que même l'expression régulière <a href=".*?" ne sera pas constamment produire des correspondances, parce que HTML est très paresseux avec sa syntaxe, de sorte que vous pouvez également rencontrer des chaînes comme <A HREF='.....'>, <a href = "....., <a id="something" href="......"> et ainsi de suite.

Vous devrez soit améliorer l'expression rationnelle pour correspondre à tous ces cas, ou se tourner vers BeautifulSoup comme la réponse d'Evan ou un analyseur HTML à part entière qui prend soin de lui pour vous.

+0

merci pour votre explication, à propos de la regex, j'ai fait la ligne d = re.findall (' ahmedaboukora

+0

Assurez-vous que votre regex ne dépend pas de l'attribut href précédant tout autre attribut valide - un élément 'a' peut avoir d'autres attributs en plus de 'href' et ils peuvent venir * avant * le 'href'. plus qu'un simple espace pour les espaces, et "et" peut être utilisé pour délimiter les valeurs d'attribut. Votre regex devrait prendre tout cela en compte si vous traitez avec du HTML dont vous ne contrôlez pas la génération. – Pascal