美文网首页
go http服务器/客户端

go http服务器/客户端

作者: 今早上 | 来源:发表于2018-04-28 15:59 被阅读0次

服务器端简单例子:

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
)

// hello world, the web server
// w: 给客户端回复数据, req: 读取客户端发送的数据
func HelloServer(w http.ResponseWriter, req *http.Request) {
    // 打印客户端头信息
    fmt.Println(req.Method)
    fmt.Println(req.Header)
    fmt.Println(req.Body)
    fmt.Println(req.URL)

    // 给客户端回复数据
    io.WriteString(w, "hello, world!\n")
    w.Write([]byte("lisa"))
}
func main() {
    // 注册函数,用户连接, 自动调用指定处理函数
    http.HandleFunc("/hello", HelloServer)

    // 监听绑定
    err := http.ListenAndServe(":12345", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

客户端简单例子

package main

import (
    "fmt"
    "net/http"
)

func main() {

    respon, err := http.Get("http://www.baidu.com")
    if err != nil {
        fmt.Println("http.get:", err)
        return
    }
    // 关闭
    defer respon.Body.Close()

    fmt.Println("status:", respon.Status)
    fmt.Println("header:", respon.Header)
    fmt.Println("StatusCode:", respon.StatusCode)

    //fmt.Println("body:", respon.Body)
    //body是一个指针地址,需要读
    var tmp string

    buf := make([]byte, 1024*4)

    for {
        n, err := respon.Body.Read(buf)
        if n == 0 {
            fmt.Println("Body.Read err:", err)
            break
        }
        tmp += string(buf[:n])
    }
    fmt.Println("body:", tmp)
}

贴吧单线程爬取例子

package main

import (
    "fmt"
    "net/http"
    "os"
    "strconv"
)

func main() {
    var start, end int

    fmt.Println("请输入起始页(>=1):")
    fmt.Scan(&start)
    fmt.Println("请输入终止页(>=1):")
    fmt.Scan(&end)

    DoWork(start, end)
}

func DoWork(start, end int) {
    //提示信息
    fmt.Printf("正在爬取 %d 到 %d 页面\n", start, end)

    for i := start; i <= end; i++ {
        url := "http://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.Println(url)
        resp, err := SpiderPage(url)
        if err != nil {
            fmt.Println("SpiderPage:", err)
            continue //这里要用continue
        }

        // 获取到内容然后写入文件
        fileName := strconv.Itoa(i) + ".html"
        // 新建文件(会覆盖)
        f, fErr := os.Create(fileName)
        if fErr != nil {
            fmt.Println("os.Create:", fErr)
            continue //这里要用continue
        }
        // 写入信息
        f.WriteString(resp)
        f.Close()
    }
}

// 爬取
func SpiderPage(url string) (resp string, err error) {

    // 获取内容
    resp1, err1 := http.Get(url)
    if err1 != nil {
        err = err
        return
    }
    defer resp1.Body.Close()

    // 如果没错就获取内容
    buf := make([]byte, 1024*4)
    for {
        // 读body内容
        n, bErr := resp1.Body.Read(buf)
        if n == 0 { // 读取结束或者出问题
            fmt.Println("resp.Body.Read:", bErr)
            break //这里读取结束要break,n=0就是结束
        }
        resp += string(buf[:n])
    }
    return
}

贴吧多线程爬虫简单例子

package main

import (
    "fmt"
    "net/http"
    "os"
    "strconv"
)

// 声明一个管道,来保证爬取完毕
var page = make(chan int)

func main() {
    var start, end int

    fmt.Println("请输入起始页(>=1):")
    fmt.Scan(&start)
    fmt.Println("请输入终止页(>=1):")
    fmt.Scan(&end)

    DoWork(start, end)
}

func DoWork(start, end int) {
    //提示信息
    fmt.Printf("正在爬取 %d 到 %d 页面\n", start, end)

    for i := start; i <= end; i++ {

        // 封装函数, 开协成
        go SpiderPage(i)

        // 管道阻塞
        // fmt.Printf("第%d页爬完了\n", <-page)

    }

    // 记住一定要单独接收管道消息!!!
    for i := start; i <= end; i++ {
        //管道阻塞
        fmt.Printf("第%d页爬完了\n", <-page)

    }

}

func SpiderPage(i int) {
    url := "http://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.Println(url)
    resp, err := GetUrlContent(url)
    if err != nil {
        fmt.Println("SpiderPage:", err)
        return
    }

    // 获取到内容然后写入文件
    fileName := strconv.Itoa(i) + ".html"
    // 新建文件(会覆盖)
    f, fErr := os.Create(fileName)
    if fErr != nil {
        fmt.Println("os.Create:", fErr)
        return
    }
    // 写入信息
    f.WriteString(resp)
    f.Close()

    // 爬完一个就给管道传递数据
    page <- i
}

// 爬取
func GetUrlContent(url string) (resp string, err error) {

    // 获取内容
    resp1, err1 := http.Get(url)
    if err1 != nil {
        err = err
        return
    }
    defer resp1.Body.Close()

    // 如果没错就获取内容
    buf := make([]byte, 1024*4)
    for {
        // 读body内容
        n, bErr := resp1.Body.Read(buf)
        if n == 0 { // 读取结束或者出问题
            fmt.Println("resp.Body.Read:", bErr)
            break //这里读取结束要break,n=0就是结束
        }
        resp += string(buf[:n])
    }
    return
}

多线程爬取多个页面例子

package main

import (
    "fmt"
    "net/http"
    "os"
    "strings"
    //"os"
    "regexp"
    "strconv"
)

// 声明一个管道,来保证爬取完毕
var page = make(chan int)

func main() {
    var start, end int

    fmt.Println("请输入起始页(>=1):")
    fmt.Scan(&start)
    fmt.Println("请输入终止页(>=1):")
    fmt.Scan(&end)

    DoWork(start, end) //工作函数
}

func DoWork(start, end int) {
    //提示信息
    fmt.Printf("正在爬取 %d 到 %d 页面\n", start, end)

    for i := start; i <= end; i++ {

        // 定义一个函数,爬取主页面
        go SpiderPage(i)

    }

    // 记住一定要单独接收管道消息!!!
    for i := start; i <= end; i++ {
        //管道阻塞
        fmt.Printf("第%d页爬完了\n", <-page)

    }

}

func SpiderPage(i int) {
    url := "https://www.pengfu.com/xiaohua_" + strconv.Itoa(i) + ".html"
    // 爬取内容
    fmt.Println(url)

    resp, err := GetUrlContent(url)
    if err != nil {
        fmt.Println("GetUrlContent:", err)
        return
    }
    // 正则表达式取内容
    re := regexp.MustCompile(`<h1 class="dp-b"><a href="(?s:(.*?))"`)
    if re == nil {
        fmt.Println("regexp.MustCompile err")
        return
    }
    // 取关键信息
    joyUrls := re.FindAllStringSubmatch(resp, -1) //-1代表所有
    //fmt.Println(joyUrls)

    // 切片
    fileTitle := make([]string, 0)
    fileContent := make([]string, 0)

    //第一个返回下标,第二个返回值
    for _, data := range joyUrls {
        // 获取每一个对应到的url
        title, content, err := SpiderOneJoy(data[1])
        if err != nil {
            fmt.Println("SpiderOneJoy err", err)
            continue
        }
        //      fmt.Printf("title=#%v#", title)
        //      fmt.Printf("content=#%v#", content)
        fileTitle = append(fileTitle, title)
        fileContent = append(fileContent, content)
    }

    // 写成文件
    StoreJoyToFile(i, fileTitle, fileContent)
}

// 写入文件
func StoreJoyToFile(i int, fileTitle, fileContent []string) {
    // 新建文件
    f, err := os.Create(strconv.Itoa(i) + ".txt")
    if err != nil {
        fmt.Println("os.create err", err)
        return
    }

    defer f.Close()

    // 写内容
    n := len(fileTitle)
    for i := 0; i < n; i++ {
        f.WriteString(fileTitle[i] + "\n")
        f.WriteString(fileContent[i] + "\n")
        f.WriteString("\n===============\n")
    }
    // 爬完了
    page <- i
    return
}

// 爬取单个内容
func SpiderOneJoy(url string) (title string, content string, err error) {
    // 获取内容,发送get请求
    resp1, err1 := GetUrlContent(url)
    if err1 != nil {
        err = err1
        return
    }

    // 正则取关键信息
    // 取标题
    re1 := regexp.MustCompile(`<h1>(?s:(.*?))</h1>`)
    if re1 == nil {
        // 返回error
        err = fmt.Errorf("%s", "regexp.MustCompile title err")
        return
    }
    tmpTitle := re1.FindAllStringSubmatch(resp1, 1) //1过滤一个
    for _, data := range tmpTitle {
        title = data[1]
        // 处理换行
        //title = strings.Replace(title, "\n", "", -1)
        //title = strings.Replace(title, "\r", "", -1)
        //title = strings.Replace(title, " ", "", -1)
        title = strings.Replace(title, "\t", "", -1)

        break // 防止有多次直接break
    }

    // 取内容
    re2 := regexp.MustCompile(`<div class="content-txt pt10">(?s:(.*?))<a id="prev"`)
    if re2 == nil {
        // 返回error
        err = fmt.Errorf("%s", "regexp.MustCompile content err")
        return
    }
    tmpContent := re2.FindAllStringSubmatch(resp1, -1)
    for _, data := range tmpContent {
        content = data[1]
        // 处理换行
        content = strings.Replace(content, "\n", "", -1)
        content = strings.Replace(content, "\r", "", -1)
        content = strings.Replace(content, "<br />", "", -1)
        content = strings.Replace(content, "\t", "", -1)
        content = strings.Replace(content, "<br>", "", -1)
        break // 防止有多次直接break
    }

    return

}

// 爬取
func GetUrlContent(url string) (resp string, err error) {

    // 获取内容,发送get请求
    resp1, err1 := http.Get(url)
    if err1 != nil {
        err = err1
        return
    }
    defer resp1.Body.Close()

    // 如果没错就获取内容
    buf := make([]byte, 1024*4)
    for {
        // 读body内容
        n, bErr := resp1.Body.Read(buf)
        if n == 0 { // 读取结束或者出问题
            fmt.Println("resp.Body.Read:", bErr)
            break //这里读取结束要break,n=0就是结束
        }
        resp += string(buf[:n])
    }
    return
}

相关文章

  • go http学习笔记

    go http学习笔记 @[goweb, go, http] 1.go http基础 go http服务器简例 h...

  • go http服务器/客户端

    服务器端简单例子: 客户端简单例子 贴吧单线程爬取例子 贴吧多线程爬虫简单例子 多线程爬取多个页面例子

  • 网络通信 udp+tcp+http

    本文包括udp客户端、udp服务器、tcp客户端、tcp服务器、http客户端、http服务器 net包提供了可移...

  • node 小记(0418)http

    什么是http及相关知识 http客户端发起请求,创建端口 http服务器在端口监听客户端请求 http服务器向客...

  • node.js-http模块深入理解

    http模块主要用于搭建HTTP服务端和客户端,使用HTTP服务器或客户端功能都必须调用http模块。 创建服务器...

  • Go 调试

    Go的pprof使用 web服务器 import _"net/http/pprof" go func() { ...

  • IOS 网络请求构建--HTTP简介

    HTTP 介绍 1. HTTP请求与响应 HTTP请求遵循着客户端-服务器范式请求步鄹序列:客户端建立一个到服务器...

  • http请求生命周期流程

    HTTP 请求/相应 1、客户端连接到Web服务器 一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口...

  • 第三章 HTTP报文内的报文信息

    HTTP 通信过程包括从客户端发往服务器端的请求及从服务器端返回客户端的响应。 HTTP报文 用于 HTTP 协议...

  • 7. Nginx, uwsgi, uWSGI

    Nginx 静态的HTTP服务器把服务器上的静态文件通过HTTP协议展示给客户端。 反向代理服务器客户端和网站服务...

网友评论

      本文标题:go http服务器/客户端

      本文链接:https://www.haomeiwen.com/subject/xzbglftx.html