关于python:在django中缓存站点地图

Caching sitemaps in django

我使用django的默认站点地图应用程序实现了一个简单的站点地图类。由于执行时间很长,我添加了手动缓存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ShortReviewsSitemap(Sitemap):
    changefreq ="hourly"
    priority = 0.7

    def items(self):
        # try to retrieve from cache
        result = get_cache(CACHE_SITEMAP_SHORT_REVIEWS,"sitemap_short_reviews")
        if result!=None:
            return result

        result = ShortReview.objects.all().order_by("-created_at")

        # store in cache
        set_cache(CACHE_SITEMAP_SHORT_REVIEWS,"sitemap_short_reviews", result)

        return result

    def lastmod(self, obj):
        return obj.updated_at

问题是memcache只允许最大1MB的对象。这个比1MB大,所以存入缓存失败:

1
>7 SERVER_ERROR object too large for cache

问题是django有一种自动的方法来决定何时应该将站点地图文件划分为较小的站点地图文件。根据文档(http://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/):

You should create an index file if one
of your sitemaps has more than 50,000
URLs. In this case, Django will
automatically paginate the sitemap,
and the index will reflect that.

您认为启用缓存站点地图的最佳方式是什么?
- 攻击django sitemaps框架以限制单个站点地图大小,比方说,10,000个记录似乎是最好的主意。为什么首先选择了50,000个?谷歌的建议?随机数?
- 或许有一种方法可以让memcached存储更大的文件?
- 或者也许保存了onces,站点地图应该作为静态文件提供?这意味着不是使用memcached缓存,而是必须手动将结果存储在文件系统中,并在下次请求站点地图时从那里检索它们(可能每天在cron作业中清理目录)。

所有这些看起来都很低,我想知道是否存在明显的解决方案......


50k它不是一个核心参数。 :)

您可以使用此类代替django.contrib.sitemaps.GenericSitemap

1
2
class LimitGenericSitemap(GenericSitemap):
    limit = 2000


您也可以使用gzip格式提供站点地图,这使它们变得更小。 XML非常适合gzip压缩。我有时会这样做:在cronjob中创建gzip压缩的站点地图文件,并根据需要经常渲染它们。通常,每天一次就足够了。这个代码看起来像这样。只需确保从您的域根提供您的sitemap.xml.gz:

1
2
3
4
5
6
7
8
9
10
    from django.contrib.sitemaps import GenericSitemap
    from django.contrib.sitemaps.views import sitemap
    from django.utils.encoding import smart_str
    import gzip
    sitemaps = {
        'page': GenericSitemap({'queryset': MyModel.objects.all().order_by('-created'), 'date_field': 'created'}),
    }
    f = gzip.open(settings.STATIC_ROOT+'/sitemap.xml.gz', 'wb')
    f.write(smart_str(sitemap(request, sitemaps=sitemaps).render().content))
    f.close()

这应该让你开始。


假设您不需要站点地图中的所有这些页面,那么降低限制以获得文件大小将正常工作,如上一个答案中所述。

如果你想要一个非常大的站点地图并且想要使用memcached,你可以将内容分成多个块,将它们存储在单独的键下,然后在输出时再将它们重新组合在一起。为了提高效率,Memcached支持同时获取多个密钥的能力,虽然我不确定django客户端是否支持此功能。

作为参考,1MB限制是memcached的一个功能,它与存储数据的方式有关:http://code.google.com/p/memcached/wiki/FAQ#What_is_the_maximum_data_size_you_can_store?_(1_megabyte)


我的网站上有大约200,000个页面,所以无论如何我都必须拥有索引。我最终做了上述黑客攻击,将站点地图限制为250个链接,并实现了基于文件的缓存。

基本算法是这样的:

  • 尝试从磁盘上的文件加载站点地图
  • 如果失败,请生成站点地图,然后
  • 如果站点地图包含250个链接(上面设置的数字),请将其保存到磁盘然后将其返回。

最终结果是第一次请求站点地图,如果已完成,则生成并保存到磁盘。下次请求它时,它只是从磁盘提供。由于我的内容永远不会改变,因此效果非常好。但是,如果我确实想要更改站点地图,就像从磁盘中删除文件一样简单,并等待爬虫重新生成东西。

如果您有兴趣,整个事情的代码就在这里:http://bitbucket.org/mlissner/legal-current-awareness/src/tip/alert/alertSystem/sitemap.py

也许这对你来说也是一个很好的解决方案。