刚开始接触 bs4 的时候,我也很迷茫,觉得 string 属性和 text 属性是一样的,不明白为什么要分成两个属性。

html = '<p>hello world</p>'
soup = BeautifulSoup(html, 'lxml')
p = soup.p
print(p.string)  # hello word
print(p.text)   # hello word

输出的结果是一样的。但实际上,string 属性的返回类型是 bs4.element.NavigableString,而 text 属性的返回类型是 str。

print(type(p.string))   # <class 'bs4.element.NavigableString'>
print(type(p.text)) # <class 'str'>

不要小看了这点区别,看下面的示例:

html = '''<html>
<td>some text</td>
<td></td>
<td><p>more text</p></td>
<td>even <p>more text</p></td>
</html>''' soup = BeautifulSoup(html, 'lxml')
tds = soup.find_all('td') for td in tds:
print(td.string) for td in tds:
print(td.text)

string 属性的输出结果为:

some text
None
more text
None

text 属性的输出结果为:

some text

more text
even more text

理解了 string 属性和 text 属性的返回类型,就可以明白结果为什么是这样的了。

第一项,返回都是 “some text”,这可以理解;

第二项,string 返回 None,因为不存在 NavigableString 节点;

第三项,text 返回的是标签的所有字符串连接成的字符串,所以是“more text”

第四项,bs4 的文档中指出:(地址:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#string)

  如果 tag 只有一个 NavigableString 类型子节点,那么这个 tag 可以使用 .string 得到子节点。
  如果一个 tag 仅有一个子节点,那么这个 tag 也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同。
  如果 tag 包含了多个子节点,tag 就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None。

  那么自然 string 属性返回的结果是 None,text 属性返回的结果是“even more text”

另外,要注意的是 find 方法中的 text 参数,官方解释是:text 参数用于搜索字符串会找到 .string 方法与 text 参数值相符的tag。

也就是说,虽然参数名是 text,但实际上搜索的是 string 属性。

看下面的例子,我们需要查找到包含附件链接的<a>标签

html = '''<div>
<p>
附件:
<a href='xxx'>下载</a></p>
</div>
'''

用 string 属性来获取的话,代码如下:

soup = BeautifulSoup(html, 'lxml')
tab = soup.find(text=re.compile('附件'))
print(type(tab)) # <class 'bs4.element.NavigableString'>
print(tab) # 附件

可以看到获取到的是 NavigableString 标签,要获取<a>标签,可以配合 find_next_sibling() 方法。

如果使用使用 text 属性的话,就必须传递方法来实现,但结果可能就不是你想要的了

def txt(tag):
return re.search('附件', tag.text) is not None print(soup.find_all(txt))

结果如下,把每一层显示的都包含进来了。

[<html><body><div>
<p>
附件:
<a href="xxx">下载</a></p>
</div>
</body></html>, <body><div>
<p>
附件:
<a href="xxx">下载</a></p>
</div>
</body>, <div>
<p>
附件:
<a href="xxx">下载</a></p>
</div>, <p>
附件:
<a href="xxx">下载</a></p>]

相关博文推荐:

Python:bs4的使用

Python:requests:详解超时和重试

Python:bs4中 string 属性和 text 属性的区别及背后的原理的更多相关文章

  1. jquery html属性和text属性的区别

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. C# 中 string.Empty、""、null的区别

    原文C# 中 string.Empty."".null的区别 一.string.Empty 和 "" 1.Empty是string类中的一个静态的只读字段,它是 ...

  3. java中String new和直接赋值的区别

        Java中String new和直接赋值的区别     对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才 ...

  4. MaskEdit组件的EditText属性和Text属性

    MaskEdit组件主要是EditMask属性 是string属性. 掩码字符串EditMask属性分为3个部分,分别用分号隔开,形式是“XXXXX;X;X” 第一部分是掩码字符串的主要部分,它确定输 ...

  5. java中String、StringBuffer、StringBuilder的区别

    java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题.现在总结一下,看看他们的不同与相同. 1.可变与不可 ...

  6. C#中string.Empty和""、null的区别

    string.Empty是string类的一个静态常量,而""则表示一个空字符串. string是一种特殊的引用类型,它的null值则表示没有分配内存. 使用ILSpy反编译Str ...

  7. Java中String类两种实例化的区别(转)

    原文:http://blog.csdn.net/wangdajiao/article/details/52087302 一.String类的第一种方式 1.直接赋值 例:String str = &q ...

  8. Java基础——java中String、StringBuffer、StringBuilder的区别

    (转自:http://www.cnblogs.com/xudong-bupt/p/3961159.html) java中String.StringBuffer.StringBuilder是编程中经常使 ...

  9. .NET 中String 和StringBuilder 以及他们的区别

    stirng对象是不可变的,每次使用String类的方法进行运算时(赋值.拼接),都会在内存中生成新的字符串对象,这就要为新对象分配新的内存空间. StringBuilder 实例的 int Capa ...

随机推荐

  1. document_index_data.go

    package types type DocumentIndexData struct {     // 文档全文(必须是UTF-8格式),用于生成待索引的关键词     Content string ...

  2. appium+python 清空文本框EditText的值

    清空EditText的自动化脚本编写流程: 前提条件:进入到要删除文本框的页面 1.查找到要删除的文本框,可通过id.name等属性进行查找 2.点击 3.通过get_attribute(" ...

  3. UWP中实现大爆炸效果(二)

    上一回实现了一个宽度不均匀的Panel,这次我们编写一个简单的BigbangView主体. 首先创建一个模板化控件,删掉Themes/Generic.xaml中的<Style TargetTyp ...

  4. 使用Entity Framework Core访问数据库(DB2篇)

    前言 上一篇讲了一些EF Core访问Oracle的坑.(感兴趣请移步:使用Entity Framework Core访问数据库(Oracle篇)) 这篇主要讲一下关于EF Core访问DB2的一揽子 ...

  5. 【BAT面试题系列】面试官:你了解乐观锁和悲观锁吗?

    前言 乐观锁和悲观锁问题,是出现频率比较高的面试题.本文将由浅入深,逐步介绍它们的基本概念.实现方式(含实例).适用场景,以及可能遇到的面试官追问,希望能够帮助你打动面试官. 目录 一.基本概念 二. ...

  6. 干货,一文带你超详细了解Session的原理及应用

    session 简介 session 是我们 jsp 九大隐含对象的一个对象. session 称作域对象,他的作用是保存一些信息,而 session 这个域对象是一次会话期间使用同一个对象.所以这个 ...

  7. mongodb副本集实现

    目录 1. 简单介绍 primary: secondary: arbiter: 2.系统环境设置: 3.安装mongodb 安装mongodb 增加配置文件: 添加启动脚本 3. 副本集实现: 1. ...

  8. 一大波开发者福利来了,一份微软官方Github上发布的开源项目清单等你签收

    目录 微软Github开源项目入口 微软开源项目受欢迎程度排名 Visual Studio Code TypeScript RxJS .NET Core 基础类库 CNTK Microsoft cal ...

  9. 简易版本vue的实现

    用了Vue也有两年时间了,一直以来都是只知其然,不知其所以然,为了能更好的使用Vue不被Vue所奴役,学习一下Vue底层的基本原理. Vue官网有一段这样的介绍:当你把一个普通的JavaScript对 ...

  10. 关于php-fpm比较重要的几个参数

    pm.max_children 设置多大合适? php-fpm.conf有两个至关重要的参数: 一个是”max_children”,另一个是”request_terminate_timeout”. p ...