Goでビデオゲームの情報をスクレイピングしてみた話
Capr1です.
この記事はGo 2 Advent Calendar 2020の18日目の記事です.
今回はGoでゲームカタログ@Wikiのサイトをスクレピングして、ビデオゲームの情報を取得するプログラムを組んでみました.
やろうとした経緯
実は趣味で自分が今までプレイしてきたビデオゲームを管理できるWebサービスを作ろうとしていて、その開発にビデオゲームの情報を返してくれるWebAPIを利用としました.
しかし現状そのようなWebAPIが存在せず、ビデオゲームの情報を返してくれるWebAPIから自作することになり、そのWebAPIを開発する時に作成した、といった感じです.
ちなみに作ろうとしたWebAPIのイメージは以下のような感じ↓
使ったライブラリ
goquery
Go言語で使えるスクレイピングのライブラリです.
使い方としてはまず、以下のようにスクレイピングしたいサイトの情報を取得します.
doc, err := goquery.NewDocument("https://rooter.jp/blog/")
if err != nil {
panic("htmlの取得に失敗しました")
}
その後、セレクタを指定して、セレクタの中に含まれる複数の情報を取ってきます.
title := doc.Find("h3.article-title")
あとは、eachして、出力してあげます。 iにはindexが入っており、sに取得した情報が入ります.
title.Each(func(i int, s *goquery.Selection){
fmt.Print(s.Text())
})
苦労したこと
今回スクレイピングの対象としたゲームカタログ@Wikiについてなのですが、このサイトに記載されている情報は有志の人たちによって編集されているもので、そのため人によって書き方が違ったり、言葉の表現が微妙に違ったりします.
こういうことから以下のようなことが起こりました.
- 例えばゲームの価格を取得する際、あるページでは「価格」という表記なっていたり、「定価」という表現になっていたりするせいで、価格の情報が取ってこれないケースがあった
これはあらゆるパターンの条件文を記述し、あらゆるパターンに対応させました.(本当は正規表現を使うべきなので、ここは直したい)
Goでスクレピングしてみて感じたこと
Go言語自体、配列の操作が得意ではない
Pythonなら配列の中の特定の要素を探したり、特定の要素を削除したりする際には、標準のライブラリがPython側で用意されているので、それを使えばいいのですが、Goにはそういったライブラリがなく、自分で一からfor文などを記述して処理を実装する必要がありました.
こういったところはPythonとかの方が向いてるのかなぁ.
並行処理の実装が楽
並行処理を実装する際、Goの場合は
go f(x , y)
みたいな感じで関数の前にgo
とつけるだけで、簡単にgoroutineを作れるので、channelとかの理解は必要なあものの、楽に並行処理を実装することができました.
まあこれがGoを使う大きなメリットの一つみたいなところありますねぇ.
今後の課題
- ビデオゲームの詳細情報を取得する処理のところのファイルが比較的大きくなってしまったので、最小の責務で機能ごとに分けたい
最後に
作ったプログラムのリポジトリ↓