整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Go語言從入門到精通-06| Web服務(wù)完善之HTM

          Go語言從入門到精通-06| Web服務(wù)完善之HTML文件支持

          面我們實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的Web服務(wù)器軟件。這個(gè)服務(wù)器軟件很傻,無論你的URL是什么,所有請(qǐng)求都只返回“Hello World!”字符串。而且這個(gè)字符串是寫死在代碼中的。

          接下來我們繼續(xù)完善這個(gè)Web服務(wù)器軟件,今天我們?cè)黾訉?duì)普通靜態(tài)文件的支持。也就是當(dāng)用戶通過瀏覽器向該服務(wù)器發(fā)送請(qǐng)求的時(shí)候該軟件會(huì)從磁盤上讀取相應(yīng)的文件,然后發(fā)送給瀏覽器。本次的完善也是很有限的,只對(duì)上次的代碼做了很小的改動(dòng)。這里實(shí)現(xiàn)的主要功能是從磁盤讀取一個(gè)文件的內(nèi)容,然后封裝http響應(yīng)頭后發(fā)生給瀏覽器。因此,這里主要涉及到Go語言文件訪問相關(guān)的庫的使用。最后實(shí)現(xiàn)的效果就是在瀏覽器上顯示html文件渲染后的內(nèi)容:

          圖1 實(shí)現(xiàn)效果圖

          文件訪問庫

          由于涉及到文件的訪問,因此這里先介紹一下文件相關(guān)的包。Go語言文件相關(guān)的操作在os包里面,其中os.File封裝了文件讀寫相關(guān)的操作。如下是os包及File涉及的主要函數(shù)和方法,由于篇幅問題,這里只保留的必要的內(nèi)容:

          type File

          File代表一個(gè)打開的文件對(duì)象。

          func Open(name string) (file *File, err error)

          Open打開一個(gè)文件用于讀取。如果操作成功,返回的文件對(duì)象的方法可用于讀取數(shù)據(jù);對(duì)應(yīng)的文件描述符具有O_RDONLY模式。如果出錯(cuò),錯(cuò)誤底層類型是*PathError。

          func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

          OpenFile是一個(gè)更一般性的文件打開函數(shù),大多數(shù)調(diào)用者都應(yīng)用Open或Create代替本函數(shù)。它會(huì)使用指定的選項(xiàng)(如O_RDONLY等)、指定的模式(如0666等)打開指定名稱的文件。如果操作成功,返回的文件對(duì)象可用于I/O。如果出錯(cuò),錯(cuò)誤底層類型是*PathError。

          func (f *File) Read(b []byte) (n int, err error)

          Read方法從f中讀取最多l(xiāng)en(b)字節(jié)數(shù)據(jù)并寫入b。它返回讀取的字節(jié)數(shù)和可能遇到的任何錯(cuò)誤。文件終止標(biāo)志是讀取0個(gè)字節(jié)且返回值err為io.EOF。

          func (f *File) Write(b []byte) (n int, err error)

          Write向文件中寫入len(b)字節(jié)數(shù)據(jù)。它返回寫入的字節(jié)數(shù)和可能遇到的任何錯(cuò)誤。如果返回值n!=len(b),本方法會(huì)返回一個(gè)非nil的錯(cuò)誤。

          func (f *File) Close() error

          Close關(guān)閉文件f,使文件不能用于讀寫。它返回可能出現(xiàn)的錯(cuò)誤。

          下面是本文實(shí)現(xiàn)的從文件讀取數(shù)據(jù)的方法,在Web服務(wù)的主程序中通過調(diào)用該方法來從磁盤讀取數(shù)據(jù)。這個(gè)方法的輸入是文件路徑,輸出是文件的內(nèi)容。

          圖2 文件讀取方法實(shí)現(xiàn)


          細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn),我們這里讀取數(shù)據(jù)并沒有用File的Read方法,而是用了另外一個(gè)包ioutil的ReadAll方法。這里使用ioutil包的方法也是作為一個(gè)引子,期望大家更多的了解Go語言提供的庫函數(shù)。該方法與File的Read方法功能是一樣的,但性能上要好一些。

          ioutil包是一個(gè)io相關(guān)的包,提供了對(duì)常見io操作的性能優(yōu)化,該包提供的功能主要包括:

          func ReadAll(r io.Reader) ([]byte, error)

          從一個(gè)io.Reader讀取所有數(shù)據(jù),并返回一個(gè)字節(jié)數(shù)組

          func ReadDir(dirname string) ([]os.FileInfo, error)

          從一個(gè)目錄讀取數(shù)據(jù),并得到這個(gè)目錄里的文件對(duì)象列表

          func ReadFile(filename string) ([]byte, error)

          讀取指定文件的內(nèi)容,并返回一個(gè)字節(jié)數(shù)組

          關(guān)于文件操作的相關(guān)介紹本文先到這里,更詳細(xì)的介紹我們后面專門另起新文介紹。

          Web服務(wù)修改

          Web服務(wù)端改動(dòng)的地方也很少,除了上面介紹的讀取文件內(nèi)容的方法外,在主函數(shù)中調(diào)整了數(shù)據(jù)發(fā)送方面的代碼,其它地方均沒有做改動(dòng)。下面是涉及到的代碼片段。

          圖3 服務(wù)端代碼修改

          如圖3所示,這里一共修改了3個(gè)地方:

          1. 讀取文件(固定的文件),并計(jì)算文件的長(zhǎng)度
          2. 構(gòu)造http響應(yīng)頭,這里主要是根據(jù)文件大小,調(diào)整Content-Length字段
          3. 分別發(fā)送響應(yīng)頭和響應(yīng)體

          測(cè)試驗(yàn)證

          完成上述修改后,我們就可以通過瀏覽器進(jìn)行驗(yàn)證了。這里需要具備一個(gè)html文件,該文件保存在與服務(wù)端相同的路徑下面,名稱為index.html。該文件的內(nèi)容如下:

          圖4 HTML文件內(nèi)容

          如果熟悉html的同學(xué),很清楚是做什么的,就是現(xiàn)實(shí)一個(gè)紅色的“Hello World!”字符串,不了解html的同學(xué)也沒關(guān)系,了解到這里就行。

          在服務(wù)端運(yùn)行程序, 瀏覽器數(shù)據(jù)地址后回車,可以看到如下內(nèi)容:

          圖5 最終效果圖


          好了,今天先到這,后面文章我們將增加對(duì)圖片的支持。

          ?

          輯部 發(fā)自 凹非寺
          量子位 報(bào)道 | 公眾號(hào) QbitAI

          日本疫苗,又雙叒上熱搜了。這一回還和AI有關(guān)。

          事情是醬嬸的,為了防止疫苗保管失誤(輝瑞疫苗要求-80℃保存),日本埼玉縣現(xiàn)在引入了一種新的冷凍室檢測(cè)系統(tǒng):

          △ 攝像頭監(jiān)測(cè)冰箱讀數(shù)(圖片來自NHK)

          用攝像頭盯著冰箱的讀數(shù),再用電腦軟件識(shí)別出來。

          當(dāng)溫度超出設(shè)定范圍后,就會(huì)向管理人員發(fā)出郵件警報(bào)。

          △ 電腦識(shí)別保管溫度(圖片來自NHK)

          不用天天盯著看,工作人員這下是開心了,但這攝像頭讀數(shù)字的操作被po上網(wǎng),歡樂的氣氛可就不是那么簡(jiǎn)單了。

          這不,微博、推特等社交平臺(tái)上,網(wǎng)友們都快吵翻了。


          △截自微博@英式?jīng)]品笑話百科

          一時(shí)笑瘋者有之:

          嘲諷者有之:這就是工匠精神!

          但也有網(wǎng)友替這群日本盆友表達(dá)了無奈:這也是現(xiàn)實(shí)所迫啊。

          事情這就有意思了。

          于是,本著科(jiu)學(xué)(shi)探(wan)究(er)的精神,我們決定好好研究一番:日本工作人員這波操作,到底是“就這”,還是靠譜。

          是愚蠢還是機(jī)智?

          所謂高手在民間,我們先翻翻評(píng)論區(qū),看看網(wǎng)友們都有什么小妙招。

          有人就問了:直接從冰箱的溫度數(shù)據(jù)上接出信號(hào)它不香嗎?

          就算設(shè)備太老,沒有數(shù)據(jù)輸出接口,那在冰箱里內(nèi)放置熱電偶,再將熱電偶接入到監(jiān)測(cè)系統(tǒng)中,不也更方便嗎?

          實(shí)在不行,換臺(tái)帶溫度監(jiān)控的冰箱不就得了,疫苗還不配一臺(tái)新冰箱嗎?

          那么,事情真的這么簡(jiǎn)單嗎?

          其實(shí),不少網(wǎng)友都點(diǎn)出了兩個(gè)關(guān)鍵字——成本

          畢竟說實(shí)在的,改造系統(tǒng)并非加裝個(gè)傳感器就完事兒了。

          我們稍微匯總一下網(wǎng)友們的觀點(diǎn):

          首先冰箱設(shè)備可能太舊,如果設(shè)備本身不提供數(shù)據(jù)接口,那么獲取數(shù)據(jù)并不方便,甚至要對(duì)設(shè)備進(jìn)行破壞性的改造。

          另外在冰箱內(nèi)伸入熱電偶,可能會(huì)破壞冰箱口的密封,況且還要在-80℃溫度下保證探頭高精度工作。

          還有一點(diǎn),冰箱是金屬外殼,無線傳輸數(shù)據(jù)也不可能。

          所以,外接攝像頭無疑是一種最簡(jiǎn)單有效的方式,一種典型的程序員思維。

          1. 攝像頭與原系統(tǒng)耦合度低,不僅可以用在這種冰箱上,還可以推廣到其他解決方案;
          2. 七段數(shù)碼管的OCR識(shí)別程序已經(jīng)相當(dāng)成熟,程序員可能只要一個(gè)小時(shí)就完成系統(tǒng)的全部改造。

          對(duì)于這樣的看法,不少日本網(wǎng)友表示了認(rèn)同:

          這個(gè)辦法很聰明,它不需要改造冰箱本身,也就不會(huì)破壞系統(tǒng)原來的穩(wěn)定性。

          不過,也有日本網(wǎng)友預(yù)感一個(gè)嶄新的背鍋俠已經(jīng)誕生了。未來一旦出事,原因可能是:

          (1)相機(jī)壞了;(2)溫度計(jì)壞了;(3)溫度計(jì)傳感器壞了;(4)監(jiān)控系統(tǒng)壞了。

          別問,問就是福島經(jīng)驗(yàn)。

          其實(shí)挺常見

          咳咳……

          我們還是先順著這個(gè)思路,去GitHub上搜索一番——在七段數(shù)碼管OCR識(shí)別方面,確實(shí)有許多用OpenCV實(shí)現(xiàn)的現(xiàn)成項(xiàng)目。其中,一個(gè)7年前的數(shù)碼管OCR項(xiàng)目就已經(jīng)能達(dá)到很高的精度。

          另外,國(guó)內(nèi)的AI商用平臺(tái)上也提供付費(fèi)OCR識(shí)別服務(wù),而且識(shí)別的情況比只讀取一個(gè)冰箱溫度要復(fù)雜得多。

          如此成熟的方案,你猜都被用在了哪里?

          其實(shí)在國(guó)內(nèi),變電站表計(jì)示數(shù)識(shí)讀方面,也有用類似的方法來替代人工操作。比如已經(jīng)有巡檢機(jī)器人配備了讀數(shù)的技能。

          當(dāng)然,這種場(chǎng)景之下的識(shí)別復(fù)雜度略高一些,因?yàn)椴⒉皇窍袢毡颈O(jiān)測(cè)疫苗的攝像頭,直接“懟”到了計(jì)數(shù)器前面,而是有一定的距離。

          而正是距離和自然環(huán)境等原因,還會(huì)出現(xiàn)光線、背景特征難提取等一系列的問題。

          但隨著計(jì)算機(jī)視覺技術(shù)越來越發(fā)達(dá)、攝像頭成本越來越低,這種解決方案在其他領(lǐng)域也越來越多地被采用。

          哦對(duì)了,隨著我們的進(jìn)一步好奇心肆虐,我們還發(fā)現(xiàn)……

          日本的工作人員不是拍腦袋決定的方案啊,引起這次熱議的攝像頭讀溫度系統(tǒng),是一個(gè)成熟的、正在售賣的完整商用系統(tǒng)。

          這家公司叫做Pacific Systems,官方介紹是這樣的:

          通過IoT自動(dòng)化日常監(jiān)控工作,減輕工作負(fù)擔(dān)!

          還醒目地提出安裝他家產(chǎn)品的優(yōu)點(diǎn):

          • 大幅削減工作時(shí)間,減少巡邏、記錄數(shù)據(jù)的工作量。
          • 無論是白天還是晚上,亦或是節(jié)假日,都可以不停歇的“工作”。
          • 不聯(lián)網(wǎng)也能正常工作,獲取數(shù)據(jù)。

          而且安裝也非常地簡(jiǎn)單,只需要接入攝像頭或其他設(shè)備即可,不需要對(duì)原來的機(jī)器做更改。

          還支持各種傳感器數(shù)據(jù),例如溫度、濕度,以及二氧化碳傳感器。

          而據(jù)日本網(wǎng)友透露,這么一套設(shè)備,價(jià)格從19.8萬日元起,也就是1萬元人民幣左右。

          好啦,事情的前因后果,傳送完畢。

          現(xiàn)在,你覺得日本埼玉縣的這種方法是愚蠢還是機(jī)智呢?

          參考鏈接:
          [1]https://www3.nhk.or.jp/news/html/20210610/k10013078621000.html
          [2]https://weibo.com/2123664205/Kkaymt6V2
          [3]https://prtimes.jp/main/html/rd/p/000000046.000061548.html

          — 完 —

          量子位 QbitAI · 頭條號(hào)簽約

          關(guān)注我們,第一時(shí)間獲知前沿科技動(dòng)態(tài)

          注天善智能↑,走好數(shù)據(jù)之路

          歡迎關(guān)注天善智能微信公眾號(hào),我們是專注于商業(yè)智能BI,大數(shù)據(jù),數(shù)據(jù)分析領(lǐng)域的垂直社區(qū)。

          對(duì)商業(yè)智能BI、大數(shù)據(jù)分析挖掘、機(jī)器學(xué)習(xí),python,R等數(shù)據(jù)領(lǐng)域感興趣的同學(xué)加微信:tstoutiao,邀請(qǐng)你進(jìn)入頭條數(shù)據(jù)愛好者交流群,數(shù)據(jù)愛好者們都在這兒。


          Emoji表情包天氣數(shù)據(jù)可視化

          用emoji表情來可視化北京2016年度每日天氣狀況!

          library(RCurl)library(XML)
          library(dplyr)
          library(stringr)
          library(tidyr)
          library(plyr)
          library(rvest)
          library(ggimage)
          library(Cairo)
          library(showtext)
          library(lubridate)

          url<-"http://lishi.tianqi.com/beijing/index.html"myheader <-c("User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")webpage<-getURL(url,httpheader=myheader)

          mymonthlink<-getHTMLLinks(url,externalOnly=TRUE)%>%grep(".*?2016\d{2}.html",.,value=T)

          剛開始的時(shí)候走了冤枉路,寫了一大段白花花的無用代碼!

          ####

          #page1<-getURL(mymonthlink[2],.encoding="gbk")

          #rd<-iconv(page1,"gbk","utf-8")

          #rdhtml<-htmlParse(rd,encoding="UTF-8")

          #cesh<-readHTMLList(rdhtml,trim=TRUE,elFun=xmlValue)%>%grep("\d{4}-\d{2}-\d{2}",.,value=T)<br>#cesh<-cesh%>%sub("([a-z])(\()(\\)","",.)

          #cesh<-cesh1%>%str_split(',')%>%plyr::ldply(.fun=NULL)

          #cesh$V1<-cesh$V1%>%sub("[a-z]\(","",.)%>%as.Date()<br>#names(cesh)<-c("date","high","low","state","wind","index")

          ####

          #以上代碼寫了一半寫不下去了,我有rvest為啥要用RCurl,肯定自己腦抽筋了!

          后來換個(gè)思路,過段 棄用了RCrul,轉(zhuǎn)投rvest去了!

          mynewdata<-c()for (i in mymonthlink){mymonthdata<-read_html(i,encoding="gbk")%>%html_nodes("div.tqtongji2>ul")%>%html_text(trim=FALSE)%>%str_trim(.,side="right")%>%.[-1]mynewdata<-c(mynewdata,mymonthdata)}mynewdata1<-mynewdatamynewdata<-mynewdata1%>%gsub("\t\t\t|\t|\r\n","",.)%>%str_split(' ')%>%plyr::ldply(.fun=NULL)%>%.[,-2]names(mynewdata)<-c("date","high","low","state","wind","index")mynewdata$date<-as.Date(mynewdata$date)mynewdata$high<-as.numeric(mynewdata$high)mynewdata$low<-as.numeric(mynewdata$low)

          #清晰臟數(shù)據(jù):unique(mynewdata$state) happy<-c("晴","陣雨~晴","多云轉(zhuǎn)晴","多云~晴","雷陣雨~晴","陰~晴","霾~晴","浮塵~晴") depressed<-c("霾","陰","多云","晴~多云","霾~多云","晴~霾","多云~霾","陣雨轉(zhuǎn)多云","多云轉(zhuǎn)陰","陰~多云","多云~陰","晴~陰","陣雨~多云","小雨~多云","小雨~陰","霾~霧","小雪~陰","陰~小雪","小雨~雨夾雪") angry<-c("小雨","雨夾雪","小雪","雷陣雨","陣雨","中雨","小到中雨","雷陣雨~陰","多云~雷陣雨","陰~雷陣雨","霾~雷陣雨","多云~陣雨","晴~陣雨","陰~小雨","陣雨~小雨") Terrified<-c("中到大雨","暴雨","雷陣雨~中到大雨")

          #創(chuàng)建新變量(主要是將諸多天氣類型進(jìn)行歸類):mynewdata$mode<-NULLmynewdata$mood<-ifelse(mynewdata$state%in% happy,"happy",ifelse(mynewdata$state%in% depressed,"depressed",ifelse(mynewdata$state%in% angry,"angry","Terrified"))) mynewdata <- within(mynewdata,{ mood_code <- NA mood_code[mood=="happy"]<-"1f604" mood_code[mood=="depressed"]<-"1f633" mood_code[mood=="angry"]<-"1f62d" mood_code[mood=="Terrified"]<-"1f621"})

          #創(chuàng)建時(shí)間與日期變量:mynewdata$month<-as.numeric(as.POSIXlt(mynewdata$date)$mon+1)mynewdata$monthf<-factor(mynewdata$month,levels=as.character(1:12),labels=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),ordered=TRUE) mynewdata$weekday<-as.POSIXlt(mynewdata$date)$wdaymynewdata$weekdayf<-factor(mynewdata$weekday,levels=rev(0:6),labels=rev(c("Sun","Mon","Tue","Wed","Thu","Fri","Sat")),ordered=TRUE)mynewdata$week <- as.numeric(format(mynewdata$date,"%W"))mynewdata<-ddply(mynewdata,.(monthf),transform,monthweek=1+week-min(week))mynewdata$day<-day(mynewdata$date)

          setwd("F:/數(shù)據(jù)可視化/R/R語言學(xué)習(xí)筆記/可視化/ggplot2/商務(wù)圖表")write.table(mynewdata,"historyweather.csv",sep=",",row.names=FALSE)mynewdata<-read.csv("historyweather.csv",stringsAsFactors=FALSE,check.names=FALSE)

          圖1的主題:

          mytheme<-theme( rect=element_blank(), axis.ticks=element_blank(), text=element_text(face="plain",lineheight=0.9,hjust=0.5,vjust=0.5,size=15), title=element_text(face="plain",lineheight=0.9,hjust=0,vjust=0.5,size=30), axis.title=element_blank(), strip.text=element_text(size=rel(0.8)), plot.margin=unit(c(5,2,5,2),"lines") )

          圖一效果:

          CairoPNG("emoji1.png",1000,870)

          showtext.begin()

          ggplot(mynewdata,aes(weekdayf,monthweek,fill=high))+

          geom_tile(colour='white')+scale_fill_gradient(low=NA, high=NA,guide=FALSE)+ggtitle("The emoji-weather visualization of beijing in 2016")+scale_y_reverse(breaks=seq(from=6,to=0,by=-1))+ggimage::geom_emoji(aes(image=mood_code),size=.1)+facet_wrap(~monthf ,nrow=3)+

          mythemeshowtext.end()

          dev.off()

          圖二主題:

          mytheme2<-theme(

          rect=element_blank(),

          axis.ticks=element_blank(), text=element_text(face="plain",lineheight=0.9,hjust=0.5,vjust=0.5,size=15), title=element_text(face="plain",lineheight=0.9,hjust=0,vjust=0.5,size=30), axis.title=element_blank(),

          strip.text=element_text(size=rel(0.8)),

          plot.margin=unit(c(1,1,1,1),"lines")

          )

          圖二效果:

          CairoPNG("emoji2.png",1200,1200)

          showtext.begin()

          ggplot(mynewdata,aes(x=factor(day),y=monthf,fill=high))+geom_tile(colour='white')+expand_limits(y=c(-12,12))+

          scale_x_discrete(position=c("bottom"))+

          coord_polar(theta="x")+

          scale_fill_gradient(low=NA,

          high=NA,guide=FALSE)+

          ggimage::geom_emoji(aes(image=mood_code),size=.015)+

          geom_image(aes(x=0,y=-12),image="weather.png", size=.15)+ggtitle("The emoji-weather visualization of beijing in 2016")+

          mytheme2

          showtext.end()

          dev.off()

          這個(gè)是圖二上面的背景小圖,從網(wǎng)上找的,嵌入代碼里的,沒有P圖哦.

          個(gè)人簡(jiǎn)介:


          轉(zhuǎn)自微信公眾號(hào):EasyCharts

          對(duì)商業(yè)智能BI、大數(shù)據(jù)分析挖掘、機(jī)器學(xué)習(xí),python,R等數(shù)據(jù)領(lǐng)域感興趣同學(xué)加微信:tstoutiao,邀請(qǐng)您加入頭條數(shù)據(jù)愛好者交流群,數(shù)據(jù)愛好者們都在這兒。


          主站蜘蛛池模板: 黑人一区二区三区中文字幕| 中文字幕无码一区二区免费| 亚洲国产视频一区| 国产一区二区三区在线看| 久久国产精品视频一区| 国产精品第一区第27页| 无码中文字幕乱码一区| 久久国产一区二区| 中文字幕在线视频一区| 一区二区三区视频在线播放| 日本一区二区三区不卡视频| 亚洲一区二区三区在线| 免费一区二区三区| 狠狠色婷婷久久一区二区三区| 卡通动漫中文字幕第一区| 国产精品成人一区无码| 成人无号精品一区二区三区| 国产一区二区好的精华液| 亚洲a∨无码一区二区| 人妻无码一区二区三区免费| 亚洲av福利无码无一区二区| 中文无码AV一区二区三区| 中文字幕亚洲一区| 中文字幕在线一区二区三区| 亚洲一区二区女搞男| 无码AV动漫精品一区二区免费| AV天堂午夜精品一区二区三区| 久久久久久免费一区二区三区| 国产情侣一区二区三区| 中文字幕无码一区二区三区本日 | 精品一区二区三区中文字幕| 全国精品一区二区在线观看| 国产伦一区二区三区免费| 日本一道一区二区免费看| 蜜芽亚洲av无码一区二区三区| 免费无码一区二区三区蜜桃大| 日韩久久精品一区二区三区 | 亚洲一区二区三区免费| 鲁大师成人一区二区三区| 国产在线一区二区在线视频| 熟妇人妻AV无码一区二区三区|