2017-09-20 10 views
-1

Goを使用してWebスクレイパーを作成しようとしています。私はその言語をかなり使い慣れていますし、htmlパーサーを使用している間に何が間違っているのか分かりません。私はアンカータグを見つけるためにhtmlを解析しようとしていますが、html.TokenTypeEndを代わりに取得しています。Goを使ってHTMLを解析する

package main 

import (
    "fmt" 
    "golang.org/x/net/html" 
    "io/ioutil" 
    "net/http" 
) 

func GetHtml(url string) (text string, resp *http.Response, err error) { 
    var bytes []byte 
    if url == "https://www.coastal.edu/scs/employee" { 
     resp, err = http.Get(url) 
     if err != nil { 
      fmt.Println("There seems to ben an error with the Employee Console.") 
     } 
     bytes, err = ioutil.ReadAll(resp.Body) 
     if err != nil { 
      fmt.Println("Cannot read byte response from Employee Console.") 
     } 
     text = string(bytes) 
    } else { 
     fmt.Println("Issue with finding URL. Looking for: " + url) 
    } 

    return text, resp, err 
} 

func main() { 
    htmlSrc, response, err := GetHtml("https://www.coastal.edu/scs/employee") 
    if err != nil { 
     fmt.Println("Cannot read HTML source code.") 
    } 
    _ = htmlSrc 
    htmlTokens := html.NewTokenizer(response.Body) 
    i := 0 
    for i < 1 { 

     tt := htmlTokens.Next() 
     fmt.Printf("%T", tt) 
     switch tt { 

     case html.ErrorToken: 
      fmt.Println("End") 
      i++ 

     case html.TextToken: 
      fmt.Println(tt) 

     case html.StartTagToken: 
      t := htmlTokens.Token() 

      isAnchor := t.Data == "a" 
      if isAnchor { 
       fmt.Println("We found an anchor!") 
      } 

     } 

    } 

私は、アプリケーションがGetHtmlで、本体の最後まで読み fmt.Printf("%T", tt)

+0

コードがに簡素化することができます。これは既に 'GetHtml'関数で使われています。どうしてあなたはHTML文字列全体を読んでいるのですが、とにかくそれを投げるのですか? – RayfenWindspear

+0

私はPythonに慣れているので、私はhtmlを読んで文字列として返す必要があると思っていました。これは私が書いた初めてのGoプログラムであり、私はそれを理解しようとしているので、その言語にはとても新しいです。 – King

+0

'io.Reader'や' io.ReadCloser'sに出くわしたときは、できればそれを変数に読み込まないようにしたいと思っています。これらのタイプの最適化によって、正しく使用すると効率が向上します。このため、最初にhtml.NewTokenizerが1つ必要です。ちょうどいくつかのアドバイス。応答が巨大ではないことが確かな場合は、 'ioutil.ReadAll'を使うのが大丈夫です。 – RayfenWindspear

答えて

2

を印刷していたときに私はhtml.TokenTypeEndを取得しています。本文の読み取りによってEOFが返されるため、トークナイザはhtml.TokenTypeEndを返します。

は、このコードを使用します。

htmlTokens := html.NewTokenizer(strings.NewReader(htmlSrc)) 

トークナイザを作成します。

また、接続リークを防ぐために応答本体をGetHtmlで閉じてください。あなたは一度だけ `response.Body`を読むことができます

response, err := http.Get("https://www.coastal.edu/scs/employee") 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer resp.Body.Close() 
    htmlTokens := html.NewTokenizer(response.Body) 
loop: 
    for { 
     tt := htmlTokens.Next() 
     fmt.Printf("%T", tt) 
     switch tt { 
     case html.ErrorToken: 
      fmt.Println("End") 
      break loop 
     case html.TextToken: 
      fmt.Println(tt) 
     case html.StartTagToken: 
      t := htmlTokens.Token() 
      isAnchor := t.Data == "a" 
      if isAnchor { 
       fmt.Println("We found an anchor!") 
      } 
     } 
    } 
+0

ありがとう、これで問題は解決しましたが、私は接続リークについても気づいていませんでした。私は非常に明らかに行くために新しいです – King

+0

それは実際に私が笑をしたものです。しかし、素晴らしいアドバイスありがとう! – King

関連する問題