思路:把需要爬取的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
- 多线程:通道思路
- 多线程爬虫:快代理