書いたもの
package main import ( "goroutine-scraping-cli/sites" "fmt" "sync" ) func main() { var wg sync.WaitGroup resultChannel := make(chan sites.Article) wg.Add(2) go func() { articles := sites.ScrapingHatenaItHotentry() for _, article := range articles { resultChannel <- article } defer wg.Done() }() go func() { articles := sites.ScrapingQiitaWeeklyTrend() for _, article := range articles { resultChannel <- article } defer wg.Done() }() go func() { wg.Wait() close(resultChannel) }() for result := range resultChannel { fmt.Println(result) } }
package sites type Article struct { Title string URL string }
package sites import ( "fmt" "github.com/gocolly/colly/v2" ) func ScrapingHatenaItHotentry() []Article { fmt.Println("はてなITホットエントリー") url := "https://b.hatena.ne.jp/hotentry/it" c := colly.NewCollector() var articles []Article c.OnHTML(".entrylist-contents-main", func(e *colly.HTMLElement) { title := e.ChildText("h3") link := e.ChildAttr("a", "href") article := Article{Title: title, URL: link} articles = append(articles, article) }) c.Visit(url) return articles }
package sites import ( "fmt" "strings" "github.com/gocolly/colly/v2" ) func ScrapingQiitaWeeklyTrend() []Article { fmt.Println("Qiita週間トレンド") url := "https://b.hatena.ne.jp/hotentry/it" c := colly.NewCollector() var articles []Article c.OnHTML("h3", func(e *colly.HTMLElement) { title := e.ChildText("span") link := e.ChildAttr("a", "href") if strings.HasPrefix(link, "https") { article := Article{Title: title, URL: link} articles = append(articles, article) } }) c.Visit(url) return articles }
解説
main関数
- wgという名前のsync.WaitGroupを宣言しています。ゴルーチンの完了するのを待つために使用します。
- resultChannelという名前のチャネルを作成しています。スクレイピング結果を受け取るために使用します。
- wg.Add(2) でsync.WaitGroupに2つのタスクを追加します。
- 最初のゴルーチンは、sites.ScrapingHatenaItHotentry() 関数を呼び出して、はてなブックマークのホットエントリーをスクレイピングし、結果をresultChannelチャネルに送信します。
- 2つ目のゴルーチンは、sites.ScrapingQiitaWeeklyTrend() 関数を呼び出して、Qiitaの週間トレンド記事をスクレイピングし、結果をresultChannelチャネルに送信します。
- wg.Wait() ですべてのゴルーチンの完了を待ちます。
- resultChannel チャネルをクローズします。この程度の内容であればチャネルいらないんですが勉強のため書きたくて書いてます。 ゴルーチンが全て完了した後、resultChannelチャネルをクローズします。
- for result := range resultChannelループで、resultChannelチャネルから結果を読み取ります。
ScrapingHatenaItHotentry
広く使われてそうなcolly
というWebスクレイピングライブラリを使ってみました。
c.OnHTMLメソッドでentrylist-contents-mainクラス内のa.href要素を抜き出してスライスに追加しています。
終わり