集蜂云是一个可以让开发者在上面构建、部署、运行、发布采集器的数据采集云平台。加入到数百名开发者中,将你的采集器发布到市场,从而给你带来被动收入吧!
您是否希望指定自定义的 Golang net/http 用户代理(User Agent)?您来对地方了。随着网站采用各种技术来调控机器人流量,您必须模仿自然浏览器的行为才能访问您所需的数据。
在本文中,您将学习如何配置您的 net/http 用户代理以模拟一个真实的浏览器。
什么是 net/http 用户代理? net/http 用户代理(UA)字符串对于随每个 HTTP 请求发送的 HTTP 头部至关重要。这些头部是元数据,它们向 web 服务器传达额外信息,如认证凭据、内容类型、缓存等。
最重要的是,用户代理提供了关于 web 客户端的各个组成部分的详细信息,例如浏览器名称、版本、设备类型和操作系统。
以下是一个 Google Chrome 浏览器用户代理字符串的示例:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
它表明用户使用的是 Chrome 版本 109.0.0.0,该浏览器在 64 位 Windows 10(Windows NT 10.0)平台上使用 WebKit 渲染引擎。
然而,您的 Golang net/http 用户代理通常看起来像这样:
Go-http-client/1.1
您可以通过向 httpbin.io/user-agent 发送一个基本请求来查看您的用户代理。
上述两个用户代理样本的明显区别证实了网站区分 net/http 请求和实际浏览器是多么容易。这就是为什么指定自定义用户代理至关重要。
让我们看看如何做到这一点。
要使用 net/http 在 Go 应用程序中指定 User-Agent 标头,请按照以下步骤操作:
net/http 包是 Go 标准库的一部分,默认包含在每次 Go 安装中。因此,无需单独安装。您只需创建 Go 项目并导入必要的依赖项即可。
完成所有设置后,您就可以编写代码了。这是一个基本脚本,它发出 GET 请求https://httpbin.io/user-agent并检索其文本内容。
package main
// import the necessary dependencies
import (
"fmt"
"io"
"net/http"
)
func main() {
// make an HTTP GET request
response, err := http.Get("https://httpbin.io/user-agent")
if err != nil {
fmt.Println("Error:", err)
return
}
defer response.Body.Close()
// read the response body
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Println("Error:", err)
return
}
// print the text content
fmt.Println(string(body))
}
net/http 提供了一种Header.Set()允许您设置 HTTP 标头的方法。此方法采用两个参数:标头的名称及其值。在本例中,您将传递“User-Agent”作为标头名称,并将所需的 UA 字符串作为标头值。
为此,您必须创建一个Client。这可以让您更好地控制 HTTP 标头,并允许您根据需要操作它们。
让我们使用之前提供的 Google Chrome UA 示例和httpbin作为目标网站将其分解为更小的步骤。
导入必要的依赖项并创建自定义 HTTP 客户端
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
// create custom HTTP client
client := &http.Client{
Transport: &http.Transport{},
}
}
之后,创建您的GET请求并使用设置自定义用户代理Header.Set()。
func main() {
//...
// create HTTP request
req, err := http.NewRequest("GET", "https://httpbin.io/user-agent", nil)
if err != nil {
// Handle error
return
}
// set User-Agent header
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36")
}
接下来,发出 HTTP 请求,关闭响应主体,读取它并将其文本内容打印到控制台。
func main() {
//...
// make HTTP request
response, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
// close the response body
defer response.Body.Close()
// read the response body
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Println("Error:", err)
return
}
// print the text content
fmt.Println(string(body))
}
综合起来,完整的代码如下:
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
// create custom HTTP client
client := &http.Client{
Transport: &http.Transport{},
}
// create HTTP request
req, err := http.NewRequest("GET", "https://httpbin.io/user-agent", nil)
if err != nil {
// Handle error
return
}
// set User-Agent header
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36")
// make HTTP request
response, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
// close the response body
defer response.Body.Close()
// read the response body
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Println("Error:", err)
return
}
// print the text content
fmt.Println(string(body))
}
运行它,您的响应应该是预定义的自定义用户代理。
{
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
恭喜!您已设置第一个 Golang net/http 用户代理。
不想破坏气氛,但在大多数情况下,仅指定一个 UA 可能还不够,因为网站最终可以识别您的抓取工具。不过,您可以通过在用户代理之间切换来解决此问题。
网站将来自同一用户代理的多个请求解释为自动流量并相应地阻止它们。但通过轮换 UA,您可以让 Web 服务器认为您的请求来自不同的浏览器(用户)。
当使用 net/http 包发出 HTTP 请求时,您可以通过从预定义列表中随机选择在 UA 之间轮换。
您可以通过以下方法修改以前的代码来实现此目的。
首先导入必要的依赖项。然后,定义一个 User-Agent 字符串列表。您可以包含各种 UA 来模拟不同的浏览器、操作系统和设备。我们从这个网页抓取用户代理列表中选择了一些用于此示例。
package main
// import the necessary dependencies
import (
"fmt"
"io"
"net/http"
"math/rand"
)
func main() {
// list of User-Agent strings
var userAgents = []string{
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
// add more UA strings as needed
}
}
接下来,从列表中选择一个随机 UA。为此,生成一个随机整数,并使用它从列表中选择一个。
func main() {
//...
// select a random UA from the list
randomIndex := rand.Intn(len(userAgents))
randomUA := userAgents[randomIndex]
}
之后,创建客户端和 HTTP 请求。然后使用 指定随机选择的 UA Header.Set()。
func main() {
//...
// create custom HTTP client with custom Transport
client := &http.Client{
Transport: &http.Transport{},
}
// create HTTP request
req, err := http.NewRequest("GET", "https://httpbin.io/user-agent", nil)
if err != nil {
fmt.Println("Error:", err)
return
}
// set User-Agent header
req.Header.Set("User-Agent", randomUA)
}
最后按照上面的步骤更新之前的代码,得到以下完整代码。
package main
// import the necessary dependencies
import (
"fmt"
"io"
"net/http"
"math/rand"
)
func main() {
// list of User-Agent strings
var userAgents = []string{
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
// add more UA strings as needed
}
// select a random UA from the list
randomIndex := rand.Intn(len(userAgents))
randomUA := userAgents[randomIndex]
// create custom HTTP client with custom Transport
client := &http.Client{
Transport: &http.Transport{},
}
// create HTTP request
req, err := http.NewRequest("GET", "https://httpbin.io/user-agent", nil)
if err != nil {
fmt.Println("Error:", err)
return
}
// set User-Agent header
req.Header.Set("User-Agent", randomUA)
// make HTTP request
response, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
// close the response body
defer response.Body.Close()
// read the response body
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Println("Error:", err)
return
}
// print the text content
fmt.Println(string(body))
}
每次运行脚本时,都会使用不同的 UA 发出请求。例如,以下是三个请求的结果:
{
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
{
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}
{
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
太棒了!您已成功轮换 Golang net/http 用户代理。
值得注意的是,实际用例需要更大的 UA 列表。因此,关注您的 UA 构造至关重要。格式良好的 UA 对于避免触发反机器人措施至关重要。
例如,您的 UA 字符串必须与其他HTTP 标头匹配。
如果 User-Agent 字符串将客户端标识为特定的浏览器和版本,但其他 HTTP 标头表明不同的特征或行为,则可能会引起怀疑。
尽管如此,构建和维护一份格式正确的 UA 列表需要花费时间和精力。但不用担心,下一节将提供一个更直接的解决方案。
指定自定义 Golang net/http 用户代理有助于避免检测。但是,仅依靠 UA 可能还不够,因为网站采用各种其他措施来检测和阻止抓取活动。更不用说制作和维护准确的用户代理字符串是多么困难。
集蜂云(beeize.com)是一个可以让开发者在上面构建、部署、运行、发布采集器的数据采集云平台。平台提供了海量任务调度、三方应用集成、数据存储、监控告警、运行日志查看等功能,能够提供稳定的数据采集环境。平台提供丰富的采集模板,简单配置就可以直接运行,快来试一下吧。