1

我正在使用 BeautifulSoup 进行一些屏幕抓取。我的问题是:我需要从段落中提取特定内容。一个例子:

<p><b><a href="/name/abe">ABE</a></b> &nbsp; <font class="masc">m</font> &nbsp; <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。结果浪费了很多时间。

任何帮助,将不胜感激。谢谢。

4

2 回答 2

1

以下应该工作......:

htm = '''<p><b><a href="/name/abe">ABE</a></b> &nbsp; <font class="masc">m
</font>&nbsp; <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
于 2010-07-03T00:57:55.487 回答
0

您可以使用 pyparsing 作为一种“超级正则表达式”来解析 HTML。您可以通过组装各种开始和结束标签来组合一个简单的匹配模式,而不会遇到典型的正则表达式 HTML 抓取陷阱(不可预测的标签/属性字母大小写、不可预测的属性、无序的属性、不可预测的空格)。然后 pattern.scanString 将返回一个生成器,该生成器将扫描 HTML 源并返回匹配标记的元组、开始位置和结束位置。加上结果名称的分配(类似于正则表达式中的命名字段),访问感兴趣的各个字段很简单。

html = """<some leading html>
<p><b><a href="/name/abe">ABE</a></b> &nbsp; <font class="masc">m</font> &nbsp; 
<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 = "&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
于 2010-07-03T02:47:53.537 回答