Beautifulsoup:.find()和.select() - python 3.xx之间有区别吗?

Die*_*ter 26 python beautifulsoup python-3.x

我有一个简单的问题:

当您使用Beautiful Soup刮取网站的某个部分时,您可以使用data.find()/ data.findAll()或data.select()

现在的问题是..find().select()方法之间是否存在显着差异?(例如,在表现或灵活性方面,或......)

还是他们一样?

亲切的问候

Pad*_*ham 37

总结评论:

  • select找到多个实例并返回一个列表,find找到第一个,所以他们不会做同样的事情.select_one将等同于查找.
  • 我几乎总是在链接标签或使用tag.classname时使用css选择器,如果查找没有类的单个元素我使用find.从本质上讲,它取决于用例和个人偏好.
  • 至于灵活性,我认为你知道答案,soup.select("div[id=foo] > div > div > div[class=fee] > span > span > a")使用多个链式find/find_all 调用看起来很难看.
  • bs4中css选择器的唯一问题是非常有限的支持,nth-of-type是唯一实现的伪类,并且不支持像[href] [src]这样的链接属性,因为css选择器的许多其他部分也是如此.但是像[href = ..]*,[href ^ =],[href $ =]等等,我认为比find("a", href=re.compile(....))个人偏好更好.

出于性能,我们可以运行一些测试,我修改从代码这里的答案上800+的HTML文件运行取自这里,是不是全部,但应该给一个线索的一些选项和性能可读性:

修改后的功能是:

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")
Run Code Online (Sandbox Code Playgroud)

现在为时间安排:

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
Run Code Online (Sandbox Code Playgroud)

就像我说的那样并不详尽,但我认为我们可以肯定地说css选择器肯定更有效率.