Je ne suis pas un expert en scraping Web, mais j'ai réussi à obtenir la plupart de mes souhaits. Cependant, j'ai du mal à analyser la dernière partie de mon code, une image d'arrière-plan.
Voici ce que j'ai:
<div class="flex-embed-content flex-embed-cover-image " style="background-image: url('//site.org/photos/0/kp/cr/QOKPCRqjkbbldlo-400x225-noPad.jpg?1528717310')"></div>
Ce qui renvoie: p >
htmlSource.find('div', class_='flex-embed-content flex-embed-cover-image ')
Je suis intéressé par l'URL //site.org/photos/0/kp/cr/QOKPCRqjkbbldlo-400x225-noPad.jpg?1528717310
p>
Comment puis-je l'analyser à partir de htmlSource?
Merci
5 Réponses :
Récupérez l'attribut style et utilisez la manipulation de chaînes. Exemple de méthode ci-dessous (il y en a clairement d'autres)
from bs4 import BeautifulSoup as bs html = '''<div class="flex-embed-content flex-embed-cover-image " style="background-image: url('//site.org/photos/0/kp/cr/QOKPCRqjkbbldlo-400x225-noPad.jpg?1528717310')"></div>''' soup = bs(html, 'lxml') item = soup.select_one('div.flex-embed-content.flex-embed-cover-image') item['style'].split("url('")[1][:-3]
Remarque J'utilise select_one car il y a une seule correspondance basée sur le html inséré. Vous pouvez utiliser select avec un sélecteur incluant l'attribut style div.flex-embed-content.flex-embed-cover-image [style] et une boucle. Je verrais aussi si vous pouvez réduire le nombre de classes utilisées dans le sélecteur.
Ce n'est pas idéal, car avec le split
vous ne pouvez pas garantir qu'il continue de fonctionner si le site Web modifie ce div
en ajoutant un autre élément sur le style, avant l'url. Pour cette raison, regex est généralement idéal pour ces situations: stackoverflow.com/a/54934372/10642035
@LuanNaufal Je suis d'accord. J'en écrirais un mais tu m'as battu! +
L'attribut style contient du CSS, ce que beautifulsoup ne sait pas analyser.
Alors, première chose - obtenez le contenu de l'attribut de style. Vous devez maintenant analyser le CSS. Vous pouvez l'analyser vous-même (recherchez url (...)
), ce qui fonctionnera si le site ne change pas beaucoup.
Une autre option consiste à utiliser un analyseur CSS dédié, tel que tinycss a>. J'utiliserais un analyseur CSS, votre code sera plus résistant aux modifications du site.
Cela semble très intéressant. Doit-il avoir la page entière? Ou peut-on montrer un exemple en relation avec le problème ci-dessus?
Vous pouvez effectivement le faire avec BS4 facilement, en recherchant uniquement en fonction des classes et en obtenant le style: stackoverflow.com/a/54934372/10642035 a>
Je suis aussi un débutant en web scraping, voici la solution à votre problème.
first=htmlSource.find('div', class_='flex-embed-content flex-embed-cover-image ') get_style=first['style'] break_url=get_style.split(':') break_url=break_url[1] break_url=break_url.split("'") final_url=break_url(1)
Ce n'est pas une bonne réponse, car si le site Web modifiait la logique à l'intérieur du style, il pourrait cesser de fonctionner (comme l'ajout d'un autre élément de style avant l'url). Pour cette raison, je préfère toujours utiliser regex dans ces situations: stackoverflow.com/a/54934372/10642035
Tout d'abord, vous devez obtenir votre élément div
, et il existe de nombreuses façons de le faire, mais comme vous avez une classe vraiment spécifique, cela suffit (en supposant ici que votre code html est stocké dans le Variable htmlSource
:
from bs4 import BeautifulSoup import re soup = BeautifulSoup(html, "html.parser") divElement = soup.select_one('div.flex-embed-content.flex-embed-cover-image') pattern = r"(?<=url\().*(?='\))" url = re.search(pattern, divElement["style"]).group(0)
Maintenant, vous devriez prendre l'attribut style
, et le filtrer pour l'url, et je suggère d'utiliser regex, et de cette façon, vous n'aurez pas de problème avec les éléments inattendus ajoutés aux heures supplémentaires de style:
pattern = r"(?<=url\().*(?='\))" url = re.search(pattern, divElement["style"]).group(0) # The group(0) is used to recover the whole match
Le contenu (? dans regex , suppose que notre correspondance commence par ce contenu TEXT_BEFORE, mais ne l'inclut pas dans la correspondance ( assertion lookbegind ), et le
(? = TEXT_AFTER)
indique le contraire, et ne correspond que si la correspondance suit TEXT_AFTER ( assertion lookahead )
Le code complet serait donc:
soup = BeautifulSoup(htmlSource, "html.parser") divElement = soup.select_one('div.flex-embed-content.flex-embed-cover-image')
L'une des solutions consiste à utiliser urlextract
. Cette classe aide à trouver l'url dans la chaîne.
Code:
site.org/photos/0/kp/cr/QOKPCRqjkbbldlo-400x225-noPad.jpg?1528717310 ---- //site.org/photos/0/kp/cr/QOKPCRqjkbbldlo-400x225-noPad.jpg?1528717310
SORTIE:
soup = BeautifulSoup(html,"lxml") finddiv = htmlSource.find('div', class_='flex-embed-content flex-embed-cover-image') style = finddiv['style'] for url in extractor.gen_urls(style): print (url) print('----') print('//'+url)