在爬取网站时,经常会遇到一些反爬虫的网站,这些网站会检测你的ip地址,如果你的ip地址被检测到是爬虫的话,就会拒绝你的访问,这时候就需要使用代理来解决这个问题。代理的原理就是你的请求先发送给代理服务器,代理服务器再发送给目标服务器,目标服务器返回数据给代理服务器,代理服务器再返回给你。这样的话,目标服务器就无法知道你的真实ip地址,从而达到隐藏你的真实ip地址的目的。网上有一些免费的获取http代理的网站或者可以采用付费购买的方式获取http代理。
我这里我想采用机场来做我的http代理但是机场一般提供的是v2或者ssr协议的代理,恰好clash是用golang写的所以我能在我的golang程序中直接引入clash的代码开启一个本地端口进行代理。
下面是我的代码:
代理实现
package proxyimport ("bytes""encoding/json""fmt""github.com/Dreamacro/clash/config"C "github.com/Dreamacro/clash/constant""github.com/Dreamacro/clash/hub"logs "github.com/danbai225/go-logs""go.uber.org/automaxprocs/maxprocs""io""math/rand""net/http""net/url""os""path/filepath""sync""time")func init() {rand.NewSource(time.Now().UnixNano())}type Clash struct {configPath string}func New(configPath string) *Clash {return &Clash{configPath: configPath}}func (c *Clash) Start() {maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))C.SetHomeDir(".")if c.configPath != "" {if !filepath.IsAbs(c.configPath) {currentDir, _ := os.Getwd()c.configPath = filepath.Join(currentDir, c.configPath)}C.SetConfig(c.configPath)} else {configFile := filepath.Join(C.Path.HomeDir(), C.Path.Config())C.SetConfig(configFile)}if err := config.Init(C.Path.HomeDir()); err != nil {logs.Err("Initial configuration directory error: %s", err.Error())return}if err := hub.Parse(hub.WithExternalController(":9091")); err != nil {logs.Err("Parse config error: %s", err.Error())return}time.Sleep(time.Second * 1)c.Speed()c.RandomSelect()}func (c *Clash) Speed() {proxies := c.Proxies()group := sync.WaitGroup{}for _, s := range proxies {group.Add(1)go func() {http.Get(fmt.Sprintf(`http://127.0.0.1:9091/proxies/%s/delay?timeout=5000&url=%s`, url.PathEscape(s.Name), url.QueryEscape(`https://baidu.com`)))group.Done()}()}group.Wait()}func (c *Clash) Proxies() []P {resp, _ := http.Get(`http://127.0.0.1:9091/proxies`)all, _ := io.ReadAll(resp.Body)m := make(map[string]interface{})m2 := make(map[string]P)json.Unmarshal(all, &m)marshal, _ := json.Marshal(m["proxies"])json.Unmarshal(marshal, &m2)ps := make([]P, 0)for k := range m2 {ps = append(ps, m2[k])}return ps}func (c *Clash) Switchover(name string) {json := fmt.Sprintf(`{"name":"%s"}`, name)req, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:9091/proxies/GLOBAL", bytes.NewBufferString(json))if err != nil {logs.Err(err)return}req.Header.Set("Content-Type", "application/json")_, err = http.DefaultClient.Do(req)if err != nil {logs.Err(err)return}}func (c *Clash) EffectiveProxy() []P {ps := make([]P, 0)for _, p := range c.Proxies() {if len(p.History) > 0 && p.History[len(p.History)-1].Delay > 0 {ps = append(ps, p)}}return ps}func (c *Clash) RandomSelect() string {ps := c.EffectiveProxy()name := ps[rand.Int63n(int64(len(ps)))].Namec.Switchover(name)logs.Info("切换为", name)return name}type P struct {Alive bool `json:"alive"`History []struct {Time time.Time `json:"time"`Delay int `json:"delay"`MeanDelay int `json:"meanDelay"`} `json:"history"`Name string `json:"name"`Type string `json:"type"`Udp bool `json:"udp"`}
使用demo
package mainimport (logs "github.com/danbai225/go-logs""io""net/http""net/url""test/proxy")func main() {clash := proxy.New("clash.yml")clash.Start()// 创建代理URLproxyURL, err := url.Parse("http://127.0.0.1:7799")if err != nil {return}transport := &http.Transport{Proxy: http.ProxyURL(proxyURL),}c := &http.Client{Transport: transport,}resp, err := c.Get("https://ip.useragentinfo.com/json")all, err := io.ReadAll(resp.Body)logs.Info(string(all))}