ホームページ  >  記事  >  バックエンド開発  >  golang はクローラーを誘導しません

golang はクローラーを誘導しません

PHPz
PHPzオリジナル
2023-05-10 10:06:06434ブラウズ

1. はじめに

インターネットの発展に伴い、Web クローラーの適用範囲はますます広がっています。日常生活では、ニュース、株式、天気、映画、音楽など、ウェブクローラーを通じてさまざまな情報を得ることができます。特にビッグデータ分析や人工知能の分野では、Web クローラーが重要な役割を果たします。この記事では主に、golang 言語を使用して、インターネット上の情報を取得するための無指向性 (つまり、特定のターゲット Web サイトがない) クローラーを作成する方法について説明します。

2. golang の概要

Golang は Google によって開発されたプログラミング言語であり、その同時実行性、高いパフォーマンス、シンプルさ、学習の容易さにより、プログラマーの間でますます好まれています。この記事で使用されている golang のバージョンは 1.14.2 です。

3. 実装のアイデア

このクローラーは主に次のステップに分かれています:

  1. 開始 URL を取得する

次のことができます。 pass URL を手動で入力する、ファイルから URL を読み取る、データベースから URL を読み取るなどの方法で、開始 URL を取得します。

  1. Send http request

Get または Post を通じて http リクエストを送信し、応答データを取得します。

  1. 応答データの解析

正規表現またはサードパーティ ライブラリを使用して、応答データの形式に従ってデータを解析します。

  1. データの保存

データは、ニーズに応じてファイルやデータベースに保存したり、他の保存方法を使用したりできます。

  1. 新しい URL を解析する

応答データ内のハイパーリンクおよびその他の情報に従って、新しい URL を次にクロールされる URL として解析します。

  1. 上記の手順を繰り返します

新しい URL に従って、http リクエストを再度送信し、応答データを解析し、データを保存し、新しい URL を解析し、繰り返します新しいものがなくなるまで URL が表示されるまで。

4. コードの実装

golang では、net/http パッケージを使用して http リクエストを送信し、regexp パッケージまたはサードパーティのライブラリを使用して応答データを解析します。ゴークエリライブラリ。

  1. 初期化関数

まず、開始 URL の取得、http クライアントのセットアップ、その他の操作を担当する初期関数を定義する必要があります。

func init() {
    // 获取起始网址
    flag.StringVar(&startUrl, "url", "", "请输入起始网址")
    flag.Parse()

    // 设置http客户端
    client = &http.Client{
        Timeout: 30 * time.Second,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            return http.ErrUseLastResponse
        },
    }
}
  1. http リクエスト関数の送信

http リクエストの送信と応答データの取得を担当する関数を定義します。

func GetHtml(url string) (string, error) {
    resp, err := client.Get(url)
    if err != nil {
        log.Println(err)
        return "", err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Println(err)
        return "", err
    }

    return string(body), nil
}
  1. 応答データ関数の解析

応答データを解析するには goquery ライブラリを使用します。具体的な実装は次のとおりです:

func ParseSingleHTML(html string, query string) []string {
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
    if err != nil {
        log.Println(err)
        return nil
    }

    result := make([]string, 0)
    doc.Find(query).Each(func(i int, selection *goquery.Selection) {
        href, ok := selection.Attr("href")
        if ok {
            result = append(result, href)
        }
    })

    return result
}
  1. ストレージ データfunction

データをファイルに保存する関数を定義します。

func SaveData(data []string) error {
    file, err := os.OpenFile("data.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        log.Println(err)
        return err
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    for _, line := range data {
        _, err := writer.WriteString(line + "
")
        if err != nil {
            log.Println(err)
            return err
        }
    }
    writer.Flush()

    return nil
}
  1. 新しい URL の解析関数

正規表現を使用して、ハイパーリンク内の新しい URL を解析します。

func ParseHref(url, html string) []string {
    re := regexp.MustCompile(`<a[sS]+?href="(.*?)"[sS]*?>`)
    matches := re.FindAllStringSubmatch(html, -1)

    result := make([]string, 0)
    for _, match := range matches {
        href := match[1]
        if strings.HasPrefix(href, "//") {
            href = "http:" + href
        } else if strings.HasPrefix(href, "/") {
            href = strings.TrimSuffix(url, "/") + href
        } else if strings.HasPrefix(href, "http://") || strings.HasPrefix(href, "https://") {
            // do nothing
        } else {
            href = url + "/" + href
        }
        result = append(result, href)
    }

    return result
}
  1. メイン関数

最後に、クローラー プロセス全体を実装するメイン関数を定義する必要があります。

func main() {
    // 确认起始网址是否为空
    if startUrl == "" {
        fmt.Println("请指定起始网址")
        return
    }

    // 初始化待访问队列
    queue := list.New()
    queue.PushBack(startUrl)

    // 初始化已访问集合
    visited := make(map[string]bool)

    // 循环爬取
    for queue.Len() > 0 {
        // 从队列中弹出一个网址
        elem := queue.Front()
        queue.Remove(elem)
        url, ok := elem.Value.(string)
        if !ok {
            log.Println("网址格式错误")
            continue
        }

        // 确认该网址是否已经访问过
        if visited[url] {
            continue
        }
        visited[url] = true

        // 发送http请求,获取响应数据
        html, err := GetHtml(url)
        if err != nil {
            continue
        }

        // 解析响应数据,获取新的网址
        hrefs := ParseHref(url, html)
        queue.PushBackList(list.New().Init())
        for _, href := range hrefs {
            if !visited[href] {
                hrefHtml, err := GetHtml(href)
                if err != nil {
                    continue
                }
                hrefUrls := ParseSingleHTML(hrefHtml, "a")

                // 将新的网址加入队列
                queue.PushBackList(list.New().Init())
                for _, hrefUrl := range hrefUrls {
                    queue.PushBack(hrefUrl)
                }
            }
        }

        // 存储数据到文件
        data := ParseSingleHTML(html, "title")
        err = SaveData(data)
        if err != nil {
            continue
        }
    }
}

5. 概要

上記は、golang を使用して無向クローラーを作成する基本的なプロセスと実装方法です。もちろん、これは単なる例であり、実際の開発では、クローラ対策やスレッドの安全性なども考慮する必要があります。読者の役に立つことを願っています。

以上がgolang はクローラーを誘導しませんの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。