hasen's tech life

Twitter: @hasen

GolangのgoqueryでQiitaのアドベントカレンダリストをスクレイピング.

最近,Golangをあまり書いてなかったので,スクレイピングの写経をしました.
Qiitaのアドベントカレンダを対象としたもので,goqueryを使っています.
フロントのコーディングが変わったようなので,元のコードから少し変更させてもらいました.

$ vi by_goquery.go

++ package main
++
++ import (
++   "fmt"
++   "github.com/PuerkitoBio/goquery"
++   "os"
++   "regexp"
++   "sync"
++ )
++
++ type Result struct {
++   Title string
++   Url string
++ }
++
++ const (
++   // 引数の確認
++   MINIMUM_ARGS = 2
++ )
++
++ // DOMを解析して,タイトルとURLを取り出す.
++ func getPage(url string) [ ]Result {
++   results := [ ]Result{}
++   doc, _ := goquery.NewDocument(url)
++   doc.Find("td.adventCalendar_calendarList_calendarTitle>a").Each(func(_ int, s *goquery.Selection) {
++     url, exists := s.Attr("href")
++     if exists {
++       // feedではない方のURLを取得
++       is_feed_url, _ := regexp.MatchString(".*\\/feed$", url)
++       if !is_feed_url {
++         result := Result{s.Text(), "http://qiita.com" + url}
++         results = append(results, result)
++       }
++     }
++   })
++
++   return results
++ }
++
++ // 対象のURLにDOMを取得しに行く.
++ func get(urls [ ]string) <-chan [ ]Result {
++   var wg sync.WaitGroup
++
++   ch := make(chan [ ]Result)
++   go func() {
++     for _, url := range urls {
++       wg.Add(1)
++       go func(url string) {
++         ch <- getPage(url)
++         wg.Done()
++       }(url)
++     }
++     wg.Wait()
++     close(ch)
++   }()
++
++   return ch
++ }
++
++ // 実行
++ func main() {
++   args := os.Args
++   if len(args) < MINIMUM_ARGS {
++     panic("usage: $ go run by_goquery.go TARGET_URLS")
++   }
++
++   urls := [ ]string{}
++   for index, arg := range args {
++     if index != 0 {
++       urls = append(urls, arg)
++     }
++   }
++
++   ch := get(urls)
++   for {
++     results, ok := <-ch
++     if !ok {
++       return
++     }
++
++     for _, result := range results {
++       fmt.Println("[" + result.Title + "]: " + result.Url)
++     }
++   }
++ }

# 実行
$ go run by_goquery.go http://qiita.com/advent-calendar/2013 http://qiita.com/advent-calendar/2014

# コードを下記に置いています.
nesah/scrape_qiita_advent_calendar

参考: goqueryでお手軽スクレイピング!