0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go初心者必見!ウェブスクレイピングからCSV保存まで徹底解説

Posted at

はじめに

ウェブスクレイピングとデータ処理を行いたい場合、Pythonが選ばれることが多いですが、Goでも同様のことが可能です。本記事では、ウェブスクレイピングとCSV書き込みのコードを1つ1つ丁寧に解説します。

この記事では以下を学べます:

  • GoでのHTTPリクエスト
  • GoでHTMLを解析する方法
  • データを整形しCSVファイルに保存する方法

Goに興味がある方に向けて、わかりやすく説明します!

実装手順

1. HTTPリクエストの送信

まず、GoでウェブページのHTMLを取得します。Goでは標準ライブラリnet/httpを使用します。

以下のコードで、指定したURLからHTMLデータを取得します。

resp, err := http.Get(url)
if err != nil {
    fmt.Printf("Failed to fetch the URL: %v\n", err)
    return
}
defer resp.Body.Close()
  • http.Get(url): 指定したURLからHTMLを取得
  • エラーハンドリング: Goではエラー処理が必須なので、err != nilでエラーをチェック
  • defer: 関数終了時にresp.Body.Close()を自動で実行

2. HTMLパース

Goではgoqueryを使用します。

以下のコードでHTMLを解析します。

doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
    fmt.Printf("Failed to parse HTML: %v\n", err)
    return
}
  • goquery.NewDocumentFromReader: HTTPレスポンスをパースして、操作可能なオブジェクトを生成します。

3. データ抽出と整形

HTMLからテキストを抽出し、不要なスペースや改行を削除します。

以下のコードで、記事内容を取得します。

// 投稿テキストの抽出
var textBuilder strings.Builder
doc.Find(".post_txt p").Each(func(i int, s *goquery.Selection) {
    textBuilder.WriteString(strings.TrimSpace(s.Text()))
})
text := textBuilder.String()

// 不要なスペースや改行を削除
cleanedText := regexp.MustCompile(`\s+`).ReplaceAllString(text, "")
  • doc.Find(): CSSセレクタでHTML要素を指定。
  • Each: 各要素に対して処理を実行。
  • strings.Builder: テキストを効率的に結合。
  • regexp.MustCompile: 正規表現を使用してスペースや改行を削除。

4. 日付の解析

Goのtime.Parseを使います。

timeElement := doc.Find(".nichi_post_title h1").Text()
dateObj, err := time.Parse("2006年1月2日", timeElement)
if err != nil {
    fmt.Printf("Failed to parse date: %v\n", err)
    return
}
  • time.Parse: 日付フォーマットを指定して文字列を解析。
  • 2006年1月2日: Goのtimeパッケージでは、フォーマット指定子に特定の日付 (2006-01-02) を使用します。

5. CSVにデータを保存

Goのencoding/csvパッケージを使用して、データをCSVファイルに保存します。

csvFile := "岩手日日新聞_日日草.csv"
file, err := os.OpenFile(csvFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
    fmt.Printf("Failed to open the CSV file: %v\n", err)
    return
}
defer file.Close()

writer := csv.NewWriter(file)
defer writer.Flush()

insertText := fmt.Sprintf("%d,%d,%d,%s", year, month, day, cleanedText)
err = writer.Write(strings.Split(insertText, ","))
if err != nil {
    fmt.Printf("Failed to write to CSV file: %v\n", err)
}
  • os.OpenFile: ファイルを開きます。存在しない場合は作成されます。
  • csv.NewWriter: CSVファイルに書き込むためのライターを生成。
  • writer.Write: 配列データを1行として書き込み。

完成したコード

ここまでの手順をすべて統合すると、以下のコードになります。

package main

import (
	"encoding/csv"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
)

func main() {
	url := "https://www.iwanichi.co.jp/nichinichiso/"

	// HTTPリクエスト
	resp, err := http.Get(url)
	if err != nil {
		fmt.Printf("Failed to fetch the URL: %v\n", err)
		return
	}
	defer resp.Body.Close()

	// HTMLパース
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		fmt.Printf("Failed to parse HTML: %v\n", err)
		return
	}

	// 投稿テキストの抽出
	var textBuilder strings.Builder
	doc.Find(".post_txt p").Each(func(i int, s *goquery.Selection) {
		textBuilder.WriteString(strings.TrimSpace(s.Text()))
	})
	text := textBuilder.String()

	// 不要なスペースや改行を削除
	cleanedText := regexp.MustCompile(`\s+`).ReplaceAllString(text, "")

	// 日付の抽出
	timeElement := doc.Find(".nichi_post_title h1").Text()
	dateObj, err := time.Parse("2006年1月2日", timeElement)
	if err != nil {
		fmt.Printf("Failed to parse date: %v\n", err)
		return
	}

	year := dateObj.Year()
	month := int(dateObj.Month())
	day := dateObj.Day()

	// データフォーマット
	insertText := fmt.Sprintf("%d,%d,%d,%s", year, month, day, cleanedText)

	// CSVに書き込む
	csvFile := "岩手日日新聞_日日草.csv"
	file, err := os.OpenFile(csvFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Printf("Failed to open the CSV file: %v\n", err)
		return
	}
	defer file.Close()

	writer := csv.NewWriter(file)
	defer writer.Flush()

	// データをCSVファイルに書き込む
	err = writer.Write(strings.Split(insertText, ","))
	if err != nil {
		fmt.Printf("Failed to write to CSV file: %v\n", err)
		return
	}

	fmt.Println("Data has been written to the CSV file.")
}

まとめ

Goを使うことで、Pythonとは異なるエラーハンドリングやパッケージの特性を学びながら、ウェブスクレイピングからCSV書き込みまで実装できました。Goの高速性や並行処理の特性を活かせば、さらに強力なアプリケーションが作れます。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?