zoukankan      html  css  js  c++  java
  • [GO]并发的网络爬虫

    package main
    
    import (
        "fmt"
        "strconv"
        "net/http"
        "os"
        "io"
    )
    
    //百度贴吧的地址规律
    //第一页:https://tieba.baidu.com/f?kw=%E7%BB%9D%E5%9C%B0%E6%B1%82%E7%94%9F&ie=utf-8(&pn=0)
    //第二页:https://tieba.baidu.com/f?kw=%E7%BB%9D%E5%9C%B0%E6%B1%82%E7%94%9F&ie=utf-8&pn=50
    //第三页:https://tieba.baidu.com/f?kw=%E7%BB%9D%E5%9C%B0%E6%B1%82%E7%94%9F&ie=utf-8&pn=100
    //所以它的最后的数字每加50,代表着下一页
    
    //整体提取的思路:
    //1、先拿地址
    //2、爬
    //3、取
    //4、存
    
    func HttpGet(url string) (result string, err error) {
        resp, err1 := http.Get(url)
        if err != nil {
            err = err1
            return
        }
        defer resp.Body.Close()
        //读取网页的body内容
        buf := make([]byte, 4*1024)
        for true {
            n, err := resp.Body.Read(buf)
            if err != nil {
                if err == io.EOF{
                    fmt.Println("文件读取完毕")
                    break
                }else {
                    fmt.Println("resp.Body.Read err = ", err)
                    break
                }
            }
            result += string(buf[:n])
        }
        return
    }
    
    //爬取一个网页
    func SpiderPage(i int, page chan <- int)  {
        url := "https://tieba.baidu.com/f?kw=%E7%BB%9D%E5%9C%B0%E6%B1%82%E7%94%9F&ie=utf-8&pn=" + strconv.Itoa((i-1)*50)
        fmt.Printf("正在爬取第%d个网页
    ", i)
        //爬,将所有的网页内容爬取下来
        result, err := HttpGet(url)
        if err != nil {
            fmt.Println("http.Get err = ", err)
            return
        }
        //把内容写入到文件
        filename := strconv.Itoa((i-1)*50) + ".html"
        f, err1 := os.Create(filename)
        if err1 != nil{
            fmt.Println("os.Create err = ", err1)
            return
        }
        //写内容
        f.WriteString(result)
        //关闭文件
        f.Close()
        //每爬完一个,就给个值
        page<-i
    }
    
    func DoWork(start, end int)  {
        fmt.Printf("正在爬取第%d页到%d页
    ", start, end)
        //因为很有可能爬虫还没有结束下面的循环就已经结束了,所以这里就需要且到通道
        page := make(chan int)
        for i:=start; i<=end; i++ {
            //将page阻塞
            go SpiderPage(i, page)
        }
        for i:=start; i<=end; i++ {
            fmt.Printf("第%d个页面爬取完成
    ",<-page)//这里直接将面码传给点位符,值直接从管道里取出
        }
    }
    
    func main() {
        var start, end int
        fmt.Printf("请输入起始页>=1:> ")
        fmt.Scan(&start)
        fmt.Printf("请输入结束页:> ")
        fmt.Scan(&end)
        DoWork(start, end)
    }

    这里带来的是效率上的提升

  • 相关阅读:
    释放jQuery 的$ 的使用权
    jQuery 入口函数主要有4种写法
    jQuery的 ready() 和原生 Js onload() 的主要区别:
    简单的单击图片循环播放
    Jsの练习-数组其他常用方法 -map() ,filter() ,every() ,some()
    Jsの练习-数组常用方法 -forEach()
    stylelint和eslint的VS插件配置
    工作中遇到的bug
    VUE关于data对象中数组修改和对象添加属性的响应式问题
    VUE的watch监听对象
  • 原文地址:https://www.cnblogs.com/baylorqu/p/9705549.html
Copyright © 2011-2022 走看看