我们使用Go语言编写一个爬虫,通过API提取代理IP,并使用这些代理IP来访问目标网站。 我们将编写一个简单的程序,由于代理的可用性不确定,这里我会尝试使用不同的代理直到成功或全部尝试完毕。
以下是一个使用 Go 语言编写的爬虫代码,它通过代理 API 获取代理列表,并使用随机代理访问目标网站:
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
"net/url"
"os"
"time"
)
// 代理 API 响应结构体 (根据实际 API 响应调整)
type ProxyResponse struct {
Data []struct {
IP string `json:"ip"`
Port int `json:"port"`
} `json:"data"`
}
func main() {
// 代理 API 地址 (替换为实际 API 地址)
proxyAPI := "https://proxy-provider.com/api/get-proxies?type=http&count=10"
// 目标网站 URL
targetURL := "https://httpbin.org/ip"
// 步骤 1: 从 API 获取代理列表
proxies, err := fetchProxies(proxyAPI)
if err != nil {
fmt.Printf("获取代理失败: %v\n", err)
return
}
fmt.Printf("共获取 %d 个代理\n", len(proxies))
// 步骤 2: 随机选择一个代理
rand.Seed(time.Now().UnixNano())
proxyAddr := proxies[rand.Intn(len(proxies))]
fmt.Printf("使用代理: %s\n", proxyAddr)
// 步骤 3: 使用代理发送请求
resp, err := sendRequestWithProxy(targetURL, proxyAddr)
if err != nil {
fmt.Printf("请求失败: %v\n", err)
return
}
defer resp.Body.Close()
// 步骤 4: 处理响应
body, _ := io.ReadAll(resp.Body)
fmt.Printf("响应状态: %d\n内容:\n%s\n", resp.StatusCode, body)
}
// 从 API 获取代理列表
func fetchProxies(apiURL string) ([]string, error) {
resp, err := http.Get(apiURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 根据 API 实际返回格式处理 (示例为 JSON 格式)
var proxyResp ProxyResponse
if err := json.NewDecoder(resp.Body).Decode(&proxyResp); err != nil {
// 如果 API 返回文本格式 (每行一个代理)
return parseTextProxies(resp.Body)
}
// 处理 JSON 格式响应
var proxies []string
for _, p := range proxyResp.Data {
proxies = append(proxies, fmt.Sprintf("%s:%d", p.IP, p.Port))
}
return proxies, nil
}
// 解析文本格式代理 (ip:port 每行一个)
func parseTextProxies(body io.Reader) ([]string, error) {
var proxies []string
scanner := bufio.NewScanner(body)
for scanner.Scan() {
proxies = append(proxies, scanner.Text())
}
return proxies, scanner.Err()
}
// 通过代理发送 HTTP 请求
func sendRequestWithProxy(targetURL, proxyAddr string) (*http.Response, error) {
// 设置代理
proxyURL, err := url.Parse("http://" + proxyAddr)
if err != nil {
return nil, err
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyURL),
}
client := &http.Client{
Transport: transport,
Timeout: 10 * time.Second,
}
// 创建请求
req, err := http.NewRequest("GET", targetURL, nil)
if err != nil {
return nil, err
}
// 设置请求头 (模拟浏览器)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
// 发送请求
return client.Do(req)
}
使用说明:
1、替换代理 API:
- 将
proxyAPI变量替换为实际的代理服务商 API - 示例 API 格式假设返回 JSON:
{"data": [{"ip":"1.2.3.4", "port":8080}, ...]} - 如果 API 返回文本格式(每行一个
ip:port),代码会自动处理
2、配置目标 URL:
- 修改
targetURL为你要爬取的目标网站 - 示例使用 httpbin.org 进行测试
3、安装依赖:
go mod init proxy-crawler
go mod tidy
4、运行代码:
go run main.go
功能特点:
- 自动获取代理列表
- 随机选择代理服务器
- 支持 HTTP 代理
- 模拟浏览器 User-Agent
- 自动处理 JSON/文本格式代理
- 10 秒超时设置
自定义选项:
-
增加重试机制:遇到失败时更换代理重试
-
添加代理验证:检查代理可用性
-
设置请求频率:添加
time.Sleep()避免被封 -
使用 HTTPS 代理:修改代理 URL 为
https:// -
添加代理认证:
proxyURL := fmt.Sprintf("http://user:pass@%s", proxyAddr)
最后需要提醒的是,在实际使用时,请根据代理服务商提供的 API 文档调整响应解析逻辑。了解API提取频率限制以及了解网站规则,避免超量提取使用请求导致触发反爬机制,这样正向循环才能更高效的获取你想要的数据。