每个tag或字符串都有父节点,即每个节点都被包含在tag中,通过 .parent 属性来获取某个元素的父节点: p.parent,通过元素的 .parents 属性可以递归得到元素的所有父辈节点。
soup = BeautifulSoup(div_html), \'lxml\') # 使用3.1中定义的 div_html div = soup.div # 获取 div 节点 sa = div.a.string # 第一个 a 节点的string sa.parent # a 节点 sa.parent.parent # div 节点 for parent in sa.parents: print(parent) # a # div # [document] # None 3.3 兄弟节点兄弟节点就是具有相同父节点的同义词节点。如3.1中定义的 div_html 中的3个p标签互相为兄弟节点。使用下面的节点tag属性访问兄弟节点
next_sibling:当前节点的下一个兄弟节点
previous_sibling:当前节点的上一个兄弟节点
next_siblings:当前节点之后的所有兄弟节点
previous_siblings:当前节点之前的所有兄弟节点
4. 搜索文档树搜索功能可以说是写爬虫过程中必用的功能,用来查找指定的节点,Beautiful Soup定义了很多搜索方法,这些搜索方法的参数和用法都很类似,查询功能非常强大,下面主要针对 find_all 方法说明。
4.1 过滤器过滤器是使用搜索方法过程中的匹配规则,即参数的可能取值。过滤器可以为下面几种形式:
字符串:find_all(\'div\')
列表:find_all([\'div\', \'span\'])
正则表达式:find_all(re.compile(\'[a-z]{1,3}\'))
True:匹配任意非字符串子节点
方法:相当于匹配的回调函数,该方法返回 True 表示匹配
content = \'<nav><a>a_1</a><a>a_2</a>string</nav>\' soup = BeautifulSoup(content), \'lxml\') nav_node = soup.nav # <nav><a>a_1</a><a>a_2</a>string</nav> nav_node.find_all(True) # 不匹配 string # [\'<a>a_1</a>\', \'<a>a_2</a>\'] def has_class_but_no_id(tag): # 定义匹配函数 return tag.has_attr(\'class\') and not tag.has_attr(\'id\') soup.find_all(has_class_but_no_id) # 返回有class属性没有id属性的节点 4.2 find_all() find() 方法find_all 方法返回匹配搜索的所有节点的列表或者空,而 find 方法直接返回第一个匹配搜索的结果。详细的定义如下:
find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs) find_find(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)各参数含义如下:
name:匹配 tag 标签名
attrs:匹配属性名:find_all(href=\'index.html\')
text:匹配文档中的字符串内容
limit:指定匹配的结果集数量
recursive:默认True,False表示只搜索直接子节点
以上的参数值都可以是 4.1 中说明的任意一种过滤器值。另外还需要注意以下几点:
attrs 参数为字典类型,可以是多个属性条件组合
单独使用 class 属性时,应该使用 class_
class 属性为多值属性,会分别搜索每个 CSS 类名
按照CSS类目完全匹配时,必须顺序相同
# 搜索所有 div 标签 soup.find_all(\'div\') # 搜索所有具有id属性并且id属性值为 link1 或者 link2 的节点 soup.find_all(id=[\'link1\', \'link2\']) # 搜索所有 class 属性包含 button 的节点 soup.find_all(class_=\'button\') # 搜索所有匹配给定正则表达式内容的 p 标签 soup.find_all(\'p\', text=re.compile(\'game\')) # 搜索具有 button 类,并且具有值为 link1 的 href 属性的 a 标签 soup.find_all(\'a\', {\'classl\': \'button\', \'href\': \'link1\'}) # 只搜索一个直接子节点的 a 标签 soup.find_all(\'a\', limit=1, recursive=False) 4.3 其他方法其他的搜索方法参数和 find_all 和 find 类似,它们成对出现,分别返回结果列表和第一个匹配的结果,只是搜索文档的范围不一样,下面列举一些常用的:
find_parents() 和 find_parent():只从当前节点的父节点中搜索
find_next_siblings() 和 find_next_sibling():只从当前节点的后面的兄弟节点搜索
find_previous_siblings() 和 find_previous_sibling():只从当前节点的前面的兄弟节点搜索
find_all_next() 和 find_next():从当前节点之后的节点搜索
find_all_previous() 和 find_previous():从当前节点之前的节点搜索
4.4 CSS选择器Beautiful Soup支持大部分的CSS选择器,使用 select() 方法来搜索。如id选择器,标签选择器,属性选择器设置组合选择器。如:
soup.select(\'body a\')
soup.select(\'#top\')
soup.select(\'div > span\')
soup.select(\'.button + img\')
5. 修改文档树