思路:把需要爬取的url放入通道,多線程爬取。但是這個快代理有點拉,把我ip拉黑了
```
package main
import (
"fmt"
"net/http"
"strconv"
"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(urljob <-chan string) {
for j := range urljob {
// 用這個結構體儲存 請求返回的結果
proxyList := []Presult{}
// 創建一個請求客戶端
client := &http.Client{}
// 設置發起請求參數
re, err := http.NewRequest("GET", j, 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, //最后驗證時間
})
})
// 輸出 這個結構體
fmt.Println(proxyList)
time.Sleep(time.Second)
}
}
func main() {
// 創建一個通道
urljob := make(chan string, 1000)
// 將準備爬取的url 放入通道
for i := 1; i < 10; i++ {
urls := "https://www.kuaidaili.com/free/inha/" + strconv.Itoa(i) + "/"
urljob <- urls
}
// 關閉
close(urljob)
// 創建2個goroutine
for j := 1; j < 5; j++ {
go Collection(urljob)
time.Sleep(time.Second * 10)
}
}
```
- 安裝開發環境
- 安裝開發環境
- 安裝詳細教程
- 引入包
- Go語言基礎
- 基本變量與數據類型
- 變量
- 數據類型
- 指針
- 字符串
- 代碼總結
- 常量與運算符
- 常量
- 運算符
- 流程控制
- if判斷
- for循環
- switch分支
- goto跳轉
- 斐波那契數列
- Go語言內置容器
- 數組
- 切片
- 映射
- 函數
- 函數(上)
- 函數(中)
- 函數(下)
- 小節
- 包管理
- 結構體
- 結構體(上)
- 結構體(中)
- 結構體(下)
- 小節
- 錯誤處理
- 錯誤處理
- 宕機
- 錯誤應用
- 小節
- 文件操作
- 獲取目錄
- 創建和刪除目錄
- 文件基本操作(上)
- 文件基本操作(中)
- 文件基本操作(下)
- 處理JSON文件
- 接口與類型
- 接口的創建與實現
- 接口賦值
- 接口嵌入
- 空接口
- 類型斷言(1)
- 類型斷言(2)
- 小節
- 并發與通道
- goroutine協程
- runtime包
- 通道channel
- 單向通道channel
- select
- 線程同步
- 多線程的深入學習
- http編程
- http簡介
- Client和Request
- get請求
- post請求
- 模塊函數方法
- 模塊
- fmt庫,模塊
- 項目練習
- 爬蟲:高三網
- 爬蟲:快代理
- 爬蟲:快代理2
- 多線程:通道思路
- 多線程爬蟲:快代理