12 votes

Beautifulsoup : Y a-t-il une différence entre .find() et .select() - python 3.xx

J'ai une question simple :

lorsque vous utilisez Une belle soupe pour récupérer une certaine partie d'un site web, vous pouvez utiliser data.find() / data.findAll() ou data.select()

La question qui se pose maintenant est la suivante. Existe-t-il une différence significative entre les .find() et le .select() méthodes ? (par exemple, en matière de performance ou de flexibilité, ou ...)

ou sont-elles identiques ?

Cordialement, je vous prie d'agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

21voto

Padraic Cunningham Points 87411

Pour résumer les commentaires :

  • sélectionner trouve plusieurs instances et renvoie une liste, trouver trouve le premier, afin qu'ils ne fassent pas la même chose. select_one serait l'équivalent de trouver .
  • J'utilise presque toujours des sélecteurs css lors de l'enchaînement de balises ou de l'utilisation de tag.classname Si je cherche un seul élément sans classe, j'utilise trouver . Il s'agit essentiellement d'un cas d'utilisation et d'une préférence personnelle.
  • En ce qui concerne la flexibilité, je pense que vous connaissez la réponse, soup.select("div[id=foo] > div > div > div[class=fee] > span > span > a") serait assez laid si l'on utilisait plusieurs find/find_all appels.
  • Le seul problème avec les sélecteurs css dans bs4 est le support très limité, nième du type est la seule pseudo classe implémentée et le chaînage d'attributs comme a[href][src] n'est pas non plus supporté comme beaucoup d'autres parties des sélecteurs css. Mais des choses comme a[href \=..]* , a[href^=] , a[href$=] etc. sont, à mon avis, beaucoup plus agréables que les find("a", href=re.compile(....)) mais là encore, il s'agit d'une préférence personnelle.

Pour des raisons de performance, nous pouvons effectuer quelques tests, j'ai modifié le code à partir d'un fichier réponse ici fonctionnant sur 800+ fichiers html provenant de ici Il n'est pas exhaustif mais devrait donner une idée de la lisibilité de certaines options et des performances :

Les fonctions modifiées sont les suivantes :

from bs4 import BeautifulSoup
from glob import iglob

def parse_find(soup):
    author = soup.find("h4", class_="h12 talk-link__speaker").text
    title = soup.find("h4", class_="h9 m5").text
    date = soup.find("span", class_="meta__val").text.strip()
    soup.find("footer",class_="footer").find_previous("data", {
        "class": "talk-transcript__para__time"}).text.split(":")
    soup.find_all("span",class_="talk-transcript__fragment")

def parse_select(soup):
    author = soup.select_one("h4.h12.talk-link__speaker").text
    title = soup.select_one("h4.h9.m5").text
    date = soup.select_one("span.meta__val").text.strip()
    soup.select_one("footer.footer").find_previous("data", {
        "class": "talk-transcript__para__time"}).text
    soup.select("span.talk-transcript__fragment")

def  test(patt, func):
    for html in iglob(patt):
        with open(html) as f:
            func(BeautifulSoup(f, "lxml")

Passons maintenant aux horaires :

In [7]: from testing import test, parse_find, parse_select

In [8]: timeit test("./talks/*.html",parse_find)
1 loops, best of 3: 51.9 s per loop

In [9]: timeit test("./talks/*.html",parse_select)
1 loops, best of 3: 32.7 s per loop

Comme je l'ai dit, ce n'est pas exhaustif, mais je pense que nous pouvons dire sans risque que les sélecteurs css sont définitivement plus efficaces.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X