当你使用100来刮网站的某个部分时,你可以使用

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

.find().select()方法之间有区别吗?

推荐答案

总结 comments :

  • select查找多个实例并返回一个列表,find查找第一个实例,因此它们不会执行相同的操作.select_one相当于find.
  • 当链接标签或使用tag.classname时,我几乎总是使用css Select 器,如果寻找一个没有类的元素,我使用find.本质上,这取决于用例和个人偏好.
  • 就灵活性而言,我想你知道答案,如果使用多个链接的find/find_all个电话,soup.select("div[id=foo] > div > div > div[class=fee] > span > span > a")个看起来会很难看.
  • bs4中css Select 器的唯一问题是支持非常有限,nth-of-type是唯一实现的伪类,像[href][src]这样的链接属性也不受支持,css Select 器的许多其他部分也不受支持.但是像a[href=…]*,a[href^=]a[href$=]等等..我认为这比find("a", href=re.compile(....))好得多,但这也是个人偏好.

为了提高性能,我们可以运行一些测试,我修改了运行在here的800+html文件上的answer here的代码,这不是详尽的,但应该提供一些选项的可读性和性能的线索:

修改后的功能包括:

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 Select 器肯定更有效.

Python-3.x相关问答推荐

Python3和请求-超文本标记语言:试图抓取一个网站-没有取回真正的超文本标记语言代码

Pandas :从元组字典创建数据帧

如何从枚举中获取某个值?

正确的本地react 方式-Django身份验证

根据第一个字典的值序列对第二个字典进行排序

Django中自动设置/更新字段

将值从函数传递到标签

在新数据帧上自动提取两个字符串 python 之间的相等性

Pytest顺序测试A,然后测试B,然后再测试A

平移数组

在 pytest 中,如何测试 sys.exit('some error message')?

如何使用 regex sub 根据列表中的变量替换字符

非拉丁字符的Python正则表达式不起作用

是否将dict转换为一个数据帧,每个值都有重复的键?

Selenium (Python) - 使用 Chrome 网络驱动程序等待下载过程完成

导入 python 模块而不实际执行它

Pyodbc:登录超时错误

Python 3 中的连接列表

如何阻止散景在 Jupyter Notebook 中打开新标签?

在 Visual Studio Code 中调试 Scrapy 项目