Mezzanine で、サイトマップが出力したくなりました。
Robot.txt
の作成&配置- Mezzanine で
Sitemap.xml
の生成 python manage.py ping_google
でGoogle Blog 更新を通知
というところまでやってみましたので、結果を記載します。
環境情報
-
OS
CentOS release 6.7 (Final) -
Python Version
Python 2.7.8 -
Package (必要そうなものだけ抜粋)
Django (1.9.6)
Mezzanine (4.1.0)
1. Robot.txt
の作成&配置
検索したところ、以下のような記事が見つかります。
正直プラグイン入れてまでやるか? というところはありますが、
記事記載の、django-robots 2.0 : Python Package Index をインストール&設定しました。
1.1 pip
でインストール
pip install django-robots
1.2 INSTALLED_APPS
に robots
追加
INSTALLED_APPS = (
"robots",
"request",
"admin_backup",
1.3 TEMPLATES
に django.template.loaders.app_directories.Loader
を追加
TEMPLATES
の、OPTIONS
を loaders
として追加します。
'APP_DIRS': True
は、コメントアウトしないと動作しないようなので、コメントアウトし、
以下のように記載にしました。
# List of callables that know how to import templates from various sources.
TEMPLATES = [{
#u'APP_DIRS': True,
u'BACKEND': u'django.template.backends.django.DjangoTemplates',
u'DIRS': (u'${YOUR_TEMPLATE_DIR}'),
u'OPTIONS': {u'builtins': [u'mezzanine.template.loader_tags'],
u'context_processors': (u'django.contrib.auth.context_processors.auth',
u'django.contrib.messages.context_processors.messages',
u'django.core.context_processors.debug',
u'django.core.context_processors.i18n',
u'django.core.context_processors.static',
u'django.core.context_processors.media',
u'django.core.context_processors.request',
u'django.core.context_processors.tz',
u'mezzanine.conf.context_processors.settings',
u'mezzanine.pages.context_processors.page'),
u'loaders': [
"django.template.loaders.filesystem.Loader",
"django.template.loaders.app_directories.Loader"
]
}
}]
1.4 The “sites” framework
がインストールされていることを確認
Mezzanine を使っていれば、デフォルトでインストールされているはずなので、
OFF にしていない限り確認不要となります。
1.5 マイグレーション
# マイグレーション COMMAND
python manage.py makemigrations
# マイグレーション 実行
python manage.py migrate
1.6 設定
urls.py
に以下の記述を追加する。urlpatterns += [ # add robots.txt URL url(r'^robots\.txt$', include('robots.urls')),
1.7 確認
- 以下、URLにアクセスする。
robots.txt
のURL
http://www.monotalk.xyz/robots.txt
上記URLにアクセスして出力される。 robots.txt
User-agent: *
Allow: /
Host: www.monotalk.xyz
Sitemap: http://www.monotalk.xyz/sitemap.xml
robots.txt
が出力されていることを確認できたので、一旦これで OK とします。
出力内容がセキュリティとして微妙な気がしますので、
そのあたりの調整は別途、行う必要がありそうです。
2. Mezzanine で Sitemap.xml
の生成
- 参考サイト 一般的なサイトマップの説明 全然知らなかったです..
2.1 Mezzanine のデフォルト動作について
Mezzanine はデフォルトでSitemap.xml
が出力されます。
${YOUR_DOMAIN}/sitemap.xml
でアクセスすると以下のようなSitemap.xmlが出力されます。
ですので、出力内容を変えたいという場合以外、特に何もしないでOKです。
- Sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<script/>
<url>
<loc>
${YOUR_DOMAIN}/blog/at-comfasterxmljacksondatabindexcunrecognizedpropertyexceptionfromunrecognizedpropertyexceptionjava51/
</loc>
<lastmod>2016-03-20</lastmod>
</url>
<url>
<loc>
${YOUR_DOMAIN}/blog/no-module-named-djangoutilslognullhandler-djangoutilslog-is-not-a-package/
</loc>
<lastmod>2016-01-11</lastmod>
</url>
<url>
<loc>
${YOUR_DOMAIN}/blog/javalangillegalargumentexception-invalid-bson-field-name-javaruntimename/
</loc>
<lastmod>2016-01-11</lastmod>
</url>
<url>
<loc>${YOUR_DOMAIN}/about/</loc>
</url>
<url>
<loc>${YOUR_DOMAIN}/blog/</loc>
</url>
<url>
<loc>
${YOUR_DOMAIN}/blog/uses-a-non-entity-orgeclipsepersistenceexceptionsvalidationexception/
</loc>
<lastmod>2016-01-14</lastmod>
</url>
<url>
<loc>
${YOUR_DOMAIN}/blog/gradle-could-not-find-method-provided-for-arguments/
</loc>
<lastmod>2016-03-14</lastmod>
</url>
<url>
<loc>${YOUR_DOMAIN}/blog/mezzanine-pagedown/</loc>
<lastmod>2016-01-11</lastmod>
</url>
</urlset>
</xml>
2.2 Mezzanine (4.1.0)
の不具合
Python 2.7.8
環境下においては、Mezzanine (4.1.0)
はバグがあるようで、
以下、エラーが発生し、対象のファイルにパッチをあてないとSitemap.xml
が出力されませんでした。
Python 3
でも発生するかもしれませんが、試してはいないため不明です。
- エラー内容
TypeError at /sitemap.xml
isinstance() arg 2 must be a class, type, or tuple of classes and types
Request Method: GET
Request URL: http://www.monotalk.xyz/sitemap.xml
Django Version: 1.9.6
Exception Type: TypeError
Exception Value:
isinstance() arg 2 must be a class, type, or tuple of classes and types
Exception Location: /usr/local/lib/python2.7/site-packages/django/db/models/fields/related.py in get_default, line 905
Python Executable: /usr/bin/python
Python Version: 2.7.8
Python Path:
以下のパッチをあてることで解消しました。
Mezzanine の次のVersionで改修されるようです。
-
参考サイト
-
修正記述
# DEL
#home = self.model(title=_("Home"))
# ADD
class Home:
title = _("Home")
home = Home()
#----
setattr(home, "get_absolute_url", home_slug)
items = {home.get_absolute_url(): home}
3. python manage.py ping_google
でGoogle に Blog 更新を通知する。
Sitemap.xml
の出力に使用している。The sitemap framework | Django documentation | Djangoは、
ping_google
という、管理コマンドがあり、Google に Blog の ping 送信が行えます。
この管理コマンドは、google以外にも更新通知を送れるようなので、
別途管理コマンドを作成して、複数のサイトに更新通知を送るようにします。
3.1 Mezzanine のPROJECT_APP
ディレクトリ配下に、管理コマンドディレクトリを作成する。
- Applicationを作成
cd ${PROJECT_ROOT}
python manage.py startapp jobs
- 管理コマンドディレクトリを作成
cd jobs
mkdir ./management
touch ./management/__init__.py
mkdir ./management/commands
touch ./management/commands/__init__.py
touch ./management/commands/ping_all_search_engines.py
3.2 settings.py
のINSTALL_APPS
にjobs
を追加する
INSTALLED_APPS = (
"jobs",
"robots",
"request",
3.3 ping_all_search_engines.py
を作成する。
-
参考サイト
-
ping_all_search_engines.py (Django 1.8 で動作する)
以下の内容で作成しました。 pingサーバーを参考サイトを元に記述してみましたが、RPC形式じゃないので、通信失敗します.. また、後日 Django 1.10 に Upgrade したら、django ImportError: cannot import name NoArgsCommand | Monotalk が原因で動作しなくなり、実装を修正しています。
# -*- coding: utf-8 -*- from django.core.management.base import NoArgsCommand class Command(NoArgsCommand): def handle_noargs(self, **options): print "--------------------------------------------" print "ping_all_search_engines START" print "-------------------------" """ Pings the popular search engines, Google, Yahoo, ASK, and Windows Live, to let them know that you have updated your site's sitemap. Returns successfully pinged servers. """ from django.contrib.sitemaps import ping_google SEARCH_ENGINE_PING_URLS = ( ('google', 'http://www.google.com/webmasters/tools/ping'), ('live', 'http://webmaster.live.com/ping.aspx'), ) successfully_pinged = [] failure_pinged = [] sitemap_url = "http://www.monotalk.xyz/sitemap.xml" for (site, url) in SEARCH_ENGINE_PING_URLS: try: ping_google(sitemap_url=sitemap_url, ping_url=url) successfully_pinged.append(site) except: failure_pinged.append(site) print "--------------------------------------------" print "ping_all_search_engines END" print "successfully_pinged >>>" print successfully_pinged print "failure_pinged >>>" print failure_pinged print "-------------------------"
-
ping_all_search_engines.py (Django 1.10 で動作する)
Django 1.10 にUpgrade したところ動作しなくなり、且つログをちゃんと出力するため、
printをloggerに書き換えました。
# -*- coding: utf-8 -*- from django.core.management.base import BaseCommand from logging import getLogger logger = getLogger(__name__) class Command(BaseCommand): def handle(self, *args, **options): logger.info("ping_all_search_engines START") """ Pings the popular search engines, Google, Yahoo, ASK, and Windows Live, to let them know that you have updated your site's sitemap. Returns successfully pinged servers. """ from django.contrib.sitemaps import ping_google SEARCH_ENGINE_PING_URLS = ( ('google', 'http://www.google.com/webmasters/tools/ping'), ('live', 'http://webmaster.live.com/ping.aspx'), ('goo', 'http://blog.goo.ne.jp/XMLRPC'), ('with2', 'http://blog.with2.net/ping.php'), ('google_blog_search_co_jp', 'http://blogsearch.google.co.jp/ping/RPC2'), ('google_blog_search_com', 'http://blogsearch.google.com/ping/RPC2'), ('blo', 'http://ping.blo.gs/'), ('blogmura', 'http://ping.blogmura.com/xmlrpc/hidmbp2r256f'), ('blogranking', 'http://ping.blogranking.net'), ('cocolog-nifty', 'http://ping.cocolog-nifty.com/xmlrpc'), ('dendou', 'http://ping.dendou.jp'), ('fc2', 'http://ping.fc2.com'), ('feedburner', 'http://ping.feedburner.com'), ('freeblogranking', 'http://ping.freeblogranking.com/xmlrpc'), ('drecom', 'http://ping.rss.drecom.jp'), ('sitecms', 'http://ping.sitecms.net'), ('pingoo', 'http://pingoo.jp/ping'), ('kuruten', 'http://ranking.kuruten.jp/ping'), ('pingomatic', 'http://rpc.pingomatic.com'), ('livedoor', 'http://rpc.reader.livedoor.com/ping'), ('weblogs', 'http://rpc.weblogs.com/RPC2'), ('serenebach', 'http://serenebach.net/rep.cgi'), ('newsgator', 'http://services.newsgator.com/ngws/xmlrpcping.aspx'), ('taichistereo', 'http://taichistereo.net/xmlrpc'), ('sourceforge', 'http://wpdocs.sourceforge.jp/Update_Services'), ('blogpeople', 'http://www.blogpeople.net/ping'), ('blogpeople_servlet', 'http://www.blogpeople.net/servlet/weblogUpdates'), ('blogstyle', 'http://www.blogstyle.jp'), ('i-learn', 'http://www.i-learn.jp/ping'), ('pubsub', 'http://xping.pubsub.com/ping'), ) SITEMAP_URLS = ( "https://www.monotalk.xyz/sitemap.xml", "https://www.monotalk.xyz/blog/feeds/rss", "https://www.monotalk.xyz/blog/feeds/atom", ) successfully_pinged = {} failure_pinged = {} for elem_url in SITEMAP_URLS: for (site, url) in SEARCH_ENGINE_PING_URLS: try: ping_google(sitemap_url=elem_url, ping_url=url) values = successfully_pinged.get(elem_url, None) if values is None: values = [] values.append(site) successfully_pinged.update({elem_url:values}) except: fail_values = failure_pinged.get(elem_url, None) if fail_values is None: fail_values = [] fail_values.append(site) failure_pinged.update({elem_url:fail_values}) import pprint logger.info("ping_all_search_engines END") logger.info("successfully_pinged >>>" + pprint.pformat(successfully_pinged, indent=4)) logger.info("failure_pinged >>>" + pprint.pformat(failure_pinged, indent=2))
3.4 crontab
で実行可能にする。
あとは、1日1回くらい実行されるようにcron
を設定しておきます。
signal
を使用して、Blog 記事更新時に更新通知ができるとかっこいいと思いましたが、
それはまた別の機会に試してみようと思います。
- 追記
django plugin の django-crontab で後日設定を行いました。
Mezzanine django-crontab をインストールしてジョブスケジュールをしてみる | Monotalk
以上です。
コメント