Skip to content

ねたみまん

Webサイト運営の裏側で必要な技術、テクニック、マーケティング、考え方などのメモを記事にしたサイトです

Archive

Category: ツール

SEOの考え方は色々あると思います。

基本は、
・訪れるユーザーにとって良質の情報を提供する

ことだと思いますが、

  • キーワードに対して、どのようなライバルサイトがあって、それらがどんなバックリンクを持っているのか?
  • 関連キーワードにはどういうものがあって、関連キーワードを使ったライバルサイトのSEO情報はどうなのか?

などは金力になる情報じゃないかと思います。

全てを自動で調査できる超強力ツールが無料

バックリンクコレクター

バックリンクコレクター 自動でライバルサイトをチェックできる

バックリンクコレクターというこのツール。
競争の激しいキーワードでライバルサイトの弱いキーワードを探したり、よりニッチなキーワードを探したりするのに向いていると思います。

この強力なツール、実は14800円で発売されるはずでした。

しかし、Yahoo!の検索エンジンがGoogleに変更されるため、利用できる保証が12月までしかないそうです。

なので、急遽無料で配られることになりました。

今のうちにライバルサイトをチェックしたい方、

とくにアフィリエイターや競争の激しい物販サイトなどを展開している方なんかは利用してみる価値があると思います。

>>お申し込みは今すぐココをクリック <<

AdWordsをオフラインで管理できるソフト AdWords Editor

AdWordsをオフラインで管理できるソフト AdWords Editor の管理画面

AdWordsをデスクトップで管理するソフトがありました。
しかも、本家Google製。
そのソフトの名は AdWords Editor .
AdWordsに関しては最近きっちり勉強し始めたところなので、こんなソフトがあるとは全く知りませんでした。

AdWords Editorを使う利点

AdWords Editorを使う利点は以下です。

  • オフラインで作業でき、いつでも変更内容をアップロードできる
  • ほんの数ステップで単価の更新やキーワードの追加などの一括変更が出来る
  • 広告グループ、キャンペーン間でキーワード、原稿などの設定内容をコピー、移動できる
  • アカウントをすばやく切り替えられる
  • 他のユーザーから提案された変更内容を回覧したり意見交換できる

まだ使い始めたばかりなので、使い方自体を勉強していかなければいけないのですが、
かなり便利良さそうです。

AdWords Editor のダウンロード先

AdWords Editor は、こちらからダウンロードできます。
http://www.google.com/intl/ja/adwordseditor/

現在の最新バージョンは 7.6.1 です.

Windows版とMac版があるので、Macな方でも安心ですね。

Djangoで顧客管理システムを作るテストをするのに、ダミーの顧客情報を作る方法を以前紹介した。
個人情報のダミーデータを作ってくれるサイト

そこで作ったダミーの顧客データをDjangoに入力するのに、どのようにしたらいいのか調べてみると・・・
manage.pyにloaddata というFixtureを入力するコマンドがあることを知った。

> manage.py loaddata data.json

Fixture は XML, JSON, YAML形式で書いていたらOKらしい。
manage.py dumpdata appname
で出力したデータがそのままFixtureに使えるそうなので、それを参考にCSVファイルからJSON形式のFixtureを作るスクリプトを作ってみた。

JSON形式のFixtueの構造

まず始めにJSON形式のFixtureの構造は以下のようになっている。

[
    {"pk": 1,
     "model": "customer.item",
     "fields":
        {"category": "\u30af\u30ed\u30b9",
         "code": "a-silvercloth",
         "name": "\u9280\u307f\u304c\u304d\u30af\u30ed\u30b9\uff082\u679a\u5165\uff09",
         "price": "525",
         "memo": "\u9280\u78e8\u304d\u30af\u30ed\u30b9\u30022\u679a\u5165\u308a\u3002",
         "unit": "\u500b"}
     },
     {"pk": 2,
      "model": "customer.item",
      "fields":
          {"category": "\u30d0\u30f3\u30b0\u30eb",
           "code": "ba-ki-l0001",
           "name": "\u30ec\u30c7\u30a3\u30b9\u30d0\u30f3\u30b0\u30eb\u3000\u300e\u83ca\u6c34\u300f",
           "price": "70350",
           "memo": "",
           "unit": "\u500b"}
     }
]

Objectで書かれた各データの配列になっていて、各データのObjectは
pk — PrimaryKeyの値
model — Djangoのモデル名 アプリ名.モデルクラス名 の形式で表記
fields — 各フィールドのフィールド名と値のObject

となっている。
ちなみにJSONの構文は以下のページを見れば良く分かる。
JSONの紹介

手書きでも書けるので、初期データを放り込むのにカンタンなものなら手書きで書いてもいいんだけど、顧客ダミーデータは5000件あるのでそれを手書きで変換するのはめんどくさい。

そこで、カンタンに変換できるツールを作ってみた。

CSVデータをJSONのFixtureに変換するツール(Pythonスクリプト)

ツールの構成は
1.変換用スクリプト make_fixture.py
2.変換設定ファイル(JSON形式)
からなっていて、コマンドラインで利用する。

使い方は、変換設定ファイルを書いて、コマンドラインから
make_fixture.py -s 設定ファイル -i 変換元CSVファイル -o 変換後の出力ファイル
とするだけ。
各ファイルはUTF-8で使うことを前提にしている(UTF-8でしかテストしていない)

例として前回作ったダミーの顧客情報を変換する設定ファイルを載せてみる。

変換元のCSVデータはこんな感じ

姓,名,姓(カタカナ),名(カタカナ),性別,電話番号,携帯電話,メールアドレス,郵便番号,住所,,,,,生年月日,年齢
早川,順,ハヤカワ,ジュン,M,03-0043-5967,080-1129-0749,srkpfajun112@ftapigbq.uh,229-0032,神奈川県,相模原市,矢部,2-8,グランド矢部403,1980/03/09,29
都築,武雄,ツズキ,タケオ,M,03-8521-5608,080-4747-0980,takeotsuzuki@cukt.npkbr.fi,393-0046,長野県,諏訪郡下諏訪町,東赤砂,4-5-15,,1988/05/27,21
内藤,果歩,ナイトウ,カホ,F,03-7080-8426,090-0443-2574,jyqydqafb-kaho64604@pljimta.qc,794-0015,愛媛県,今治市,常盤町,1-3-18,,1979/07/05,30
岩永,紅葉,イワナガ,クレハ,F,03-7063-2531,080-1587-4004,dyjkpsnkureha28732@yoiyr.ks,382-0806,長野県,上高井郡高山村,なかひら,3-11-16,,1944/03/13,65
永野,志保,ナガノ,シホ,F,03-7739-4442,,shiho5190@voyifkg.pd,297-0075,千葉県,茂原市,押日,2-11-11,,1944/08/21,65

※これは、完全にダミーのデータなのでこの世に存在しない人の情報ですが、偶然にも存在してしまった場合はごめんなさい。

この、CSVデータをDjangoの以下のモデル用のFixtureに変換する。

class Customer(models.Model):
    SEX_CHOICES = (
        ('M', u'男性'),
        ('F', u'女性'),
    )
    AGE_CHOICES = (
        ('-', u'---'),
        ('-20', u'20最未満'),
        ('20-29', u'20歳-29歳'),
        ('30-39', u'30歳-39歳'),
        ('40-49', u'40歳-49歳'),
        ('50-',   u'50歳以上'),
    )
    JOB_CHOICES = (
        ('-', u'---'),
        (u'会社員', u'会社員'),
        (u'自営業', u'自営業'),
        (u'公務員', u'公務員'),
        (u'団体職員', u'団体職員'),
        (u'主婦', u'主婦'),
        (u'学生', u'学生'),
        (u'その他', u'その他'),
    )
    sei     = models.CharField(u'姓', max_length=100)
    mei     = models.CharField(u'名', max_length=100)
    kanasei = models.CharField(u'かな姓', max_length=100)
    kanamei = models.CharField(u'かな名', max_length=100)
    zip     = models.CharField(u'郵便番号', max_length=10)
    pref    = models.CharField(u'都道府県', max_length=20)
    add1    = models.CharField(u'住所1', max_length=256)
    add2    = models.CharField(u'住所2', max_length=256, blank=True)
    tel1    = models.CharField(u'TEL1', max_length= 20)
    tel1_is_mobile = models.BooleanField(u'TEL1は携帯電話', default= False)
    tel2    = models.CharField(u'TEL2', max_length = 20, blank=True)
    tel2_is_mobile = models.BooleanField(u'TEL2は携帯電話', default= False)
    fax     = models.CharField(u'FAX', max_length = 20, blank=True)
    email1  = models.CharField(u'email1', max_length=100)
    email1_is_mobile = models.BooleanField(u'email1は携帯メール', default= False)
    email2  = models.CharField(u'email2', max_length=100, blank=True)
    email2_is_mobile = models.BooleanField(u'email2は携帯メール', default= False)
    is_inform = models.BooleanField(u'お知らせメール許可', default=True)
    sex  = models.CharField(u'性別', max_length=1, choices=SEX_CHOICES)
    birthday = models.DateField(u'生年月日', null=True, blank=True)
    age  = models.IntegerField(u'年齢', null=True, blank=True)
    ages = models.CharField(u'年代', max_length=10, choices=AGE_CHOICES, blank=True)
    jobclass = models.CharField(u'職業区分', max_length=20, choices=JOB_CHOICES)
    occupation = models.CharField(u'職業', max_length=100, blank=True)
    first_contact = models.DateField(u'初回接触', null=True, blank=True)
    first_buy = models.DateField(u'初回購入日', null=True, blank=True)

モデルと元データを比べてみたら分かると思うが、元データにはモデルの全てのフィールドが定義されているわけではなく、また、
元データのフィールドの値を加工しなければモデルの合わないデータも存在する。

住所の項目などでは、CSVのいくつかのフィールドを結合しなければモデルの住所データに合わないし、
誕生日の日付の形式はPythonで使っているyyyy-mm-dd 形式に変換しなければいけない。
(Python側で日付のフォーマット形式を変更することも出来そうだけど、今回はデータを変換して使う)
また、携帯電話項目には tel2_is_mobile を常に True としたデータを作りたい。

ということで、以下のような設定ファイルで、モデルにあるJSON形式のFixtureを作れるようにした。

{"model": "customer.customer",
 "header": true,
 "fields": [{"field": "sei",     "col": [0]},
            {"field": "mei",     "col": [1]},
            {"field": "kanasei", "col": [2]},
            {"field": "kanamei", "col": [3]},
            {"field": "sex" ,    "col": [4]},
            {"field": "tel1",    "col": [5]},
            {"field": "tel2",    "col": [6]},
            {"field": "tel2_is_mobile", "static": true},
            {"field": "email1",  "col": [7]},
            {"field": "zip",     "col": [8]},
            {"field": "pref",    "col": [9]},
            {"field": "add1",    "col": [10, 11, 12]},
            {"field": "add2",    "col": [13]},
            {"field": "is_inform", "static": true},
            {"field": "birthday", "col": [14], "replace": ["/", "-"]},
            {"field": "age",      "col": [15]}
           ]
}

設定の意味は以下の通り
model — Djangoのモデル名 アプリ名.モデルクラス名 を小文字で
header — CSVファイルにヘッダー行があるか? ある場合(1行目がデータでない場合) true
fields — データのフィールドの定義をObjectの配列で設定
—- fields 内の意味 —-
ひとつのフィールドはひとつのObject
field — モデルのフィールド名 Django のモデルのフィールド名
col — CSVの何カラム目を当てはめるのかの配列
複数のカラムを指定するとそれらを結合したものをそのフィールドのデータとする
例 {“field”: “add1″, “col”: [10, 11, 12]}
CSVの10カラム目、11カラム目、12カラム目を結合したデータをadd1に入力する。
static — 常に一定のデータを入力したいときに利用
例 {“field”: “is_inform”, “static”: true}
is_inform は常にTrueを入力する。
replace — CSVのカラム内のデータの一部を置換したデータにして入力する
例  {“field”: “birthday”, “col”: [14], “replace”: ["/", "-"]}
birthday フィールドにはCSVの14カラム目のデータの / を - に置換して入力
2010/02/12 を 2010-02-12 に変換する
replace は re.subを使っているので、正規表現が使える(と思う)
select — 選択データを入力する
例  {“field”: “is_inform”, “col”: [16], “select”: {“Y”: true, “N”: false}}
is_inform にはCSVの16カラム目のデータがYの場合は True、 Nの場合はFalseを入力する。

上のデータを変換するとこんな感じになる。

[{"pk": 1, "model": "customer.customer", "fields": {"tel1": "03-0043-5967", "is_inform": true, "add2": "\u30b0\u30e9\u30f3\u30c9\u77e2\u90e8403", "add1": "\u76f8\u6a21\u539f\u5e02\u77e2\u90e82-8", "zip": "229-0032", "age": "29", "pref": "\u795e\u5948\u5ddd\u770c", "mei": "\u9806", "kanamei": "\u30b8\u30e5\u30f3", "birthday": "1980-03-09", "sex": "M", "tel2": "080-1129-0749", "kanasei": "\u30cf\u30e4\u30ab\u30ef", "tel2_is_mobile": true, "sei": "\u65e9\u5ddd", "email1": "srkpfajun112@ftapigbq.uh"}}, {"pk": 2, "model": "customer.customer", "fields": {"tel1": "03-8521-5608", "is_inform": true, "add2": "", "add1": "\u8acf\u8a2a\u90e1\u4e0b\u8acf\u8a2a\u753a\u6771\u8d64\u78024-5-15", "zip": "393-0046", "age": "21", "pref": "\u9577\u91ce\u770c", "mei": "\u6b66\u96c4", "kanamei": "\u30bf\u30b1\u30aa", "birthday": "1988-05-27", "sex": "M", "tel2": "080-4747-0980", "kanasei": "\u30c4\u30ba\u30ad", "tel2_is_mobile": true, "sei": "\u90fd\u7bc9", "email1": "takeotsuzuki@cukt.npkbr.fi"}}, {"pk": 3, 以下省略

さて、肝心のツールのコードは以下

<追記 2010/02/13>

以前のコードでUTF-8回りでうまく動かないところがあった(select がうまく動いていなかった)ので、修正したソースに変更。
追加機能として

type -- 数値型の型指定をする場合に使う。type指定していない場合は文字列としてデータを扱う。
例 {"field": "price",    "col": [2], "type": "integer"}
priceフィールドには2番目のカラムのデータをinteger型で入力。
型指定は現在のところ integer とfloat だけ存在している。

< 追記 2010/02/15 >
余計なデバッグ用print文があったので削除。

make_fixture.py

# -*- coding: utf-8 -*-

import csv
import cStringIO
import json
import codecs
import re
import sys
from optparse import OptionParser

# PythonのリファレンスマニュアルよりUnicode対応csv.reader csv.writerラッパークラス
# http://pythonjp.sourceforge.jp/dev/library/csv.html#csv-examples
class UTF8Recoder:
    """
    Iterator that reads an encoded stream and reencodes the input to UTF-8
    """
    def __init__(self, f, encoding):
        self.reader = codecs.getreader(encoding)(f)

    def __iter__(self):
        return self

    def next(self):
        return self.reader.next().encode("utf-8")

class UnicodeReader:
    """
    A CSV reader which will iterate over lines in the CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        f = UTF8Recoder(f, encoding)
        self.reader = csv.reader(f, dialect=dialect, **kwds)

    def next(self):
        row = self.reader.next()
        return [unicode(s, "utf-8") for s in row]

    def __iter__(self):
        return self

class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)

# CSVをDjango用のFixtureに変換するクラス
class CSV2Fixture:
    def __init__(self, settingf, inputf, outputf):
        self.setting_file = settingf
        self.data_file = inputf
        self.fixture = outputf
        self.setting = json.load(open(self.setting_file, 'r'))
        self.csvdata = UnicodeReader(open(self.data_file, 'r'))
        self.data = []
        self.model_name = self.setting['model']
        self.index = 1

    def load_one_line(self, line):
        fields = {}
        for field in self.setting['fields']:
            fieldname = field['field']
            data = ''
            #-- カラムからデータを取り出す場合
            try:
                if field['col']:
                    for col in field['col']:
                        data += line[col]
                    try:
                        #-- 選択値データの場合 --
                        if field['select']:
                            data = field['select'][data]
                    except KeyError:
                        pass

                    try:
                        #-- データの変換がある場合 --
                        if field['replace']:
                            data = re.sub(field['replace'][0], field['replace'][1], data)
                    except KeyError:
                        pass

                    try:
                        #-- データが数値の場合 --
                        if field['type']:
                            if field['type'] == 'integer':
                                data = int(data)
                            elif field['type'] == 'float':
                                data = float(data)
                    except KeyError:
                        pass
            except:
                pass

            #-- 固定値データの場合 --
            try:
                if field['static']:
                    data = field['static']
            except:
                pass

            fields[fieldname] = data
        return fields

    def execute(self):
        #ヘッダー処理 settingファイル内で "header": true の場合、1行目をフィールド名とみなして1行目を取り込まない
        try:
            if self.setting['header']:
                self.csvdata.next()
        except:
            pass

        #データの処理
        for line in self.csvdata:
            a=self.load_one_line(line)
            if 'pk' in a:
                self.data.append({'model': self.model_name,
                                  'fields': a})
            else:
                self.data.append({'pk': self.index,
                                  'model': self.model_name,
                                  'fields': a})
            self.index += 1

        json_data = json.JSONEncoder().encode(self.data)
        outf = codecs.open(self.fixture, 'w', encoding='utf-8')
        outf.write(json_data)
        outf.close()

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option("-s", "--setting", dest="settingfile", default="setting.json", help="Setting File (JSON)")
    parser.add_option("-i", "--input", dest="inputfile", default="input.csv", help="Input File (CSV)")
    parser.add_option("-o", "--output", dest="outputfile", default="output.json", help="Output File (JSON): This file is Fixture for Django apprication model.")

    (options, args) = parser.parse_args(sys.argv)
    x = CSV2Fixture(options.settingfile, options.inputfile, options.outputfile)
    x.execute()

カンタンなコードの割にはかなり便利である。
よければ自由に使ってみてください。
もう少し発展させて、リレーションのあるモデル用のCSV-JSON Fixtureの変換も出来るようにしたいところです。

色々と環境が整ってきたので、ここらでバージョン管理システムを入れてみようと思う。

色々あるが、分散管理できて最近主流になりつつあるGitにすることにした。

昨年あたりからWindows環境でもGitがちゃんと使えるようになっている・・・らしいからだ。

ということで、導入は以下のサイトを参考にしてみた。

komicomi開発ブログ windows環境でのgitの使い方(下準備編)

ちょっと変わっているとこがあるので、後でまとめてみたいと思うが、とりあえずメモ。

Blog WebMastered by All in One Webmaster.