おすすめ投稿

本ブログの更新を終了します

掲題のとおり, 本ブログの更新は終了します。

今後は http://www.e2esound.com/tech/ として技術ブログを始めます。このブログは WordPress で運用されてきましたが, 次のブログは Middleman の blog 機能を採用しています。

尚、過去に書いた記事のデータは当面残る予定です。

追記: 2017/09/10

法人化した影響で個人事業であった e2esound.com の技術ブログは更新を停止しています。現在は https://issueoverflow.com で個人的なブログを書いています。

2015年まとめ

例年あまり年間のまとめをしていないのですが, 大晦日の今日少し時間ができたので取り組んだこと, どういった仕事をしていたかとか諸々をざっくりとまとめたいと思います。

続きを読む

Middleman v4 がリリースされました

先日不意にリリースされた v4 ですが, ドキュメント日本語版の更新が完了しドキュメントページに反映されています。個人的に重要だと思う点をまとめてみます。

https://middlemanapp.com/jp/

手をつける前に読むべきもの

Middleman ガイドのドキュメントに V4 アップグレードのドキュメントと, Middleman の開発リポジトリに CHANGELOG (英語) があります。

プレビューサーバ (middleman server) で SSL が使えるようになったりしているんですが記述がないことに気づきました。いくつかオプションがあるんですが簡単に使うには次のコマンドで動きます。

$ middleman server --https

細かいところではテンプレートや config.rb で使用していた page (カレントページを表す) は削除され current_resource を使うことようになりました。

v4-beta から使っていたのであまり何が変わったのか他には思い出せないので何か見つけた人はまとめてくれると助かります。

続きを読む

最近ひっそりと公開した golang のパッケージ 2 つ

最近ひっそりと公開した golang のパッケージ 2 つ

疲れ果てて早い時間に寝落ちし変な時間に起きて暇なので, 最近ひっそりと公開した Go 言語のパッケージを 2 つ紹介だけしておこう思います。

go-webpage

https://github.com/yterajima/go-webpage

goquery の Web サイトのページ用エイリアスパッケージ。goquery は Ruby でいえば nokogiri のような動作をするパッケージで HTML から要素を取得できます。

“goquery そのまんま使えよ” という話ではあるんですが, meta タグのデータとったりするとコードが長くなりがちだったので別パッケージにしました。

雑な使い方

package main

import (
  "fmt"

  "github.com/PuerkitoBio/goquery",
  "github.com/yterajima/go-webpage"
)

func main() {
  // []byte を返す html ページを取得する処理
  page := getHtmlPage("http://example.com/hoge.html")

  // 初期化
  // この時点で wp.Title とか取得できる
  wp := webpage.New(page)

  // wp.Title から余計なスペースを除去したデータを返す
  fmt.Println(wp.GetTitle())
}

go-dtf

https://github.com/yterajima/go-dtf

go-dtf は W3C Date and Time Formats (通称: W3C-DTF) に該当する時刻文字列を time.Time に変換するだけのパッケージです。この W3C-DTF が少々曲者で某プロダクトの中でコードを一緒にしておきたくなかったので分離してパッケージにしました。

W3C-DTF は 6 パターンの文字列を日時定義としています。

  • YYYY ex: 2015
  • YYYY-MM ex: 2015-12
  • YYYY-MM-DD ex: 2015-12-10
  • YYYY-MM-DDThh:iiTZD ex: 2015-12-10T13:00+09:00
  • YYYY-MM-DDThh:ii:mmTZD ex: 2015-12-10T13:00:00+09:00
  • YYYY-MM-DDThh:ii:mm.sTZD ex: 2015-12-10T13:00:00.123456789+09:00

詳しくは 日付の表記に関するノート にとてもよくまとめられています。末尾の +09:00 はタイムゾーン指定で日本を表します。UTC の場合は +00:00 と書くか 2015-12-10T13:00Z のように末尾に “Z” 1文字で UTC を表します。

パッケージとしては文字列が W3C-DTF にマッチするか判定することと, それぞれの形式に応じて time.Time に変換しているだけですが golang のタイムゾーンのテストあたりは勉強になりました。

雑な使い方

package main

import (
  "fmt"

  "github.com/yterajima/go-dtf"
)

func main() {
  // エクスポートしている関数は沢山あるけれど
  // 単にパースするだけなら dtf.Parse だけ使えばできる
  parsedTime, _ := dtf.Parse("2015-12-10T02:50+09:00")
  fmt.Println(parsedTime)
}

最後に

golang 製のプロダクトを github の private リポジトリで勢いよく作ると分離したい汎用パッケージが増えて思わず github の契約プランを上げてしまう現象, もう少しどうにかならないだろうか。

sitemap.xml をよしなに取得する go-sitemap を公開しました

golang で開発・運用している Web クローラの設計を見直すに当たり, 分離できそうな機能を分割しパッケージにすることにしました。そのうちの 1 つとして sitemap.xml を取得し Sitemap 構造体を生成する部分を公開しました。

go-sitemap

どういう部分で使っているのか

某 Web クローラでは各 Web サイトの sitemap.xml から全ページの URL を取得, さらにそこからデータを加工, ページデータの取得といった処理を行っています。その sitemap.xml からのページ URL 取得処理部分を go-sitemap で実装しています。

sitemap.xml 取得の面倒なところ

ファイル名が sitemap.xml だったとしても中身を見るまで サイトマップインデックス なのか サイトマップ かわからない場合があります。

例えば, この blog の sitemap.xml の中身は <sitemapindex...>...</sitemapindex> で囲まれているサイトマップインデックスです。サイトマップインデックスは複数のサイトマップ(<urlset...>...</urlset>) への参照を持っています。1 つのデータとしてページ URL をまとめるにはすべてのサイトマップファイルをパースしまとめる必要があります。

go-sitemap ではサイトマップインデックス or サイトマップか自分で判定せずに呼び出し Sitemap 構造体として返します。

続きを読む

クローラをテストする場合の少し気を使ったテストサーバ

まだあまり細かい話は外に出せないですが, golang で Web クローラと API を使ったシステムを開発しています。

クローラを書くにあたり net/http/httptest を使ってこんなテスト用サーバを書いて対応しました。

package main

import (
  "fmt"
  "io/ioutil"
  "net/http"
  "net/http/httptest"
)

func testServer() *httptest.Server {
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    // User-Agent が想定してないものの場合 400
    if r.Header.Get("User-Agent") != "Mybot" {
      http.Error(w, "User-Agent is invalud", http.StatusBadRequest)
    }

    // Basic 認証が設定されている場合照合し判定
    // 不正な場合 401 を返す
    if authName, authPass, authStatus := r.BasicAuth(); authStatus {
      if authName != "correct-username" || authPass != "correct-password" {
        http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
      }
    }

    // サイト root はテストしないので 404
    if r.RequestURI == "" {
      // index page is always not found
      http.NotFound(w, r)
    }

    // RequestURI と同名のファイルを testdata ディレクトリから取得
    // 存在しなければ 404
    res, err := ioutil.ReadFile("../testdata" + r.RequestURI)
    if err != nil {
      http.NotFound(w, r)
    }

    // 取得したコンテンツを返す
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, str)
  }))
  return server
}

続きを読む

Middlemanの拡張gemをv4.beta.2対応してハマったこと

このところの Middleman の変更も落ち着いて来たようなので公開している Middleman の拡張機能をアップデートしてみました。

やったこと

  • v4.beta でも拡張機能が動作するように gemspec の依存関係を変更
  • .travis.yml から Ruby v1.9 関係の処理を削除
  • v4.beta.x と併用した場合に落ちるテストへの対応

続きを読む

gitoliteのリポジトリ管理ツールをgolangで書きなおしてみた

最近では github をメインにリポジトリ管理をしていますが, 特に公開する必要がないものはサーバに gitolite で Git サーバを用意して管理しています。2 年ほど前に gitolite 用のリポジトリを管理するコマンドを Ruby で適当に書いて使っていたのですが不便だったのと最近 golang を書いているので書きなおしてみました。

2 年前の記事: gitolite 管理のリポジトリを簡単に追加できるようにした

そもそもの仕組み

gitolite は git サーバのリポジトリ自体を git で管理しています。

例えば, 新たにリポジトリを追加する場合, conf/gitolite.conf に対して次の行を追加します。

repo    namespace/new-repository
        RW+  =  @develop

このまま commit し push すると git@example.jp:namespace/new-repository.git をリモートリポジトリとして利用できるようになります。作成したコマンドではこの gitolite.conf を管理するためのリポジトリの内容を確認, 変更 して利用します。

続きを読む

仕事サイトをMiddleman v4.beta.2にしてみた

v4-beta がようやくリリースされたので自分の サイト を v4.beta.2 に変更してみました。正確には middleman/middleman の master ブランチを Gemfile に追加して利用しています。

続きを読む

外部APIを用いてMiddlemanで動的にページ生成する

Middleman には 動的ページ と呼ばれる機能があります。この機能は非常にパワフルでデータを元にして動的にページを生成することができます。

今回はこの機能を用いて外部 API からデータを取得しつつページを生成してみます。

外部 API を用意する

Lumenで簡単なAPI作ってみた で作成した API 機能を用いてテストしてみます。難しいことはなく単に次の画像のようなデータを JSON で返すだけです。データ自体は faker で作られています。

lumen-test-api response

この API をローカルの Vagrant 上で動作させています。

続きを読む