14
9

More than 3 years have passed since last update.

[Go]goqueryで超簡単!Webスクレイピングを試してみた

Last updated at Posted at 2021-03-23

はじめに

私が、Webマーケッターをやっていた頃、
エンジニアたちがよく、
「このページをスクレイピングして…DDoSならないように、秒間隔空けて…」
とかいうやりとりをしていて、

そう言えば、自分でもスクレイピングに憧れて、
import.io
とかいうスクレイピングの超便利サービスも使ってたなあと懐かしい思いがこみあげまして、、、

エンジニアになった自分もスクレイピングなるものを試してみようと思いたったので挑戦してみますた。

ウェブスクレイピングとは

ウェブスクレイピング(英: Web scraping)とは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。ウェブ・クローラー[1]あるいはウェブ・スパイダー[2]とも呼ばれる。 通常このようなソフトウェアプログラムは低レベルのHTTPを実装することで、もしくはウェブブラウザを埋め込むことによって、WWWのコンテンツを取得する。
参考:wikipedia ウェブスクレイピング

ほうほう、なるほど。(━うん、知ってた)
とりあえずページから情報を抽出できる感じ。

goqueryを使ってみる

Goには、goquery というWebスクレイピング用の便利なライブラリが存在しているらしく、
他の記事でも試している人が多かったので、自分もこちらを採用。

jQuery ライクに操作ができるので便利らしい。

準備

必要なパッケージをダウンロードする。

$ go get -u github.com/PuerkitoBio/goquery # スクレイピングのライブラリ
$ go get -u github.com/saintfish/chardet # 文字コードの判定用
$ go get -u golang.org/x/net/html/charset # 文字コードの変換用

go.modでやる場合は、上記パッケージを記述後
go build等をしてください〜

go getのオプション

ざっくりと記します。詳しくは公式サイトへ
Go: Package get

go get
-d # only download (no install)
-u # update the packages & dependencies
-f # force -uと一緒に使い、-uがパッケージチェックするのを無効化する。利用シーンはソースがローカルコピーのとき
-t # test テストをビルドするパッケージもダウンロード
-v # verbose 進捗とデバッグ出力
-fix # 依存関係を修正

コード

go gin のフレームワークを使って、REST APIを作成し、
URLを入力すると、そのページ先からタイトルを抽出して結果を返すmain.goです。
(※エディタはgolandを使いました。Go Modulesとかの管理が楽)

main.go
package main

import (
    "bytes"
    "fmt"
    "golang.org/x/net/html/charset"
    "io/ioutil"
    "log"
    "net/http"

    "github.com/PuerkitoBio/goquery"
    "github.com/gin-gonic/gin"
    "github.com/saintfish/chardet"
)

func main() {
    // Start HTTP server
    r := gin.Default()
    r.GET("/scrape", scrapeText)

    if err := r.Run(":8080"); err != nil {
        log.Fatal(err)
    }
}

func scrapeText(c *gin.Context) {
    url := c.Query("url")

    // Getリクエストでレスポンス取得
    res, _ := http.Get(url)
    defer res.Body.Close()

    // Body内を読み取り
    buffer, _ := ioutil.ReadAll(res.Body)

    // 文字コードを判定
    detector := chardet.NewTextDetector()
    detectResult, _ := detector.DetectBest(buffer)
    fmt.Println(detectResult.Charset)
    // => UTF-8

    // 文字コードの変換
    bufferReader := bytes.NewReader(buffer)
    reader, _ := charset.NewReaderLabel(detectResult.Charset, bufferReader)

    // HTMLをパース
    document, _ := goquery.NewDocumentFromReader(reader)

    // titleを抜き出し
    result := document.Find("title").Text()
    fmt.Println(result)

    // Response: JSON
    c.IndentedJSON(http.StatusOK, result)
}

htmlはテスト用です。(超ショボい・・・(´・ω・`))

index.html
<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" charset="utf-8">
</head>
<body>
  <form method="get" action="http://localhost:8080/scrape">
    <p>URL<textarea name="url" size="30" placeholder="URL記入"></textarea></p>
    <p><input type="submit" value="scrape"></p>
  </form>
</body>
</html>

実際に動かしてみる

とりあえず、フォームに鉄板の Yahoo! JAPAN を入れてみる。

スクリーンショット 2021-03-23 16.09.44.png

やほおおおおお

いざ!scrapeボタンを押すと・・・

スクリーンショット 2021-03-23 15.16.44.png

表示された!!

地味に嬉しい✨✨✨

まとめ

今度は、複数のURLページにアクセスして、
GO RoutineとかChannelsなんかを使って、アプリケーションを拡張してみたいですねぇ。

前に形態素解析のライブラリのMeCabなんかも入れたから、
GolangでMeCab+NEologdが使えるDockerイメージ作成してみた

それと組み合わせて、
スクレイピングしてきたテキストを形態素解析にかけて遊ぶ

みたいなこともできそうです。

可能性、無限大!!!!!!!!!!!!

以上、ありがとうございました。

参考にした記事たち

【Go】Webスクレイピングのやり方
goqueryでお手軽スクレイピング!
Goとgoqueryでスクレイピング
Go言語で jQuery ライクな操作が出来る goquery を試した。

14
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9