如何使用BeautifulSoup从HTML段落中提取内容?
我正在使用BeautifulSoup进行网页数据抓取。我的问题是:
<p><b><a href="/name/abe">ABE</a></b> <font class="masc">m</font> <font class="info"><a href="/nmc/eng.php" class="usg">English</a>, <a href="/nmc/jew.php" class="usg">Hebrew</a></font><br />Short form of <a href="/name/abraham" class="nl">ABRAHAM</a>
从这个段落中,我可以提取出名字ABE,方法如下:
for pFound in soup.findAll('p'):
print pFound
#will get the names
x = pFound.find('a').renderContents()
print x
现在我的问题是,如何在同一个段落中提取另一个名字。
Short form of <a href="/name/abraham" class="nl">ABRAHAM</a>
我只想提取当标签a前面有“Short form of”这个文本时的内容。
有没有什么好主意呢?在这个HTML页面中有很多这样的段落,并不是所有的段落都有“Short form of”这个文本,可能会有其他的文本在那个位置。
我觉得结合正则表达式和findNext()可能会有用,但我对BeautifulSoup不太熟悉,浪费了不少时间。
希望能得到一些帮助。谢谢。
2 个回答
0
你可以使用pyparsing这个工具来处理HTML,就像一个“超级正则表达式”。你可以通过组合各种开始和结束的标签来创建一个简单的匹配模式,这样就不会遇到用普通正则表达式抓取HTML时常见的问题,比如标签和属性的字母大小写不一致、属性不确定、属性顺序混乱、空格不规律等。然后,使用pattern.scanString这个方法,它会扫描HTML源代码,并返回匹配到的内容和它们的起始和结束位置。再加上结果命名的功能(类似于正则表达式中的命名字段),这样访问你感兴趣的具体字段就变得很简单了。
html = """<some leading html>
<p><b><a href="/name/abe">ABE</a></b> <font class="masc">m</font>
<font class="info"><a href="/nmc/eng.php" class="usg">English</a>, <a href="/nmc/jew.php" class="usg">
Hebrew</a></font><br />Short form of <a href="/name/abraham" class="nl">ABRAHAM</a>
<some trailing html>"""
from pyparsing import makeHTMLTags, SkipTo, Optional
pTag,pEnd = makeHTMLTags("P")
bTag,bEnd = makeHTMLTags("B")
aTag,aEnd = makeHTMLTags("A")
fontTag,fontEnd = makeHTMLTags("FONT")
brTag = makeHTMLTags("BR")[0]
nbsp = " "
nickEntry = (pTag + bTag + aTag + SkipTo(aEnd)("nickname") + aEnd + bEnd + Optional(nbsp) +
fontTag + SkipTo(fontEnd) + fontEnd + Optional(nbsp) +
fontTag + aTag + SkipTo(aEnd) + aEnd + "," +
aTag + SkipTo(aEnd) + aEnd + fontEnd +
brTag + "Short form of" +
aTag + SkipTo(aEnd)("fullname") + aEnd)
for match,_,_ in nickEntry.scanString(html):
print match.nickname, "->", match.fullname
打印结果:
ABE -> ABRAHAM
1
下面的代码应该可以正常运行...:
htm = '''<p><b><a href="/name/abe">ABE</a></b> <font class="masc">m
</font> <font class="info"><a href="/nmc/eng.php" class="usg">English
</a>, <a href="/nmc/jew.php" class="usg">Hebrew</a></font><br />
Short form of <a href="/name/abraham" class="nl">ABRAHAM</a>'''
import BeautifulSoup
soup = BeautifulSoup.BeautifulSoup(htm)
for p in soup.findAll('p'):
firsta = True
shortf = False
for c in p.recursiveChildGenerator():
if isinstance(c, BeautifulSoup.NavigableString):
if 'Short form of' in str(c):
shortf = True
elif c.name == 'a':
if firsta or shortf:
print c.renderContents()
firsta = shortf = False