ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Golang] BeautifulSoup 사용하기 (goquery 사용하기)
    언어/Golang 2019. 1. 19. 16:24

    Python에는 beautifulsoup 패키지가 존재해 Go에서도 없을까 찾아보던 도중 유사한 패키지를 찾았습니다. 해당 패키지를 사용하여 웹 크롤러를 만들거나 html에서 필요한 정보를 검색할 때, 편리하게 코딩할 수 있습니다.

    설치

    $ go get github.com/PuerkitoBio/goquery

    사용법

    아래는 현재 최신버전인 1.5 버전으로 설명합니다. 1.4이하 버전에서는 NewDocument()가 존재했지만 1.4버전에서 더이상 사용하지 않으므로 언급하지 않습니다.

    package main
    
    import (
      "fmt"
      "log"
      "net/http"
    
      "github.com/PuerkitoBio/goquery"
    )
    
    func ExampleScrape() {
      // Request the HTML page.
      res, err := http.Get("http://metalsucks.net")
      if err != nil {
        log.Fatal(err)
      }
      defer res.Body.Close()
      if res.StatusCode != 200 {
        log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
      }
    
      // Load the HTML document
      doc, err := goquery.NewDocumentFromReader(res.Body)
      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)
      })
    }
    
    func main() {
      ExampleScrape()
    }


    위는 타겟 사이트를 호출하여 원하는 데이터를 찾아가는 예시입니다. 아래에서는 test html을 생성 후 기능을 하나씩 설명한 예제입니다.

    test html 생성 후 원하는 태그 찾기

    검색은 html을 찾는 방식과 동일합니다.

    태그 .클래스명 #아이디명

    예시)

    div 안에 있는 모든 p태그 찾기

    • div p

    class=name 명 찾기

    • .name

    id=err 명 찾기

    • #err

    <div class=name> 찾기

    • div.name

    <div class=name> <p>test</p> </div> 에서 p태그 내의 내용찾기

    • div.name p


    아래는 a 태그를 찾는 예시입니다.

    package main
    
    import (
    	"fmt"
    	"strings"
    
    	"github.com/PuerkitoBio/goquery"
    )
    
    func ExampleScrape() {
    	// HTML 요청
    	html := `
    	<!DOCTYPE html>
    <html>
    
    <head>
       <title>Page title</title>
    </head>
    
    <body>
       <div>
          <p>a</p>
          <p>b</p>
          <p>c</p>
       </div>
       <div class="ex_class">
          <p>d</p>
          <p>e</p>
          <p>f</p>
       </div>
       <div id="ex_id">
          <p>g</p>
          <p>h</p>
          <p>i</p>
       </div>
       <h1>This is a heading</h1>
       <p>This is a paragraph.</p>
       <p>This is another paragraph.</p>
       <a href="http://brownbears.tistory.com" class="a"/>
    </body>
    
    </html>
    	`
    	rHtml := strings.NewReader(string(html))
    
    	// HTML 문서 불러오기
    	doc, err := goquery.NewDocumentFromReader(rHtml)
    	if err != nil {
    		panic(err)
    	}
    
    	// Find the review items
    	doc.Find("a").Each(func(i int, s *goquery.Selection) {
    		// 코드
    		// fmt.Println(s.Text())
    		
    	})
    }
    
    func main() {
    	ExampleScrape()
    }
    

    태그 사이에 있는 내용 출력

    package main
    
    import (
    	"fmt"
    	"strings"
    
    	"github.com/PuerkitoBio/goquery"
    )
    
    func ExampleScrape() {
    	// HTML 요청
    	html := `
    	<!DOCTYPE html>
    <html>
    
    <head>
       <title>Page title</title>
    </head>
    
    <body>
       <div>
          <p>a</p>
          <p>b</p>
          <p>c</p>
       </div>
       <div class="ex_class">
          <p>d</p>
          <p>e</p>
          <p>f</p>
       </div>
       <div id="ex_id">
          <p>g</p>
          <p>h</p>
          <p>i</p>
       </div>
       <h1>This is a heading</h1>
       <p>This is a paragraph.</p>
       <p>This is another paragraph.</p>
       <a href="http://brownbears.tistory.com" class="a"/>
    </body>
    
    </html>
    	`
    	rHtml := strings.NewReader(string(html))
    
    	// HTML 문서 불러오기
    	doc, err := goquery.NewDocumentFromReader(rHtml)
    	if err != nil {
    		panic(err)
    	}
    
    	// Find the review items
    	doc.Find("h1").Each(func(i int, s *goquery.Selection) {
    		fmt.Println(s.Text())
    
    	})
    }
    
    func main() {
    	ExampleScrape()
    }
    
    // This is a heading

    태그 내의 속성값 출력

    package main
    
    import (
    	"fmt"
    	"strings"
    
    	"github.com/PuerkitoBio/goquery"
    )
    
    func ExampleScrape() {
    	// HTML 요청
    	html := `
    	<!DOCTYPE html>
    <html>
    
    <head>
       <title>Page title</title>
    </head>
    
    <body>
       <div>
          <p>a</p>
          <p>b</p>
          <p>c</p>
       </div>
       <div class="ex_class">
          <p>d</p>
          <p>e</p>
          <p>f</p>
       </div>
       <div id="ex_id">
          <p>g</p>
          <p>h</p>
          <p>i</p>
       </div>
       <h1>This is a heading</h1>
       <p>This is a paragraph.</p>
       <p>This is another paragraph.</p>
       <a href="http://brownbears.tistory.com" class="a"/>
    </body>
    
    </html>
    	`
    	rHtml := strings.NewReader(string(html))
    
    	// HTML 문서 불러오기
    	doc, err := goquery.NewDocumentFromReader(rHtml)
    	if err != nil {
    		panic(err)
    	}
    
    	// Find the review items
    	doc.Find("a").Each(func(i int, s *goquery.Selection) {
    		value, isExist := s.Attr("href")
    		fmt.Println(value, isExist)
    
    	})
    }
    
    func main() {
    	ExampleScrape()
    }
    
    
    
    // http://brownbears.tistory.com true

    복잡한 검색

    아래는 ex_class라는 클래스명을 가진 div태그 내 p태그들의 내용을 찾는 쿼리입니다.

    package main
    
    import (
    	"fmt"
    	"strings"
    
    	"github.com/PuerkitoBio/goquery"
    )
    
    func ExampleScrape() {
    	// HTML 요청
    	html := `
    	<!DOCTYPE html>
    <html>
    
    <head>
       <title>Page title</title>
    </head>
    
    <body>
       <div>
          <p>a</p>
          <p>b</p>
          <p>c</p>
       </div>
       <div class="ex_class">
          <p>d</p>
          <p>e</p>
          <p>f</p>
       </div>
       <div id="ex_id">
          <p>g</p>
          <p>h</p>
          <p>i</p>
       </div>
       <h1>This is a heading</h1>
       <p>This is a paragraph.</p>
       <p>This is another paragraph.</p>
       <a href="http://brownbears.tistory.com" class="a"/>
    </body>
    
    </html>
    	`
    	rHtml := strings.NewReader(string(html))
    
    	// HTML 문서 불러오기
    	doc, err := goquery.NewDocumentFromReader(rHtml)
    	if err != nil {
    		panic(err)
    	}
    
    	// Find the review items
    	doc.Find("div.ex_class p").Each(func(i int, s *goquery.Selection) {
    		fmt.Println(s.Text())
    
    	})
    }
    
    func main() {
    	ExampleScrape()
    }
    
    


    만약 id명이 ex_id를 가진 div태그 내의 모든 p태그들에 대한 내용을 가지고 오고 싶을 경우, div.ex_class p 가 아닌 div#ex_id p 로 검색하면 됩니다.


    더 많은 정보는 https://github.com/PuerkitoBio/goquery 에서 확인할 수 있습니다.

    댓글