美丽的汤/正则表达式:从NavigableString中提取一部分文本

时间:2017-03-11 14:30:52

标签: python regex python-3.x beautifulsoup

我是学习python的新手,所以这可能非常明显,但我从BeautifulSoup中提取了一个NavigableString,我需要在字符串中查找数据。但是,它并不像我在网上看到的一些例子那么容易。

我的最终目标是创建一个如下所示的字典:

dict = {'Fandom':'Undertale (Video Game)', 'Works':15341}

以下是两个字符串示例:

<li>
<a class="tag" href="/tags/Undertale%20(Video%20Game)/works">Undertale (Video Game)</a>
          (15341)
      </li>

<a class="tag" href="/tags/Sherlock%20Holmes%20*a*%20Related%20Fandoms/works">Sherlock Holmes &amp; Related Fandoms</a>
          (101015)
      </li>

我已经成功地从字符串中提取了粉丝,但现在我需要括号中的工作计数。我如何使用Beautiful Soup和/或Regular Expressions来做到这一点?

我还需要进行错误处理,因为虽然会一直显示一个粉丝,但它旁边可能没有工作计数。

<li>
<a class="tag" href="/tags/Composer%20-%20Fandom/works">Composer - Fandom</a>
</li>

以下是相关的代码:

        for each_f in cate:
            #print(each_f)
            result = each_f.find('a')
            if result !=-1:
                #here is where I grab the Fandom vals
                fandom_name = result.contents
                #print(result.contents)

注意:我知道我错过了附加到字典的代码,我还没有做到那么远。我只是想把值打印到屏幕上。

2 个答案:

答案 0 :(得分:0)

您可以使用stripped_strings并解压缩值以获取文本块。您可以将结果存储在dict中,以便以后可以使用它们。

示例:

from bs4 import BeautifulSoup
import requests


example = """<li>
<a class="tag" href="/tags/Undertale%20(Video%20Game)/works">Undertale (Video Game)</a>
      (15341)
  </li>

<li><a class="tag"     href="/tags/Sherlock%20Holmes%20*a*%20Related%20Fandoms/works">Sherlock Holmes &amp; Related Fandoms</a>
      (101015)
  </li>
  <li>
<a class="tag" href="/tags/Composer%20-%20Fandom/works">Composer - Fandom</a>
</li>"""

soup = BeautifulSoup(example, "html.parser")
Fandom = {"Fandom" : []}

for li in soup.find_all("li"):
    try:
        fandom, count = li.stripped_strings
        Fandom["Fandom"].append({fandom.strip() : count[1:-1]})
    except:
        fandom = li.text.strip()
        Fandom["Fandom"].append({fandom.strip() : 0})

print (Fandom)

输出:

  

{'Fandom':[{'Undertale(电子游戏)':'15341'},{'Sherlock Holmes&amp;相关的粉丝':'101015'},{'作曲家 - 粉丝':0}]}

try-catch将捕获任何不包含两个值的解包:你的粉丝标题和字数。

答案 1 :(得分:0)

使用dict.fromkeys(('Fandom', 'Works'))获取:

In [17]: dict.fromkeys(('Fandom', 'Works'))
Out[17]: {'Fandom': None, 'Works': None}

使用zip将密钥与li标记中的字符串组合在一起,这只会结​​合最短的内容:

zip(('Fandom', 'Works'),li.stripped_strings)

[('Fandom', 'Undertale (Video Game)'), ('Works', '(15341)')]
[('Fandom', 'Sherlock Holmes & Related Fandoms'), ('Works', '(101015)')]
[('Fandom', 'Composer - Fandom')]

然后我们用这些数据更新dict

In [20]: for li in soup.find_all('li'):
    ...:     d = dict.fromkeys(('Fandom', 'Works'))
    ...:     out = zip(('Fandom', 'Works'),li.stripped_strings)
    ...:     d.update(out)
    ...:     print(d)

出:

{'Works': '(15341)', 'Fandom': 'Undertale (Video Game)'}
{'Works': '(101015)', 'Fandom': 'Sherlock Holmes & Related Fandoms'}
{'Works': None, 'Fandom': 'Composer - Fandom'}