我正在使用 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。
关于我可以在这里做什么有什么建议吗?
更新:
作品(卷曲):
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
所以基本上,cloudflare 会因为你伪造浏览器或模仿而抓到你,不是吗?因此,您有一个带有 http 客户端的应用程序,它使用实际浏览器的用户代理。 cloudflare waf 肯定会抱怨。
而是为您的应用程序使用自定义用户代理,这样它对于 CF 来说看起来是真实的。说“我的应用程序 1.0”