当前位置: 首页 > 面试题库 >

Beautifulsoup:.find()和.select()之间的区别

苍兴怀
2023-03-14
问题内容

当您使用
BeautifulSoup

抓取网站的特定部分时,您可以使用

  • soup.find()soup.findAll()
  • soup.select()

.find().select()方法之间有区别吗?(例如,性能或灵活性等)还是相同?


问题答案:

总结评论:

  • select 查找多个实例并返回一个列表, find 查找第一个实例,因此它们不会执行相同的操作。 select_one 将等同于 find
  • 我链接时,标签或使用几乎总是使用CSS选择 tag.classname ,如果寻找一个单一的元素没有一个类我用 找到 。本质上,它取决于用例和个人喜好。
  • 就灵活性而言,我认为您知道答案,soup.select("div[id=foo] > div > div > div[class=fee] > span > span > a")使用多个链接的 find / find_all 调用看起来很难看。
  • bs4中的css选择器唯一的问题是对它的支持非常有限, nth-of-type 是唯一实现的伪类,并且像c [sref ]的许多其他部分一样,也不支持链接属性,例如a [href] [src]。但是像 a [href = ..] *, a [href ^ =]a [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")

现在是时候了:

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

就像我说的并不详尽,但我认为我们可以肯定地说CSS选择器绝对有效。



 类似资料:
  • 问题内容: 我发现与BeautifulSoup一起使用时有些奇怪,找不到任何文档来支持此操作,所以我想在这里询问。 假设我们有一个这样的标签,我们已经用BS对其进行了解析: 提取数据的官方记录方法是。但是,这为第二个标签提取了NoneType 。所以我尝试了(因为为什么不呢?),它完全按照我的意愿提取了一个空字符串。 但是,我在文档中找不到对此的任何引用,并且担心某些内容会丢失。谁能告诉我这是否可

  • 问题内容: 我想明白之间的差别和。 根据,(据我了解),即使找到了所要查找的内容,它也会搜索整个字符串,并在找到所要查找的内容时停止。 如果这个假设是正确的,我看不到,只要你想使用的,而不是,除非你想指望它找到匹配的数量。 在我看来,类应该具有而不是作为内置方法。 总结一下: 我的假设正确吗? 什么时候代替有用? 问题答案: 尝试将表达式与整个字符串匹配,并在模式的开头和结尾隐式添加a ,这意味着

  • 问题内容: Java 正则表达式中match()和find()之间的区别? 问题答案: 尝试将表达式与整个字符串匹配,并在模式的开头和结尾隐式添加 ,这意味着它将不查找子字符串。因此,此代码的输出: 是的子字符串,因此该方法输出。仅“看到” 与“不相同” ,因此输出。

  • 问题内容: 最近,我在查询性能方面遇到了一些问题。经过长时间的努力,我终于发现带有select前缀的查询如下: 是慢300倍,然后以这种方式启动查询: 有人可以帮我吗,为什么呢?关于此的一些外部文档将非常有用。 用于测试的表是: SALES_UNIT 表包含一些基本的信息 自动售货机 节点,例如名称等。唯一的关联是表SALES_UNIT_TYPE,例如ManyToOne。主键是ID和字段VALID

  • 问题内容: 我错放了太多次了,我想我一直忘记,因为我不知道两者之间的区别,只是一个给了我我期望的价值,而另一个却没有。 为什么是这样? 问题答案: 是的简写形式(尽管请注意,该表达式只会被计算一次。) 是的,即指定一元的到。 例子: