Je suis novice en python et j'ai commencé à expérimenter avec Beautiful Soup 4. J'ai essayé d'écrire du code qui obtiendrait tous les liens sur une seule page, puis avec ces liens, répéter les prosses jusqu'à ce que j'ai un site Web entier analysé.

import bs4 as bs
import urllib.request as url

links_unclean = []
links_clean = []
soup = bs.BeautifulSoup(url.urlopen('https://pythonprogramming.net/parsememcparseface/').read(), 'html.parser')

for url in soup.find_all('a'):
    print(url.get('href'))
    links_unclean.append(url.get('href'))

for link in links_unclean:
    if (link[:8] == 'https://'):
        links_clean.append(link)

print(links_clean)

while True:
    for link in links_clean:
        soup = bs.BeautifulSoup(url.urlopen(link).read(), 'html.parser')

        for url in soup.find_all('a'):
            print(url.get('href'))
            links_unclean.append(url.get('href'))

        for link in links_unclean:
            if (link[:8] == 'https://'):
                links_clean.append(link)

        links_clean = list(dict.fromkeys(links_clean))



input()

Mais je reçois maintenant cette erreur:

L'objet 'NoneType' n'est pas appelable ligne 20, dans soup = bs.BeautifulSoup (url.urlopen (link) .read (), 'html.parser')

Peux-tu aider s'il te plait.

1
hacker HD 16 mars 2019 à 05:34

2 réponses

Meilleure réponse

Soyez prudent lorsque vous importez des modules as quelque chose. Dans ce cas, url sur la ligne 2 est remplacé dans votre boucle for lorsque vous itérez.

Voici une solution plus courte qui ne renverra également que les URL contenant https dans le cadre de l'attribut href :

from bs4 import BeautifulSoup
from urllib.request import urlopen


content = urlopen('https://pythonprogramming.net/parsememcparseface/')
soup = BeautifulSoup(content, "html.parser")
base = soup.find('body')

for link in BeautifulSoup(str(base), "html.parser").findAll("a"):
    if 'href' in link.attrs:
        if 'https' in link['href']:
            print(link['href'])

Cependant, cela donne une image incomplète car tous les liens ne sont pas capturés en raison d'erreurs sur la page avec des balises HTML. Puis-je également recommander l'alternative suivante, qui est très simple et fonctionne parfaitement dans votre scénario (note : vous aurez besoin du package Requêtes-HTML) :

from requests_html import HTML, HTMLSession

session = HTMLSession()
r = session.get('https://pythonprogramming.net/parsememcparseface/')

for link in r.html.absolute_links:
    print(link)

Cela produira toutes les URL, y compris celles qui font référence à d'autres URL sur le même domaine et celles qui sont des sites Web externes.

0
Sébastien Lavoie 16 mars 2019 à 18:31

J'envisagerais d'utiliser un sélecteur CSS d'attribut = valeur et d'utiliser l'opérateur ^ pour spécifier que les attributs href commencent par https. Vous n'aurez alors que des protocoles valides. Utilisez également des compréhensions d'ensemble pour éviter les doublons et Session pour réutiliser la connexion.

from bs4 import BeautifulSoup as bs
import requests
import pandas as pd
final = []

with requests.Session() as s:
    r = s.get('https://pythonprogramming.net/parsememcparseface/')
    soup = bs(r.content, 'lxml')
    httpsLinks = {item['href'] for item in soup.select('[href^=https]')}
    for link in httpsLinks:
        r = s.get(link)
        soup = bs(r.content, 'lxml')
        newHttpsLinks = [item['href'] for item in soup.select('[href^=https]')]
        final.append(newHttpsLinks)
tidyList =  list({item for sublist in final for item in sublist})  
df = pd.DataFrame(tidyList)
print(df)
0
QHarr 16 mars 2019 à 04:58