日記

更新頻度はあまり高くはありませんがネタがあったら書いていこうと思います。

コマンドラインで翻訳できるツールを作った。(バイナリ配布)

roomba.hatenablog.com

こちらの記事でGlosbeの翻訳APIをしったので、このツールのGo実装を作成してみました。さらに、いろいろな言語に対応できるようにしました。

github.com

ソースコードです

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
    "os"
    "strings"
)

// URL of api
const URL = "https://glosbe.com/gapi/translate"

func makeURL(src, srcLang, destLang string) string {
    v := url.Values{}
    v.Add("from", srcLang)
    v.Add("dest", destLang)
    v.Add("format", "json")
    v.Add("phrase", src)

    return URL + "?" + v.Encode()
}

// Send request.
func request(url string) (result string, err error) {
    resp, err := http.Get(url)
    if err != nil {
        return
    }

    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return
    }

    var response Response
    err = json.Unmarshal(b, &response)
    if err != nil {
        return
    }

    res := make([]string, len(response.Tuc))
    count := 0
    for i, v := range response.Tuc {
        if v.Phrase.Text != "" {
            res[i] = v.Phrase.Text
            count = i
        }
    }
    result = strings.Join(res[:count+1], ",")

    return
}

func main() {

    // Setting help message.
    flag.Usage = func() {
        fmt.Fprintf(os.Stderr, `dict [OPTIONS] <src>
Options
`)
        flag.PrintDefaults()
    }

    // If this option is exist, translate to Japanese from English.
    from := flag.String("f", "", "From")
    to := flag.String("t", "", "To")
    flag.Parse()
    args := flag.Args()

    if *to == "" || *from == "" || args == nil || len(args) != 1 {
        flag.Usage()
        os.Exit(1)
    }

    result, err := request(makeURL(args[0], *from, *to))
    if err != nil {
        fmt.Println("Not found.")
    } else {
        fmt.Println(result)
    }
}

// Response object.
type Response struct {
    Result string `json:"result"`
    Tuc    []Tuc  `json:"tuc"`
    Phrase string `json:"phrase"`
    From   string `json:"from"`
    Dest   string `json:"dest"`
}

// Tuc object.
type Tuc struct {
    Phrase    Phrase    `json:"phrase"`
    Meanings  []Meaning `json:"meanings"`
    MeaningID int64     `json:"meaningId"`
    Authors   []int64   `json:"authors"`
}

// Phrase object.
type Phrase struct {
    Text     string `json:"text"`
    Language string `json:"language"`
}

// Meaning object.
type Meaning struct {
    Language string `json:"language"`
    Text     string `json:"text"`
}

使い方はGithubにも書いてありますが。例えば

$ dict -f en -t ja cat
$ 猫,ネコ,ねこ,にゃあにゃあ,neko,にゃにゃ,にゃんにゃん,ぬこ,カト,キャット

みたいな感じで実行します。
マークダウンとか英語で書いてる時この日本語英語でなんて言うんだろうって時にさっと検索できるのでいいと思います。 うえで上げたブログにかかれているようにaliasを好きな(自然)言語で設定するといいです。

バイナリも配布しているのでGoの環境を作らなくてもお気軽に試すことができるのでぜひ導入してみてください。

バイナリダウンロードリンク

Downloads | dict

良いお年を〜

GolangでSteamのセール情報を取得するクローラを作った。

Amazon.co.jp: Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例: るびきち, 佐々木 拓郎: 本 という本を読んでいて何か実際に実装してみたいなと思い、Steamのセールを取得して保存するクローラをGoで作成しました。
このソフトウェアではSteamのセールページをクローリングしてゲームのセール情報をすべて取り出すことができます。

Go言語で並列化を実装したので約400ページ、約6000ゲームの情報を10秒程で取得できます。また、取得したものをCSV形式でファイルに保存するようにしました。
並列化部分の実装は下記のようになっています。

// StartCrawl start crawling.
func (c *Crawler) StartCrawl() (err error) {
    doc, err := goquery.NewDocument(url)
    if err != nil {
        return
    }

    // Getting the number of pages.
    var pageNum int
    doc.Find(".search_pagination_right").Children().Each(func(i int, s *goquery.Selection) {
        if i == 2 {
            pageNum, err = strconv.Atoi(s.Text())
            if err != nil {
                return
            }
        }
    })

    // Starting goroutine.
    resultCh := make(chan []Game, pageNum)
    for i := 1; i < pageNum+1; i++ {
        url := fmt.Sprintf("%s&page=%d", url, i)
        go c.crawl(url, resultCh)
    }

    // Collectiong games.
    for i := 1; i < pageNum+1; i++ {
        gs := <-resultCh
        c.games = append(c.games, gs...)
    }
    close(resultCh)

    return
}

ページネーションからページ数を取得できるので、取得したページのURLを作成し、1ページにつき1つのGoroutineを稼働させChannelを使って回収しています。HTMLのスクレイピングにはgoqueryというライブラリを使用しました。

また、コードはすべてGithub上で公開しています。

github.com

Python+tweepyでフォロワー増殖装置を作った。(+TwitterAPIの考察)

それがそのソースコードです。

Function to increase follower on twitter

qWordというタプルにフォローしたいアカウントのキーワードを入れることで自動的にフォローを行います。 さらにリフォロー率をあげるために、If文でフォロワーよりフォローしている人数が多いユーザーをフォローするようにしています。 Twitter APIにはリクエスト制限(180リクエスト/15min)があるので、1ワードにつき50回リクエストをするので3ワード(150リクエスト)で15分のスリープを行います。

しかしながら、フォローしまくってしまうと161エラーという「もうフォローできない」という趣のエラーが出てしまいます。 1日のフォロー制限は1000人のはずですが、これはそれよりも早い段階で出てしまうようです。 さらに、Twitter APIのユーザ検索は検索上位1000人を検索出来ると書いてあるのですが、実際には27回リクエストつまり540人しか検索出来ずに、それ以降は同じユーザがでてきました。

以上の理由から1000人は自動フォローできませんでした。 他のやり方を知っている方がいましたら教えていただきたいです。

Python+tweepyで自動フォロー装置を作った。

PythonでTwitterAPIを使ってみました。 PythonにはtweepyというTwitterAPIのラッパーライブラリがあるのでそれを使ってみました。

こんな感じになりました。

def followAndUnfollow(api):
    followersIds = api.followers_ids()
    friendsIds = api.friends_ids()


    #フォロアーにそのユーザが存在しなければアンフォロー
    for friendId in friendsIds:
        count = 0
        for followerId in followersIds:
            if friendId==followerId:
                break
            count+=1   
        if count == len(followersIds):
            try:
                api.destroy_friendship(friendId)
                print 'Destoroyed friendship with %s' %friendId
            except tweepy.error.TweepError:
                print 'I could not destroy this friendship.:('

    #フォローしていないフォロアーがいればフォロー
    for followerId in followersIds:
        count=0
        for friendId in friendsIds:
            if followerId == friendId:
                break
            count += 1
        if count == len(friendsIds):
            try:
                api.create_friendship(followerId, True)
                print 'Created friendship with %s :)' %followerId
            except tweepy.error.TweepError:
                print 'I could not create this friendship.:('

あとはこれを適当なサーバにデプロイしてスケジューラで実行すれば、勝手にフォロー、アンフォローをしてくれると思います。

たまにidを参照できずにエラーが出るので例外処理を入れました。

自然気胸入院、手術体験記2

 

昨日無事退院することが出来ました。  結局手術をしました。  

先週の金曜日まで気胸によるエアリーク(肺の空気漏れ)もなく順調に見えたのですが、先週の土曜日にまたブラ(嚢胞)が破れたらしく、エアリークが出始めました、結局エアリークは収まらずに、1週間たってしまったので内科治療(胸腔ドレナージ)をやめて外科の治療(手術)を受けることを告げられました。

 

今までは呼吸器科の入院病棟は埋まっていたので小児病棟にいたのですが、手術が決まったので、外科病棟に移りました。  外科病棟のほうが綺麗でよかったです。  それから、手術の説明を受けて、全身麻酔の説明を受けました。  この説明を聞いている間生きている心地がしませんでした。

 

そして手術当日10月16日木曜日、全身麻酔をするので前日の夜から何も飲まず食わずだったので、お腹が空いていましたが、手術は3例目で午後だったので、寝たり、音楽を聞いたりして気を紛らわして待ちました。  そして、15時30分ごろついに看護師が病室にきて手術着に着替えさせられ手術室に連れて行かれました。 手術室がある手術センターはとても騒がしく、でかい機械が無数にあり、なにか工場のようなところだと感じました。

 

そして、硬膜外麻酔という24時間麻酔を注入して手術後の痛みを緩和するために背中にさす麻酔をしました。  これがとても痛く3度ほど局所麻酔をしたのを覚えています。  それが終わると点滴とマスクによる全身麻酔が行われ即座に深い眠りに落とされました。

 

目が覚めると、担架に寝かされていました。  手術中は人工呼吸器が喉に挿管されるので苦しいかと思いきや、目が覚めた時にはもう取れていて苦しくはありませんでした。  でもとにかく強烈に体が痙攣していて電気毛布をかけられていたのを覚えています。  

 

それからもとの病室に戻って寝かされました。  本当の地獄はこれからでした。  

 1番いやっだたのが、手術中の姿勢のせいで左腕が極度の筋肉痛になっていて全く動かせないどころか動かさなくても痛かったことです。  胸の痛みよりもこれが辛かったです。  あと、体中に取り付けられた管やらマスクやらが鬱陶しく、とても眠るどころの話ではありませんでした。  この時体には、胸の排液を取り出すための胸腔ドレーン、尿管、点滴、血圧計、酸素飽和度を測る線、酸素マスク、心電図を測る線、背中の硬膜外麻酔の管が取り付けられていました。  おまけに、寝返りを打てないので、途中から腰痛も加わりました。  この状態で誰が眠れるのかと。。。

 

大変申し訳なかったのですが、5回以上はナースコールをおしてしまいました。  看護師さんに「今何時ですか?」と聞いて「10時。」と言われた時は今までで1番の絶望を味わいました。  なぜなら、自分は3時くらいだと思っていたからです。  これほど朝になって欲しいと切望したことはありませんでした。  あと夜中に熱が高かったので、2本血液を取られましたが、左腕がきになって全然いたくありませんでした。

 

朝になってベッドを起こしてもいいと言われてやっと落ち着きを取り戻せました。  それから、尿管と胸腔ドレーンを抜管し、次の日に硬膜外を抜いて退院出来ました。  こんなに早くていいのかと驚きましたが、ほとんどの人が入院後2、3日で退院できるそうです。  

 

  • まとめ

この自然気胸という病気は、肺にブラという嚢胞ができて、それに穴が空いてそこから、空気が漏れるという病気なのですが、大変再発率が高くたちの悪い病気です。  さらに、原因不明で、若いヤセ型の男性に多く見られる病気です。  例えばこの方

気胸物語(top)

のように10回以上再発することもあるようです。

 

再発率は自然に穴がふさがった場合、30~50%、胸腔鏡手術をしてブラを切除した場合5~10%、開胸手術をしてブラを取った場合1%くらいといった感じです。  なので、自然に治って(内科的治療で)も、多くの人が再発するらしいです。  よって、早めに手術してしまったほうがいいのではとも思います。  でももう手術はうんざりです。

 

以上が僕の気胸体験でした。  ではまた。