【golang】2、http client、代理、爬图

news2024/11/18 4:07:27

文章目录

  • 一、http client
  • 二、反向代理
    • 2.1 http
    • 2.2 gin
  • 三、爬取并存储 jpg

在这里插入图片描述

用 golang 可以很方便的爬图(http 下载图片,存储为 jpg 格式)。

一、http client

http client 有如下最佳实践:

  • 尽量用 default http client:默认的 http client 设置了很多合适的参数(如超时、连接池),也便于在各请求间复用(如先将获取到的 token 存储到 client 内,后续所有请求都可用此 token)
  • 要设置 timeout:防止因网络 or 下游 server 的问题,而盲等,导致自己阻塞,降低拥堵体验
  • 谨慎处理 redirects:若 server 不存在某资源时可能会用 3xx redirect 到新目的地。然而若 client 未合适处理,可能导致 loop redirect。因此需要如下做法:
    • 校验 redirect url
    • 限制 redirect 次数
  • reuse connections:可用连接池实现,可减少新建连接的开销、降低延迟、增加流量。
  • 默认会打开 Keep-Alive,除非需求是在一个连接上的数据请求密度不高则可手动关闭。详见实验

二、反向代理

正向代理、反向代理 区别

2.1 http

package main

import (
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

// NewProxy 拿到 remoteURL 后,创建一个反向代理
func NewProxy(remoteURL string) (*httputil.ReverseProxy, error) {
	remote, err := url.Parse(remoteURL)
	if err != nil {
		return nil, err
	}

	proxy := httputil.NewSingleHostReverseProxy(remote)
	proxy.Director = func(req *http.Request) {
		//req.Header = ctx.Request.Header
		req.Host = remote.Host
		req.URL.Scheme = remote.Scheme
		req.URL.Host = remote.Host
		req.URL.Path = "/metrics"
	}

	return proxy, nil
}

// ProxyRequestHandler 使用 proxy 处理请求
func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) { proxy.ServeHTTP(w, r) }
}

func main() {
	proxy, err := NewProxy("http://127.0.0.1:7000/metrics") // 初始化反向代理并传入真正后端服务的地址
	if err != nil {
		panic(err)
	}
	http.HandleFunc("/api/proxy/metrics", ProxyRequestHandler(proxy)) // 使用 proxy 处理所有请求到你的服务
	log.Fatal(http.ListenAndServe(":8080", nil))
}

2.2 gin

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"net/http/httputil"
	"net/url"
)

// NewProxy 拿到 remoteURL 后,创建一个反向代理
func NewProxy(remoteURL string) (*httputil.ReverseProxy, error) {
	remote, err := url.Parse(remoteURL)
	if err != nil {
		return nil, err
	}

	proxy := httputil.NewSingleHostReverseProxy(remote)
	proxy.Director = func(req *http.Request) {
		//req.Header = ctx.Request.Header
		req.Host = remote.Host
		req.URL.Scheme = remote.Scheme
		req.URL.Host = remote.Host
		req.URL.Path = "/metrics"
	}

	return proxy, nil
}

func proxy(c *gin.Context) {
	proxy, err := NewProxy("http://127.0.0.1:7000/metrics") // 初始化反向代理并传入真正后端服务的地址
	if err != nil {
		panic(err)
	}
	proxy.ServeHTTP(c.Writer, c.Request)
}

func main() {
	r := gin.Default()
	r.GET("/api/proxy/metrics", proxy)
	r.Run(":8080")
}

三、爬取并存储 jpg

package clients

import (
	"fmt"
	"github.com/sirupsen/logrus"
	"gitlab.deepglint.com/yuchuansun/petroltools/configs"
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

var httpCli = &http.Client{
	Timeout: 10 * time.Second,
}

type spiderCli struct {
	httpCli *http.Client
	txtFile *os.File
}

func Spider() *spiderCli {
	txtFile, err := os.OpenFile(configs.TxtFileName(), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		logrus.Fatal(err)
	}
	return &spiderCli{
		httpCli: httpCli,
		txtFile: txtFile,
	}
}

func (c *spiderCli) Download(url string) ([]byte, error) {
	res, err := c.httpCli.Get(url)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if res.StatusCode == http.StatusNotFound {
		return nil, fmt.Errorf("got invalid status code: %v", res.StatusCode)
	}
	return io.ReadAll(res.Body)
}

// Save img.jpg and txt
func (c *spiderCli) Save(fid int64, bytes []byte, plateText, plateColor, plateType string) error {
	// img
	fImgName := fmt.Sprintf("%v.jpg", fid)
	fImg, err := os.Create(fImgName)
	if err != nil {
		return err
	}
	defer fImg.Close()
	writtenImg, err := fImg.Write(bytes)
	if err != nil {
		return err
	}
	if writtenImg == 0 {
		os.Remove(fImgName)
	}
	// txt
	line := strings.Join([]string{fImgName, plateText, plateColor, plateType}, ",")
	writtenTxt, err := c.txtFile.WriteString(line + "\n")
	_ = writtenTxt
	return err
}

func (c *spiderCli) Close() {
	c.txtFile.Close()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/591939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小米万兆路由器里的 Docker 安装 chatgpt-next-web,打造自己的专属ChatGPT

小米万兆路由器里的 Docker 安装 chatgpt-next-web,打造自己的专属ChatGPT 0. 先体验一下效果1. 准备工作2. 查看Docker Hub镜像信息3. 拉取 ChatGPT-Next-Web 镜像和运行容器4. 感谢99. (Optional)其他 小米2022年12月份发布了万兆路由器,里面可以使用D…

挑战高通!智能座舱升级战

和智能驾驶相比,智能座舱无疑是智能化普及的领跑角色。 高工智能汽车研究院监测数据显示,2022年中国市场(不含进出口)乘用车搭载智能数字座舱(大屏语音车联网OTA)前装标配交付795.05万辆,同比增…

01. docker安装青龙面板 基于阿里云centos7服务器(保姆级图文)

目录 1. 安装docker2. 在终端中安装青龙面板3. 开放端口4. 访问青龙面板总结 欢迎关注 『青龙面板』 专栏,持续更新中 欢迎关注 『青龙面板』 专栏,持续更新中 1. 安装docker 在宝塔面板的软件商店中安装docker 2. 在终端中安装青龙面板 安装命令如下…

DTM在新交易平台的落地 | 业务平台

一、项目背景 在项目的发展过程中,我们将整个新交易平台(业务平台部专门为360集团内部打造的类似有赞、微盟的交易系统)微服务化,产生了店铺服务、商品服务、订单服务、优惠券服务、红包服务、用户服务、支付服务、履约服务、售后服务等等。并且这些服务…

前端系列17集-和公司架构师在学习vue3-springboot

SyntaxError: "undefined" is not valid JSON at JSON.parse (<anonymous>) 这个错误通常意味着你正在尝试将一个非 JSON 格式的数据转换成 JSON 格式。为了修复这个问题&#xff0c;你需要找到导致错误的代码行并检查它的输入数据是否符合 JSON 格式标准。 这…

chatgpt赋能python:Python中构造函数的作用

Python中构造函数的作用 Python是一种高级编程语言&#xff0c;其强大的面向对象编程&#xff08;OOP&#xff09;功能是其流行的主要原因之一。在Python中&#xff0c;通过使用构造函数可以轻松创建对象实例&#xff0c;并为对象的属性赋值。在本文中&#xff0c;我们将介绍P…

剖析CPU性能火焰图生成的内部原理

关注开发内功修炼&#xff0c;掌握硬核技术原理 大家好&#xff0c;我是飞哥&#xff01; 在进行CPU性能优化的时候&#xff0c;我们经常先需要分析出来我们的应用程序中的CPU资源在哪些函数中使用的比较多&#xff0c;这样才能高效地优化。一个非常好的分析工具就是《性能之巅…

到底什么是“5G新通话”?

今天这篇文章&#xff0c;我们来聊聊今年很热门的一个概念——“5G新通话”。 小枣君当年第一次听说“5G新通话”的时候&#xff0c;还以为是VoNR的“新马甲”。 后来&#xff0c;仔细研究了一下&#xff0c;我才知道&#xff0c;原来“5G新通话”并不是VoNR&#xff0c;而是Vo…

chatgpt赋能python:Python中的构造函数

Python 中的构造函数 Python 是一门广泛应用于各种应用领域的高级编程语言&#xff0c;它支持不同的编程范式&#xff0c;包括面向对象编程。在面向对象编程中&#xff0c;构造函数是一个重要的概念。本文将介绍 Python 中的构造函数&#xff0c;并介绍如何使用它们来创建对象…

PFTL201C 10KN 3BSE007913R0010 专为测量该分力而设计

在许多带材加工中&#xff0c;带材张力会在轧辊上产生一个水平分力...或者&#xff0c;通过设计&#xff0c;它可以做到这一点。概述使用该水平分力测量带材张力非常有利。称重传感器的尺寸可仅测量带材张力&#xff0c;不包括辊的皮重。结果是优化了测量精度。另一个优势是ABB…

以支付宝为例,聊聊Web安全的三个攻防姿势

我们最常见的Web安全攻击有以下几种 XSS 跨站脚本攻击CSRF 跨站请求伪造clickjacking 点击劫持/UI-覆盖攻击 下面我们来逐个分析 一、XSS 跨站脚本攻击 跨站脚本攻击&#xff08;Cross Site Scripting&#xff09;&#xff0c;为了不和层叠样式表&#xff08;Cascading Styl…

直播倒计时 1 天 | SOFAChannel#33《Occlum x EDMM=更安全好用的机密计算 LibOS》

Occlum 是蚂蚁集团于 2019 年开源的机密计算操作系统&#xff0c;也是 Linux 基金会机密计算联盟官方项目&#xff0c;荣列 2021“科创中国”开源创新榜。2022 年 12 月 10 日&#xff0c;Occlum 正式发布 v1.0 版本。学术成果发表在 ASPLOS20。Occlum 可让复杂应用轻松获得机密…

冷气机、空调扇、饮水机、液晶驱动VK0256C LQFP52段码LCD液晶显示驱动芯片技术资料

品牌&#xff1a;永嘉微电/VINKA 型号&#xff1a;VK0256C 封装形式&#xff1a;LQFP52 年份&#xff1a;新年份 KPP2649 概述: VK0256C是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大256点&#xff08;32EGx8COM&#xff09;的LCD屏。单片机可通过3/4线串行接口配…

界面控件DevExpress WinForms全新的UI模板,解决各种业务线需求!

去年秋天DevExpress官方发布了一个新的 WinForms UI模板预览版&#xff08;第一个EAP只提供给DevExpress宇宙版激活的用户&#xff09; &#xff0c;这些精炼的、随时可用的“模板”旨在启动表单设计/开发过程。有了这个模板&#xff0c;用户可以创建/交付现成的UI解决方案&…

ISO21434 分布式网络安全(四)

目录 一、概述 二、目标 三、输入 四、要求和建议 4.1 供应商能力 4.2 报价申请 4.3 责任的协调 五、输出 一、概述 如果分发了一个项目或组件的网络安全活动的责任&#xff0c;则适用本条款。 本条款描述了对分布式网络安全活动的管理&#xff0c;并适用于&#xff1a…

win10没有hyper-v功能解决方法

1.在Win10搜索框,搜索PowerShell 2.打开 Windows PowerShell&#xff0c;输入 systeminfo 命令 如果四个全为 “是”&#xff0c;则表示支持 Hyper-V 功能 3.桌面新建一个记事本文件&#xff0c;将它的后缀改成bat&#xff0c;复制下面的代码 pushd "%~dp0"dir /b …

5、USB协议学习:USB的枚举过程

文章目录 枚举顺序枚举过程标准请求bmRequestTypebReqest请求类型 GetDescriptor设备描述符设备描述符定义获取设备描述符返回设备描述符 配置描述符配置描述符定义获取配置描述符返回配置描述符 接口描述符&端点描述符&HID描述符接口描述符定义返回接口描述符HID描述符…

基于 ESP32 的高级气象站,带有 BME280 和实时天气数据

在这个项目中,我们将学习如何创建一个气象站,它将在网络服务器中显示来自 BME280 模块的读数和来自 OpenWeatherMap API 的实时天气数据。该设备将从 BME280 传感器获取温度、湿度、气压和高度,并从 OpenWeatherMap API 获取外部温度、湿度、天气状况以及日出和日落。我们可…

基于springboot+vue的校园二手交易市场

一、项目背景介绍&#xff1a; 校园二手交易市场是大学生生活中的重要组成部分&#xff0c;它为学生提供了一个便捷的方式来买卖物品。然而&#xff0c;传统的校园二手交易方式存在着信息不对称、交易风险高等问题。为了解决这些问题&#xff0c;基于Spring Boot和Vue的校园二手…

从瀚海到万家,易开得为净水器开辟新航道

前不久&#xff0c;我们报道过一家净水器品牌易开得&#xff0c;将“航母展台”搬到了家电行业展的事情。不仅现场观众纷纷前去打卡&#xff0c;网络读者们也都倍感神奇直呼666。 大众的兴奋感从何而来呢&#xff1f;我想是因为航母这类“重器”和卫星、导弹、航天飞机一样&…