### 快代理
goquery包github地址:https://github.com/PuerkitoBio/goquery
快代理:https://www.kuaidaili.com/free/
ip地址查詢api接口:http://vv.video.qq.com/checktime?otype=json
運行結果:

這個報錯是因為有變量指向nli了

ip地址查詢api接口
1. 搜狐:https://pv.sohu.com/cityjson?ie=utf-8
2. 網易:http://ip.ws.126.net/ipquery?ip=114.114.114.114
3. 天翼:https://cloud.189.cn/ip/getIp.do
4. 騰訊:http://vv.video.qq.com/checktime?otype=json
5. 高德:https://restapi.amap.com/v3/ip?key=0113a13c88697dcea6a445584d535837&ip=39.156.69.79
6. B站:https://api.bilibili.com/x/web-interface/zone?jsonp=jsonp
7. 太平洋:http://whois.pconline.com.cn/ip.jsp?ip=114.114.114.114
8. IPAPI:http://ip-api.com/json/114.114.114.114?lang=zh-CN
參考:https://blog.csdn.net/qq_39116404/article/details/105346644
參考:https://blog.csdn.net/weixin_33936401/article/details/89582308?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&utm_relevant_index=2
Find()選擇器用法參考:https://www.cnblogs.com/chaoyueqi/p/7545837.html
完整案列:
```
// by 安研 記性不好 只能多寫注釋
package main
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
"github.com/PuerkitoBio/goquery"
)
// 使用結構體 來解碼 編碼json數據 和用來接收爬取的數據
type Presult struct {
Ip string `json:"ip"` // ip
Port string `json:"port"` // port 端口
Anonymous string `json:"anonymous"` // 匿名度
Agreement string `json:"agreement"` //類型
Region string `json:"region"` //地區
Speed string `json:"speed"` //速度
Timeout string `json:"timeout"` //最后驗證時間
}
// 采集代理ip數據
func Collection(Url string) []Presult {
// 用這個結構體儲存 請求返回的結果
proxyList := []Presult{}
// 創建一個請求客戶端
client := &http.Client{}
// 設置發起請求參數
re, err := http.NewRequest("GET", Url, nil)
// 錯誤處理
if err != nil {
fmt.Println(err)
}
// 設置請求頭 不設置請求頭會請求失敗
re.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36")
// 發起請求
resp, err := client.Do(re)
// 錯誤處理
if err != nil {
fmt.Println(err)
}
// 響應處理
if resp.StatusCode != 200 {
fmt.Println("請求失敗")
}
// 使用goquery 的方法 返回網站的html文檔
doc, err := goquery.NewDocumentFromReader(resp.Body)
//錯誤處理
if err != nil {
fmt.Println(err)
}
// 根據標簽和節點匹配到需要的內容
doc.Find("table tbody tr").Each(func(i int, s *goquery.Selection) {
ip := s.Find("td[data-title=IP]").Text() // ip
port := s.Find("td[data-title=PORT]").Text() //端口
anonymous := s.Find("td[data-title=匿名度]").Text() //匿名度
agreement := s.Find("td[data-title=類型]").Text() //類型
region := s.Find("td[data-title=位置]").Text() // 位置
speed := s.Find("td[data-title=響應速度]").Text() //響應速度
timeout := s.Find("td[data-title=最后驗證時間]").Text() // 最后驗證時間
// fmt.Println(ip, port, anonymous, agreement, region, speed, timeout) //檢查一下
proxyList = append(proxyList, Presult{
Ip: ip, //ip
Port: port, // port 端口
Anonymous: anonymous, // 匿名度
Agreement: agreement, //類型
Region: region, //地區
Speed: speed, //速度
Timeout: timeout, //最后驗證時間
})
})
// 輸出 這個結構體
return proxyList
}
// 發起請求 測試ip
func Requestproxy(proxyList []Presult, httpurl string) {
//fmt.Println(proxyList)
for _, p := range proxyList {
// 根據不同協議 測試
if p.Agreement == "HTTP" {
// 整理采集到的ip,輸出成 http://111.160.169.54:41820 協議 ip 端口 這種形式
proxyip := "http://" + p.Ip + ":" + p.Port
// 這里是請求對象 是一個 檢查訪問ip 返回的網站
httpurl := httpurl
// 格式化 代理ip
proxy, err := url.Parse(proxyip)
// 錯誤處理
if err != nil {
fmt.Println(err)
}
// 主要設置請求的代理ip 時長
netTransport := &http.Transport{
Proxy: http.ProxyURL(proxy),
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, time.Second*time.Duration(10))
if err != nil {
return nil, err
}
return c, nil
},
MaxIdleConnsPerHost: 10, //每個host最大空閑連接
ResponseHeaderTimeout: time.Second * time.Duration(5), //數據收發5秒超時
}
httpClient := &http.Client{
Timeout: time.Second * 10,
Transport: netTransport,
}
// 使用設置的代理ip 發起 get請求
res, err := httpClient.Get(httpurl)
if err != nil {
fmt.Println("ip:" + p.Ip + ",請求超時")
}
// 這里 res 可能是 nil 如果是nil 就會報錯panic: runtime error: invalid memory address or nil pointer dereference 變量不能指向nil
if res == nil {
fmt.Println("ip:" + p.Ip + ",請求超時")
} else {
// 關閉請求體 釋放資源
defer res.Body.Close()
//解析 收到的數據
body, _ := ioutil.ReadAll(res.Body)
//輸出
fmt.Println(string(body))
}
// 如果協議不是http 就會執行這里的。這里省略
} else if p.Agreement == "HTTPS" {
proxyip := "https://" + p.Ip + ":" + p.Port
fmt.Println(proxyip)
}
}
}
func main() {
proxyList := Collection("https://www.kuaidaili.com/free/")
Requestproxy(proxyList, "http://vv.video.qq.com/checktime?otype=json")
}
```
- 安裝開發環境
- 安裝開發環境
- 安裝詳細教程
- 引入包
- Go語言基礎
- 基本變量與數據類型
- 變量
- 數據類型
- 指針
- 字符串
- 代碼總結
- 常量與運算符
- 常量
- 運算符
- 流程控制
- if判斷
- for循環
- switch分支
- goto跳轉
- 斐波那契數列
- Go語言內置容器
- 數組
- 切片
- 映射
- 函數
- 函數(上)
- 函數(中)
- 函數(下)
- 小節
- 包管理
- 結構體
- 結構體(上)
- 結構體(中)
- 結構體(下)
- 小節
- 錯誤處理
- 錯誤處理
- 宕機
- 錯誤應用
- 小節
- 文件操作
- 獲取目錄
- 創建和刪除目錄
- 文件基本操作(上)
- 文件基本操作(中)
- 文件基本操作(下)
- 處理JSON文件
- 接口與類型
- 接口的創建與實現
- 接口賦值
- 接口嵌入
- 空接口
- 類型斷言(1)
- 類型斷言(2)
- 小節
- 并發與通道
- goroutine協程
- runtime包
- 通道channel
- 單向通道channel
- select
- 線程同步
- 多線程的深入學習
- http編程
- http簡介
- Client和Request
- get請求
- post請求
- 模塊函數方法
- 模塊
- fmt庫,模塊
- 項目練習
- 爬蟲:高三網
- 爬蟲:快代理
- 爬蟲:快代理2
- 多線程:通道思路
- 多線程爬蟲:快代理