//go:build windows package yu_proxy_pool import ( yu_curl "gogs.qqck.cn/s/tools/curl" yu_proxy "gogs.qqck.cn/s/tools/proxy" yu_strconv "gogs.qqck.cn/s/tools/strconv" "strings" "sync" "time" ) // Pool 代理池 type Pool struct { // 并发锁 lock sync.Mutex // 代理池 list []*pool_item // 代理API // 提取链接或直连地址 url string // 0:返回代理列表,1:直连地址,默认为0 url_type byte // 代理有效时长,默认为30秒,单位:秒 valid_time int64 // 代理池内有效时间低于该值就视为无效代理,默认为10秒,单位:秒 failure_time int64 // 0:http/https,1:socks5 _type byte // 认证账号密码,如果代理需要身份认证的情况下填写 user, pass string domain bool // 访问代理API的提取最少间隔,默认不限制 request_space int64 // 最后调用时间,单位:秒 time_last int64 // 单个 IP 最多使用次数,默认为:1 get_max int // 已提取计数 get_count int response string // 最后提取信息 } type pool_item struct { *yu_proxy.Info i int // 已使用计数 } func New() (t *Pool) { t = &Pool{} t.list = make([]*pool_item, 0) t.SetUrlList().SetValidTime(30).SetFailureTime(10).SetHttp().SetDomain(true).SetGetMax(1) return } // -----------------------------------------------------------------------------------------------------API // SetUrl 设置提取代理api链接 func (t *Pool) SetUrl(v string) *Pool { t.lock.Lock() defer t.lock.Unlock() t.url = v return t } // GetUrl 获取提取代理api链接 func (t *Pool) GetUrl() string { t.lock.Lock() defer t.lock.Unlock() return t.url } // SetUrlList 设置提取代理 api 链接 返回类型为:代理列表 func (t *Pool) SetUrlList() *Pool { t.lock.Lock() defer t.lock.Unlock() t.url_type = 0 return t } // SetUrlTunnel 设置提取代理 api 链接 返回类型为:隧道代理,直连地址 func (t *Pool) SetUrlTunnel() *Pool { t.lock.Lock() defer t.lock.Unlock() t.url_type = 1 return t } // SetValidTime 设置代理有效时长,默认为30秒,单位:秒 func (t *Pool) SetValidTime(v int64) *Pool { t.lock.Lock() defer t.lock.Unlock() if v < 1 { v = 30 } t.valid_time = v return t } // GetValidTime 获取代理有效时长,单位:秒 func (t *Pool) GetValidTime() int64 { t.lock.Lock() defer t.lock.Unlock() return t.valid_time } // SetFailureTime 设置代理池内有效时间低于该值就视为无效代理,默认为10秒,单位:秒 func (t *Pool) SetFailureTime(v int64) *Pool { t.lock.Lock() defer t.lock.Unlock() if v < 1 { v = 10 } t.failure_time = v return t } // GetFailureTime 获取代理池内有效时间低于该值就视为无效代理,单位:秒 func (t *Pool) GetFailureTime() int64 { t.lock.Lock() defer t.lock.Unlock() return t.failure_time } // SetHttp 设置代理类型为:http/https func (t *Pool) SetHttp() *Pool { t.lock.Lock() defer t.lock.Unlock() t._type = 0 return t } // SetSocks5 设置代理类型为:socks5 func (t *Pool) SetSocks5() *Pool { t.lock.Lock() defer t.lock.Unlock() t._type = 1 return t } // SetUser 设置代理认证账号,如果代理需要身份认证的情况下填写 func (t *Pool) SetUser(v string) *Pool { t.lock.Lock() defer t.lock.Unlock() t.user = v return t } // GetUser 获取代理认证账号 func (t *Pool) GetUser() string { t.lock.Lock() defer t.lock.Unlock() return t.user } // SetPass 设置代理认证密码,如果代理需要身份认证的情况下填写 func (t *Pool) SetPass(v string) *Pool { t.lock.Lock() defer t.lock.Unlock() t.pass = v return t } // GetPass 获取代理认证密码 func (t *Pool) GetPass() string { t.lock.Lock() defer t.lock.Unlock() return t.pass } // SetDomain // // @Description: 设置是否由代理解析域名,默认:true func (t *Pool) SetDomain(value bool) *Pool { t.domain = value return t } // SetRequestSpace 设置访问代理API的提取最少间隔,默认不限制 func (t *Pool) SetRequestSpace(v int64) *Pool { t.lock.Lock() defer t.lock.Unlock() t.request_space = v return t } // GetRequestSpace 获取访问代理API的提取最少间隔 func (t *Pool) GetRequestSpace() int64 { t.lock.Lock() defer t.lock.Unlock() return t.request_space } // SetGetMax 单个 IP 最多使用次数,默认为:1 func (t *Pool) SetGetMax(n int) *Pool { t.lock.Lock() defer t.lock.Unlock() t.get_max = n return t } // Size 取当前IP池内剩余IP数 func (t *Pool) Size() int { t.lock.Lock() defer t.lock.Unlock() return len(t.list) } // Clear 清空代理池提取的代理信息 func (t *Pool) Clear() { t.lock.Lock() defer t.lock.Unlock() t.list = make([]*pool_item, 0) } // -----------------------------------------------------------------------------------------------------Get // Get 计次提取 func (t *Pool) Get() *yu_proxy.Info { t.lock.Lock() defer t.lock.Unlock() if t.get_max < 1 { return nil } var j_get bool _get: for len(t.list) > 0 { if !t.list[0].IsValid() { t.list = t.list[1:] continue } if t.list[0].i >= t.get_max { t.list = t.list[1:] continue } t.list[0].i++ return t.list[0].Copy() } if j_get = !j_get; j_get && t.request_url() { goto _get } return nil } // GetCheck 计次提取并使用校验函数校验是否可用(只在从列表提取新的IP的时候才会校验) func (t *Pool) GetCheck(on func(*yu_proxy.Info) bool) *yu_proxy.Info { if on == nil { return t.Get() } var j_info *pool_item j_check := false t.lock.Lock() if t.get_max > 0 { var j_get bool _get: for len(t.list) > 0 { if !t.list[0].IsValid() { t.list = t.list[1:] continue } if t.list[0].i >= t.get_max { t.list = t.list[1:] continue } if t.list[0].i == 0 { j_info, j_check, t.list = t.list[0], true, t.list[1:] break } t.list[0].i++ j_info = t.list[0] break } if j_get = !j_get; j_info == nil && j_get && t.request_url() { goto _get } } t.lock.Unlock() if j_info == nil { return nil } if !j_check { return j_info.Copy() } if !on(j_info.Info) { return nil } j_info.i++ t.lock.Lock() t.list = append(t.list, nil) for j_i := len(t.list) - 1; j_i > 0; j_i-- { t.list[j_i] = t.list[j_i-1] } t.list[0] = j_info t.lock.Unlock() return j_info.Copy() } // GetCheckEx 计次提取并使用校验函数校验是否可用(不管是不是从列表提取新的IP都进行校验) func (t *Pool) GetCheckEx(on func(*yu_proxy.Info) bool) *yu_proxy.Info { if on == nil { return t.Get() } var j_info *pool_item t.lock.Lock() if t.get_max > 0 { var j_get bool _get: for len(t.list) > 0 { if !t.list[0].IsValid() { t.list = t.list[1:] continue } if t.list[0].i >= t.get_max { t.list = t.list[1:] continue } j_info = t.list[0] break } if j_get = !j_get; j_info == nil && j_get && t.request_url() { goto _get } } t.lock.Unlock() if j_info == nil { return nil } if !on(j_info.Info) { return nil } j_info.i++ t.lock.Lock() t.list = append(t.list, nil) for j_i := len(t.list) - 1; j_i > 0; j_i-- { t.list[j_i] = t.list[j_i-1] } t.list[0] = j_info t.lock.Unlock() return j_info.Copy() } func (t *Pool) GetResponse() string { return t.response } func (t *Pool) request_url() bool { if t.url_type == 0 { j_time := time.Now().Unix() if j_time-t.time_last < t.request_space { return false } j_curl := yu_curl.NewRequest().SetSslVerifyHost(yu_curl.SSLVERSION_DEFAULT).SetSslVerifyPeer(false).SetTimeout(1000 * 30) defer j_curl.Close() if j_curl.Get(t.url).RespErr() != nil || j_curl.RespStatusCode() != 200 { return false } t.response = j_curl.RespBodyS() j_proxy_list := []string(nil) if strings.Index(t.response, "\r\n") > -1 { j_proxy_list = strings.Split(t.response, "\r\n") } else if strings.Index(t.response, "\\r\\n") > -1 { j_proxy_list = strings.Split(t.response, "\\r\\n") } else if strings.Index(t.response, "\r") > -1 { j_proxy_list = strings.Split(t.response, "\r") } else if strings.Index(t.response, "\\r") > -1 { j_proxy_list = strings.Split(t.response, "\\r") } else if strings.Index(t.response, "\n") > -1 { j_proxy_list = strings.Split(t.response, "\n") } else if strings.Index(t.response, "\\n") > -1 { j_proxy_list = strings.Split(t.response, "\\n") } else if strings.Index(t.response, " ") > -1 { j_proxy_list = strings.Split(t.response, " ") } else if strings.Index(t.response, "
") > -1 { j_proxy_list = strings.Split(t.response, "
") } else { j_proxy_list = append(j_proxy_list, t.response) } t.time_last, j_time = j_time, j_time+t.valid_time-t.failure_time for j_i := 0; j_i < len(j_proxy_list); j_i++ { j_proxy_info := &pool_item{Info: yu_proxy.NewInfo().SetAuthorization(t.user, t.pass)} if strings.Index(j_proxy_list[j_i], " ") > -1 { if j_ip_port := strings.Split(j_proxy_list[j_i], " "); len(j_ip_port) == 3 { j_proxy_list[j_i] = j_ip_port[0] j_proxy_info.User, j_proxy_info.Pass = j_ip_port[1], j_ip_port[2] } } if strings.Count(j_proxy_list[j_i], ".") == 3 && strings.Count(j_proxy_list[j_i], ":") == 1 { j_addr := strings.Split(j_proxy_list[j_i], ":") j_proxy_info.Host, j_proxy_info.Port, j_proxy_info.Type, j_proxy_info.Timeout, j_proxy_info.Domain = j_addr[0], yu_strconv.ParseInt(j_addr[1]), t._type, j_time, t.domain t.list = append(t.list, j_proxy_info) } } return len(t.list) > 0 } else if t.url_type == 1 { j_len := 100 t.list = make([]*pool_item, j_len) for j_num := 0; j_num < j_len; j_num++ { t.list[j_num] = &pool_item{} t.list[j_num].Info = yu_proxy.NewInfo() t.list[j_num].Host = t.url t.list[j_num].User = t.user t.list[j_num].Pass = t.pass t.list[j_num].Type = t._type t.list[j_num].Timeout = -1 t.list[j_num].Domain = t.domain } return true } return false }