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

时间:2017-04-05 23:35:41

标签: python parsing dictionary rss atom-feed

只是为我的问题提供一个上下文:我正在编写一个包含多个应用程序的Django webapp。其中一个用于显示来自RSS提要的文章。目前,我只显示链接,来源和说明。我想在这些文章中添加缩略图。 我正在尝试抓取任何 RSS或ATOM Feed的缩略图。这些馈送用于以完全任意方式构造的一些部分(例如图像)。由于我不想为Web上的每个feed编写特定的脚本,我的想法是在我获取的每篇文章中查找“.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嵌套在列表和词典中。虽然我知道在这种特定情况下如何访问它,但是Feed的结构差异很大。主要是:

  • 持有网址的字典键并不总是相同的
  • 网址嵌套的“深度”并不总是相同的

然而,几乎总是这样的情况是带有图像扩展名的网址是该文章的缩略图。我该如何获得该网址?

为了进一步构建它,现在我使用辅助函数(基于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时,都会从您订阅的Feed中获取所有文章的列表。这就是我想要包含图像的地方,Feedparser不提供这些图像,因为它们在Feed中的位置不一致。

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

  • 除了现有系统之外还写一些东西,但由于太多事情必须同时发生,这可能会影响性能
  • 重写整个事情,这可能也会影响性能和一致性,因为我不再利用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'}}

2 个答案:

答案 0 :(得分:0)

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

您的触发器是冒号,后跟空格和引号。抓住引号之间的内容。称之为

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

这会让你感动吗?

答案 1 :(得分:0)

我根据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标记。