当 Python 请求和 Curl 工作时,Go 语言中发出的请求会被阻止

问题描述 投票:0回答:1

我正在使用 golang 和 http 包制作网络抓取工具。我发送了 GET 请求,但被 Cloudflare 阻止。我一直想将我的工具移植到 Go,但每次尝试时,我都会陷入发出正确的 Web 请求的困境。下面是我用于 Python 3 请求模块、curl、httpx 和命令行工具的示例用户代理。 “Mozilla/5.0(X11;Linux x86_64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/101.0.4951.54 Safari/537.36”

为curl、wget、Python 请求设置用户代理,这样的效果非常好,并且会按预期返回 html 正文,但是当我在 Go-lang 中执行完全相同的操作时,它会给出典型的“no-javascript”并启用 cookies响应体。这是我的 Go 代码,我还尝试了很多其他方法和解决方案,但它们非常过时,或者除了“尝试代理”之外没有提供任何真正的答案。这不是一个正确的解决方案。 (更新代码)

package main

import (
    "compress/gzip"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
)

func ReadAll(r io.Reader) ([]byte, error) {
    reader, err := gzip.NewReader(r)
    if err != nil {
        return nil, err
    }
    defer reader.Close()
    buff, err := io.ReadAll(reader)
    return buff, err
}

func main() {
    // url := "https://www.reaperscans.com"
    url := "http://localhost:8000"
    // agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
    agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0"
    client := &http.Client{}

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatalln(err)
    }

    // req.Header.Set("User-Agent", agent)
    // req.Header.Set("Accept-Encoding", "gzip, deflate")
    // req.Header.Set("Accept", "*/*")
    // req.Header.Set("Connection", "keep-alive")
    req.Header = http.Header{
        "User-Agent":      {agent},
        "Accept-Encoding": {"gzip, deflate"},
        "Accept":          {"*/*"},
        "Connection":      {"keep-alive"},
    }

    // make the http request
    resp, err := client.Do(req)
    if err != nil {
        log.Fatalln(err)
    }
    defer resp.Body.Close()

    // fmt.Println(resp.Uncompressed)

    // body, err := io.ReadAll(resp.Body)
    // if err != nil {
    //  log.Fatalln(err)
    // }
    // log.Println(string(body))

    // decompress the response
    reader, err := gzip.NewReader(resp.Body)
    if err != nil {
        log.Fatalln(err)
    }
    defer reader.Close()

    // read the decompressed resp body
    body, err := ioutil.ReadAll(reader)
    if err != nil {
        log.Fatalln(err)
    }

    // print it out bb
    fmt.Println(string(body))

}

这是我的Python代码

import requests

request_headers = { 
'User-Agent' : ('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36'), } 
request = requests.get("https://www.asurascans.com", headers=request_headers)
print(request.text)

它也适用于curl

curl -A“blahblah”https://www.asurascans.com>output.html

是的,您实际上可以使用“blah”作为用户代理并获得成功的请求。所以我有点困惑我不能在 Go-lang 中做到这一点。

我真的很想学习使用 Go,但我找不到任何可行的解决方案来让这个基本块开始工作。

有一些我不热衷于使用的专用软件包,因为它们不是必需的,它们不可能仍然工作,而且除了使用用户代理之外,我不想绕过 cloudflare,这在 Python 中运行良好, wget 和 Curl。

关于我可以在这里做什么有什么建议吗?

更新:

  • 运行 Python 简单服务器来回显标头,以便按照建议进行调试。我能够调整我的 golang 标头以与 Python 请求模块和 Curl 完全匹配,但问题仍然存在。我什至可以在 Curl 和 Python 中使用可笑的糟糕标头,它会起作用,但在 go lang 中却不起作用。

作品(卷曲):

127.0.0.1 - - [24/Apr/2023 13:03:49] "GET / HTTP/1.1" 200 -
ERROR:root:Host: localhost:8000
User-Agent: UWU
Accept: */*
X-Something: yeah

从字面上看,这确实有效,并为我提供了来自 Go 遇到问题的完全相同网站的响应文本

作品(Python):

127.0.0.1 - - [24/Apr/2023 13:04:59] "GET / HTTP/1.1" 200 -
ERROR:root:Host: localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive

不起作用(Go-Lang):

127.0.0.1 - - [24/Apr/2023 13:06:03] "GET / HTTP/1.1" 200 -
ERROR:root:Host: localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive

这就是我困惑的原因

编辑:- 最终花了 6 个月的时间,但我花了这段时间学习并想出了这个:

func tls_request() *http.Client {
    var (
        conn *tls.Conn
        err  error
    )

    tlsConfig := http.DefaultTransport.(*http.Transport).TLSClientConfig

    c := &http.Client{
        Transport: &http.Transport{
            TLSHandshakeTimeout: 30 * time.Second,
            DisableKeepAlives:   false,

            TLSClientConfig: &tls.Config{
                CipherSuites: []uint16{
                    tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                    tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                    tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    tls.TLS_AES_128_GCM_SHA256,
                    tls.VersionTLS13,
                    tls.VersionTLS10,
                },
            },
            DialTLS: func(network, addr string) (net.Conn, error) {
                conn, err = tls.Dial(network, addr, tlsConfig)
                return conn, err
            },
        },
    }

    // returns client with the necessary setup bypass basic cloudflare checks
    return c
}

完整解决方案在这里: https://github.com/sweetbbak/go-cloudflare-bypass/blob/main/reqwest/reqwest.go

go http web screen-scraping user-agent
1个回答
0
投票

所以基本上,cloudflare 会因为你伪造浏览器或模仿而抓到你,不是吗?因此,您有一个带有 http 客户端的应用程序,它使用实际浏览器的用户代理。 cloudflare waf 肯定会抱怨。

而是为您的应用程序使用自定义用户代理,这样它对于 CF 来说看起来是真实的。说“我的应用程序 1.0”

© www.soinside.com 2019 - 2024. All rights reserved.