LoginSignup
2
2

More than 5 years have passed since last update.

goqueryを使ってサイト内のCSSをスクレイピング

Last updated at Posted at 2017-07-31

サイト内で使用されているCSSを確認しようとしたのですが、膨大なページがあったのでスクレイピングをする事にしました。その時に使用したgoqueryがとても便利でした。

他にもスクレイピング系ライブラリがあるみたいです。
Go言語のスクレイピング系ライブラリまとめ

goqueryの便利なところは、HTMLのselectorを指定できるので、jQuery感覚で記述できる点です。
以下は、githubからExamplesをお借りしました。

ExampleScrape.go
func ExampleScrape() {
  doc, err := goquery.NewDocument("http://metalsucks.net")
  if err != nil {
    log.Fatal(err)
  }

  // Find the review items
  doc.Find(".sidebar-reviews article .content-block").Each(func(i int, s *goquery.Selection) {
    // For each item found, get the band and title
    band := s.Find("a").Text()
    title := s.Find("i").Text()
    fmt.Printf("Review %d: %s - %s\n", i, band, title)
  })
}

めちゃくちゃ読みやすくないですか?

sitemapから各ページで使用されているCSSを洗い出す

各ページで使用されているCSSを洗い出すために以下の事を行なっています。
思ったよりサクっとできました:thumbsup:

  1. sitemapにあるaタグのhref、タイトルを取得。
  2. http://example.com/がついていないかチェック。ついていなかったらつける。
  3. 重複が存在している場合は削除。(めっちゃdirty)
  4. 最後はURLを使って、各ページにアクセスし、CSSを取得・表示。
main.go
package main

import _ "fmt"

import (
    "bytes"
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "regexp"
)

func main() {
    urls := []string{}
    titles := []string{}
    doc, err := goquery.NewDocument("http://example.com/sitemap/")
    if err != nil {
        fmt.Print("url scarapping failed")
    }
    doc.Find("a").Each(func(_ int, s *goquery.Selection) {
        url, _ := s.Attr("href")
        title, _ := s.Html()
        urls = append(urls, url)
        titles = append(titles, title)
    })
    urls = removeDuplicate(createProtocolUrl(urls))
    for i := range urls {
        doc, err := goquery.NewDocument(urls[i])
        if err != nil {
            fmt.Print("\n", "child url scarapping failed", "\n")
        }
        doc.Find("[rel='stylesheet']").Each(func(_ int, s *goquery.Selection) {
            cssPath, _ := s.Attr("href")
            fmt.Print(titles[i], "  --  ", urls[i], " -> ", cssPath, "\n")
        })
    }
}

func createProtocolUrl(urls []string) (result []string) {
    arrayUrlHasProtocol := []string{}
    for i := range urls {
        var url string
        if hasDomain(urls[i]) {
            url = urls[i]
        } else {
            var buffer bytes.Buffer
            buffer.WriteString("https://example.com")
            buffer.WriteString(urls[i])
            url = buffer.String()
        }
        if url != "" {
            arrayUrlHasProtocol = append(arrayUrlHasProtocol, url)
        }
    }
    return arrayUrlHasProtocol
}

func hasDomain(path string) bool {
    return regexp.MustCompile(`^http://example.com/`).Match([]byte(path))
}

func removeDuplicate(args []string) []string {
    results := make([]string, 0, len(args))
    for i := 0; i < len(args); i++ {
        dup := false
        for j := 0; j < len(results); j++ {
            if args[i] == results[j] {
                dup = true
                break
            }
        }
        if !dup {
            results = append(results, args[i])
        }
    }
    return results
}

まとめ

スクレイピング自体どの言語を使っても割と簡単にできるので、今回はGo言語で行いました。
コードを書くよりも環境設定の方が時間かかりました。結局gopathをどこにしたらいいのかはわからず:cry:
Go自体こういったコードを書くには向いてると思います!

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