上面说明的方法findAll
及find
,都是从剖析树的某一点开始并一直往下。
他们反复的遍历对象的contents
直到最低点。
也就是说你不能在 NavigableString
对象上使用这些方法,
因为NavigableString
没有contents:它们是剖析树的叶子。
[这段翻译的不太准确]但是向下搜索不是唯一的遍历剖析树的方法。在Navigating剖析树 中,我们可以使用这些方法:parent
, nextSibling
等。
他们都有2个相应的方法:一个类似findAll
,一个类似find
.
由于NavigableString
对象也支持这些方法,你可以像Tag
一样
使用这些方法。
为什么这个很有用?因为有些时候,你不能使用findAll
或find
从Tag
或NavigableString
获得你想要的。例如,下面的HTML文档:
from BeautifulSoup import BeautifulSoup soup = BeautifulSoup('''<ul> <li>An unrelated list </ul> <h1>Heading</h1> <p>This is <b>the list you want</b>:</p> <ul><li>The data you want</ul>''')
有很多方法去定位到包含特定数据的<LI> 标签。最明显的方式如下:
soup('li', limit=2)[1] # <li>The data you want</li>
显然,这样获得所需的<LI>标签并不稳定。如果,你只分析一次页面,这没什么影响。
但是如果你需要在一段时间分析很多次这个页面,就需要考虑一下这种方法。
If the irrelevant list grows another <LI> tag, you'll get that tag instead of the one you
want, and your script will break or give the wrong data.
因为如果列表发生变化,你可能就得不到你想要的结果。
soup('ul', limit=2)[1].li # <li>The data you want</li>
That's is a little better, because it can survive changes to the
irrelevant list. But if the document grows another irrelevant list at
the top, you'll get the first <LI> tag of that list instead of the one
you want. A more reliable way of referring to the ul tag you want
would better reflect that tag's place in the structure of the
document.
这有一点好处,因为那些不相干的列表的变更生效了。
但是如果文档增长的不相干的列表在顶部,你会获得第一个<LI>标签而不是
你想要的标签。一个更可靠的方式是去引用对应的ul标签,
这样可以更好的处理文档的结构。
在HTML里面,你也许认为你想要的list是<H1>标签下的<UL>标签。
问题是那个标签不是在<H1>下,它只是在它后面。获得<H1>标签很容易,但是获得
<UL>却没法使用first
和fetch
,
因为这些方法只是搜索<H1>标签的contents
。
你需要使用next
或nextSibling
来获得<UL>标签。
s = soup.h1 while getattr(s, 'name', None) != 'ul': s = s.nextSibling s.li # <li>The data you want</li>
或者,你觉得这样也许会比较稳定:
s = soup.find(text='Heading') while getattr(s, 'name', None) != 'ul': s = s.next s.li # <li>The data you want</li>
但是还有很多困难需要你去克服。这里会介绍一下非常有用的方法。
你可以在你需要的使用它们写一些遍历成员的方法。它们以某种方式遍历树,并跟踪那些满足条件的Tag
和NavigableString
对象。代替上面那个例子的第一的循环的代码,你可以这样写:
soup.h1.findNextSibling('ul').li # <li>The data you want</li>
第二循环,你可以这样写:
soup.find(text='Heading').findNext('ul').li # <li>The data you want</li>
这些循环代替调用findNextString
和findNext
。
本节剩下的内容是这种类型所用方法的参考。同时,对于遍历总是有两种方法:
一个是返回list的findAll
,一个是返回单一量的find
。
from BeautifulSoup import BeautifulSoup doc = ['<html><head><title>Page title</title></head>', '<body><p id="firstpara" align="center">This is paragraph <b>one</b>.', '<p id="secondpara" align="blah">This is paragraph <b>two</b>.', '</html>'] soup = BeautifulSoup(''.join(doc)) print soup.prettify() # <html> # <head> # <title> # Page title # </title> # </head> # <body> # <p id="firstpara" align="center"> # This is paragraph # <b> # one # </b> # . # </p> # <p id="secondpara" align="blah"> # This is paragraph # <b> # two # </b> # . # </p> # </body> # </html>
findNextSiblings(name, attrs, text, limit, **kwargs)
findNextSibling(name, attrs, text, **kwargs)
这两个方法以nextSibling
的成员为依据,
获得满足条件的Tag
或NavigableText
对象。
以上面的文档为例:
paraText = soup.find(text='This is paragraph ') paraText.findNextSiblings('b') # [<b>one</b>] paraText.findNextSibling(text = lambda(text): len(text) == 1) # u'.'
findPreviousSiblings(name, attrs, text, limit, **kwargs)
findPreviousSibling(name, attrs, text, **kwargs)
这两个方法以previousSibling
成员为依据,获得满足条件的Tag
和 NavigableText
对象。
以上面的文档为例:
paraText = soup.find(text='.') paraText.findPreviousSiblings('b') # [<b>one</b>] paraText.findPreviousSibling(text = True) # u'This is paragraph '
findAllNext(name, attrs, text, limit, **kwargs)
findNext(name, attrs, text, **kwargs)
这两个方法以next
的成员为依据,
获得满足条件的Tag
和NavigableText
对象。
以上面的文档为例:
pTag = soup.find('p') pTag.findAllNext(text=True) # [u'This is paragraph ', u'one', u'.', u'This is paragraph ', u'two', u'.'] pTag.findNext('p') # <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p> pTag.findNext('b') # <b>one</b>
findAllPrevious(name, attrs, text, limit, **kwargs)
findPrevious(name, attrs, text, **kwargs)
这两方法以previous
的成员依据,
获得满足条件的Tag
和NavigableText
对象。
以上面的文档为例:
lastPTag = soup('p')[-1] lastPTag.findAllPrevious(text=True) # [u'.', u'one', u'This is paragraph ', u'Page title'] # Note the reverse order! lastPTag.findPrevious('p') # <p id="firstpara" align="center">This is paragraph <b>one</b>.</p> lastPTag.findPrevious('b') # <b>one</b>
findParents(name, attrs, limit, **kwargs)
findParent(name, attrs, **kwargs)
这两个方法以parent
成员为依据,
获得满足条件的Tag
和NavigableText
对象。
他们没有text
参数,因为这里的对象的parent不会有NavigableString
。
以上面的文档为例:
bTag = soup.find('b') [tag.name for tag in bTag.findParents()] # [u'p', u'body', u'html', '[document]'] # NOTE: "u'[document]'" means that that the parser object itself matched. bTag.findParent('body').name # u'body'