在嵌套字典中按子字符串查找值

Find a value by substring in a nested dictionary

只是为了给我的问题提供一个上下文:我正在编写一个包含多个应用程序的 Django webapp。其中之一用于显示来自 RSS 提要的文章。现在,我只显示 link、来源和描述。我想为这些文章添加缩略图。 我正在尝试为 any RSS 或 ATOM 提要获取这些缩略图。这些提要是针对以完全任意方式构建的某些部分(例如图像)。因为我不想为 Web 上的每个提要编写特定的脚本,所以我的想法是在我获取的每篇文章中查找“.jpg”、“.png”子字符串并获取 URL。 python Feedparser 模块可以很好地处理从 RSS 或 ATOM 提要到文章的问题,并输出例如:

 {'guidislink': False,
  'href': '',
  'id': 'http://www.bbc.co.uk/sport/football/39426760',
  'link': 'http://www.bbc.co.uk/sport/football/39426760',
  'links': [{'href': 'http://www.bbc.co.uk/sport/football/39426760',
             'rel': 'alternate',
             'type': 'text/html'}],
  'media_thumbnail': [{'height': '576',
                       'url': 'http://c.files.bbci.co.uk/44A9/production/_95477571_joshking2.jpg',
                       'width': '1024'}],
  'published': 'Wed, 05 Apr 2017 21:49:14 GMT',
  'published_parsed': time.struct_time(tm_year=2017, tm_mon=4, tm_mday=5, tm_hour=21, tm_min=49, tm_sec=14, tm_wday=2, tm_yday=95, tm_isdst=0),
  'summary': 'Joshua King scores a dramatic late equaliser for Bournemouth as '
             'Liverpool drop two crucial points at Anfield.',
  'summary_detail': {'base': 'http://feeds.bbci.co.uk/news/rss.xml',
                     'language': None,
                     'type': 'text/html',
                     'value': 'Joshua King scores a dramatic late equaliser '
                              'for Bournemouth as Liverpool drop two crucial '
                              'points at Anfield.'},
  'title': 'Liverpool 2-2 Bournemouth',
  'title_detail': {'base': 'http://feeds.bbci.co.uk/news/rss.xml',
                   'language': None,
                   'type': 'text/plain',
                   'value': 'Liverpool 2-2 Bournemouth'}}

在这里,http://c.files.bbci.co.uk/44A9/production/_95477571_joshking2.jpg 是嵌套在列表和字典中的某个地方。虽然我知道如何在这种特定情况下访问它,但提要的结构差异很大。主要是:

但是,几乎总是这样,带有图像扩展名的 url 是该文章的缩略图。我如何获得 url?

为了进一步构建它,现在我使用辅助函数(基于 Feedparser 模块)来处理 feeds 上下文变量,它是一个字典,可在我的模板中使用。我直接在我的模板中循环和显示标题、描述等,因为由于 feedparser:

,它们始终是该词典的一部分
...
{% for feed in feeds %}
  <h3>{{ feed.feed.title }}</h3>
  {% for entry in feed.entries %}
...

在后端:

def parse_feeds(urls):
    parsed_feeds = []
    for url in urls:
        parsed_feed = feedparser.parse(url)
        parsed_feeds.append(parsed_feed)
    return parsed_feeds

class IndexView(generic.ListView):
    template_name = 'publisher/index.html'

    def get_context_data(self, **kwargs):
        context = super(IndexView,self).get_context_data(**kwargs)
        reacted_feeds = RSSArticle.objects.all()
        context['reacted_feeds'] = reacted_feeds
        parsed_feeds = parse_feeds(urls)
        delete_existing_entries(parsed_feeds)
        context['feeds'] = parsed_feeds
        return context

所以基本上每次您调用 IndexView 时,您都会从您订阅的提要中获得所有文章的列表。这就是我想要包含图像的地方,由于它们在提要中的位置不一致,Feedparser 没有提供这些图像。

如果我要包含这些图片,在宏观层面上我基本上有两个解决方案:

也许我应该只保留原始 XML 并用 Beautifulsoup 试试运气,而不是用 Feedparser 翻译成字典。

PS :这是图像位于其他地方的另一个示例。

{'guidislink': False,
 'id': 'http://www.lemonde.fr/tiny/5106451/',
 'link': 'http://www.lemonde.fr/les-decodeurs/article/2017/04/05/presidentielle-les-grands-clivages-qui-divisent-les-onze-candidats_5106451_4355770.html?xtor=RSS-3208',
 'links': [{'href': 'http://www.lemonde.fr/les-decodeurs/article/2017/04/05/presidentielle-les-grands-clivages-qui-divisent-les-onze-candidats_5106451_4355770.html?xtor=RSS-3208',
            'rel': 'alternate',
            'type': 'text/html'},
           {'href': 'http://s1.lemde.fr/image/2017/04/05/644x322/5106578_3_0f2b_sur-le-plateau-du-debat-de-bfmtv-et-cnews_0e90a3db44861847870cfa1e4c3793b1.jpg',
            'length': '40057',
            'rel': 'enclosure',
            'type': 'image/jpeg'}],
 'published': 'Wed, 05 Apr 2017 17:02:38 +0200',
 'published_parsed': time.struct_time(tm_year=2017, tm_mon=4, tm_mday=5, tm_hour=15, tm_min=2, tm_sec=38, tm_wday=2, tm_yday=95, tm_isdst=0),
 'summary': 'Protection sociale, Europe, identité… Avec leurs programmes, les '
            'proximités idéologiques entre candidats bousculent de plus en '
            'plus le traditionnel axe «\xa0gauche-droite\xa0».',
 'summary_detail': {'base': 'http://www.lemonde.fr/rss/une.xml',
                    'language': None,
                    'type': 'text/html',
                    'value': 'Protection sociale, Europe, identité… Avec leurs '
                             'programmes, les proximités idéologiques entre '
                             'candidats bousculent de plus en plus le '
                             'traditionnel axe «\xa0gauche-droite\xa0».'},
 'title': 'Présidentielle\xa0: les grands clivages qui divisent les onze '
          'candidats',
 'title_detail': {'base': 'http://www.lemonde.fr/rss/une.xml',
                  'language': None,
                  'type': 'text/plain',
                  'value': 'Présidentielle\xa0: les grands clivages qui '
                           'divisent les onze candidats'}}

如果您只需要缩略图,我认为最简单的方法是忽略其他所有内容,并简单地在每个值字符串中搜索所需的尾巴。有很多链接可以帮助您遍历结构,如果您愿意的话,但我会把它变成一个字符串然后解析它。

您的触发器是一个冒号,后跟 white-space 和一个引号。抓住引号之间的内容。调用那个 value

extensions = [".jpg", ".png"]
...
if value[-4:] in extensions:
    # You've found a desired URL

这让你感动吗?

我写了一个基于this snippet的解决方案。

def get_image_url(substring, dictionary):
    for key, value in dictionary.items():
        # try is for handling Booleans
        try:
            if substring in value:
                yield value
            elif isinstance(value, dict):
                for result in get_image_url(substring, value):
                    yield result
            elif isinstance(value, list):
                for list_item in value:
                    for result in get_image_url(substring, list_item):
                        yield result
        except:
            pass

>>> list(get_image_url('.jpg', article_dict))
>>> ['https://static01.nyt.com/images/2017/04/09/us/10OBAMA-alt/10OBAMA-alt-moth.jpg']

PS :虽然它没有回答在嵌套字典中查找值的确切问题,但我发现以一致的方式从 RSS 提要中获取文章图像的好方法很简单按照 URL 返回原始文章,解析 HTML 并搜索 og:image 标签。