文章采集api
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 162 次瀏覽 ? 2022-05-14 20:49
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 91 次瀏覽 ? 2022-05-13 16:48
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 130 次瀏覽 ? 2022-05-09 10:00
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
干掉 Swagger + Postman?測試接口直接生成API文檔
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 81 次瀏覽 ? 2022-05-09 04:25
?、?點(diǎn)擊右上角的【+】按鈕,我們來(lái)新建一個(gè)頁(yè)面,編寫(xiě)一個(gè)用戶(hù)注冊的 API 接口文檔。
新建頁(yè)面
?、?點(diǎn)擊【API 接口模板】按鈕,ShowDoc 會(huì )幫我們生成 API 接口文檔的示例,采用的是 Markdown 的格式。
API 接口模板
?、?簡(jiǎn)單修改 Markdown 的內容,然后點(diǎn)擊右上角的【保存】按鈕,生成文檔。
保存接口
?、?點(diǎn)擊右上角的【返回】按鈕,可以看到剛創(chuàng )建的 API 接口文檔。
接口預覽
在右邊,艿艿圈了【分享】【目錄】【歷史版本】三個(gè)按鈕,胖友可以自己去體驗下。
ShowDoc 提供 API 接口的 Mock 功能,方便后端在定義 API 接口后,提供模擬數據。
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的右邊的【編輯頁(yè)面】按鈕,然后點(diǎn)擊【Mock】按鈕,我們可以看到一個(gè) Mock 的彈窗。
Mock 彈窗
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
友情提示:ShowDoc 提供的 Mock 能力還是比較基礎的,實(shí)際項目中,我們可能希望根據不同的請求參數,返回不同的 Mock 結果。
如果胖友有這塊需求,可以看看 YApi: 。
通過(guò)手寫(xiě) Markdown 的方式,生成 API 文檔的方式,是非常非常非常繁瑣 的?。?!所以,ShowDoc 自己也不推薦采用這種方式,而是主推 RunApi 工具,一邊調試接口,一邊自動(dòng)生成 。
咱先看看 RunApi 的自我介紹,也是賊長(cháng)一大串:
RunApi 是一個(gè)以接口為核心的開(kāi)發(fā)測試工具(功能上類(lèi)似 Postman)。
目前有客戶(hù)端版(推薦,支持 Win/Mac/Linux全平臺)和在線(xiàn)精簡(jiǎn)版 ,包含接口測試 / 自動(dòng)流程測試 / Mock 數據 / 項目協(xié)作等功能。
它和 ShowDoc 相輔相成:
相信使用 ShowDoc + RunApi 這兩個(gè)工具組合,能夠極大地提高IT團隊的效率。
管你看沒(méi)看懂,跟著(zhù)艿艿一起,體驗一下就完事了!
?、?在 地址下,提供了不同操作系統的 RunApi 客戶(hù)端的下載。
客戶(hù)端
?、?下載并安裝完成后,使用 ShowDoc 注冊的賬號,進(jìn)行登陸。
Runapi 登陸
雖然我們在 ShowDoc 中,已經(jīng)新建了項目,但是我們在 RunApi 中是無(wú)法看到的。因此,我們需要重新新建屬于 RunApi 的項目。
項目對比
?、?點(diǎn)擊 RunApi 客戶(hù)端的【新建項目】按鈕,填寫(xiě)項目名和描述,然后點(diǎn)擊【確認】按鈕進(jìn)行保存。
新建項目
?、?瀏覽器刷新 ShowDoc 頁(yè)面,可以看到剛創(chuàng )建的項目。
查看項目
?、?點(diǎn)擊【+】按鈕,選擇要新增的類(lèi)型為“帶調試功能的API接口”。
新建 API 接口
?、?啟動(dòng)一個(gè) Spring Boot 項目,提供一個(gè)需要調試的 API 接口。
友情提示:胖友可以克隆 項目,使用 lab-24/lab-24-apidoc-showdoc 示例。
嘿嘿,順手求個(gè) Star 關(guān)注,艿艿寫(xiě)了 40000+ Spring Boot 和 Spring Cloud 的使用示例代碼。
啟動(dòng) Spring Boot 項目
?、?使用 RunApi 調試下 /users/login 接口。
調試 API 接口
?、?點(diǎn)擊【返回示例和參數說(shuō)明】,補全返回結果的接口文檔。
補全響應結果
?、?點(diǎn)擊【保存】按鈕,生成 API 接口文檔。
?、?點(diǎn)擊【文檔鏈接】按鈕,獲得 API 接口文檔的地址。
文檔鏈接
?、?點(diǎn)擊 API 文檔的訪(fǎng)問(wèn)鏈接,查看 API 文檔。
RunAPI 文檔預覽
當然,我們也可以在 ShowDoc 中,進(jìn)行訪(fǎng)問(wèn)。
ShowDoc 文檔預覽
有一點(diǎn)要注意,使用 RunApi 生成的 API 接口文檔,無(wú)法在使用 Markdown 進(jìn)行編輯噢!原因也很簡(jiǎn)單,編寫(xiě)后的 Markdown 文件,可能會(huì )導致無(wú)法逆向被 RunApi 使用,格式被破壞了!
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的下邊的【Mock】按鈕,我們可以看到一個(gè) Mock 的界面。
Mock 界面
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
RunApi 還提供了 3 個(gè)高級特性,胖友后面可以自己體驗下。
強烈推薦 ?。?!
環(huán)境變量
例如說(shuō),設置“本地環(huán)境”、“測試環(huán)境”等多套環(huán)境變量,方便模擬請求不通過(guò)環(huán)境下的 API 噢。
前執行腳本
例如說(shuō),可以模擬登陸,獲得用戶(hù)的訪(fǎng)問(wèn) token 令牌。
后執行腳本
例如說(shuō),斷言響應的結果,是否為期望的 200 。
RunApi 提供的自動(dòng) 生成 API 接口文檔的方式,確實(shí)能夠避免一部分煩瑣 的手寫(xiě) Markdown 的過(guò)程。同時(shí),它能夠結合我們日常開(kāi)發(fā),模擬調用 API 接口的時(shí),復用了請求參數與響應結果。
但是我們如果仔細去思考,這是不是意味著(zhù)可能此時(shí)此刻,我們已經(jīng)開(kāi)發(fā)完 API 接口了?!那么,假如團隊采用的是前后端分離的架構,并且前端和后端是兩撥人,那么前端會(huì )希望后端提前就定義好 API 接口的文檔,而不是在后端具體完成好 API 接口的開(kāi)發(fā)后,再提供接口文檔。
所以我們在使用 RunApi 的時(shí)候,有可能是先使用它來(lái)**“手動(dòng)”** 定義好 API 接口文檔,然后復用它來(lái)模擬測試 API 接口。
嘿嘿~胖友也可以思考下,結合 RunApi 的這種模式,怎么結合到我們的日常開(kāi)發(fā)流程中,歡迎留言討論。
ShowDoc 支持通過(guò)掃描代碼注釋的方式,自動(dòng)生成 API 接口文檔,目前自持 Java、C++、PHP、Node 等等主流的編程語(yǔ)言。
艿艿看了下官方文檔 對這塊功能的介紹,感受上使用體驗會(huì )非常不好。一起來(lái)看下官方提供的示例:
????/**<br />????*?showdoc<br />????*?@catalog?測試文檔/用戶(hù)相關(guān)<br />????*?@title?用戶(hù)登錄<br />????*?@description?用戶(hù)登錄的接口<br />????*?@method?get<br />????*?@url?https://www.showdoc.cc/home/user/login<br />????*?@header?token?可選?string?設備token?<br />????*?@param?username?必選?string?用戶(hù)名?<br />????*?@param?password?必選?string?密碼??<br />????*?@param?name?可選?string?用戶(hù)昵稱(chēng)??<br />????*?@return?{"error_code":0,"data":{"uid":"1","username":"12154545","name":"吳系掛","groupid":2,"reg_time":"1436864169","last_login_time":"0"}}<br />????*?@return_param?groupid?int?用戶(hù)組id<br />????*?@return_param?name?string?用戶(hù)昵稱(chēng)<br />????*?@remark?這里是備注信息<br />????*?@number?99<br />????*/<br />????public?Object?login(String?username,?String?password,?String?name)?{<br />????????//?...?省略具體代碼<br />????}<br />
需要使用到 @catalog、@title 等等自定義的注釋標簽,且原有的 @param 需要安裝一定的格式來(lái)保證 API 接口的參數的說(shuō)明,@return 的示例會(huì )導致注釋非常長(cháng)。
自定義注釋
這樣就導致,雖然只使用代碼注釋的方式,實(shí)際對代碼還是有一定的入侵,影響代碼的可讀性。
還是老樣子,我們使用 項目,lab-24/lab-24-apidoc-showdoc 示例,編寫(xiě)一個(gè) users/login2 接口,并使用 ShowDoc 掃碼 Java代碼注釋?zhuān)?API 接口文檔。
?、?下載 腳本,到項目的根目錄。
下載 showdoc_api 腳本
?、?在項目的設置頁(yè),獲得 ShowDoc 的開(kāi)放 API 的 api_key 和 api_token 秘鑰對。
進(jìn)入項目的設置頁(yè)獲得 api_key 和 api_token 秘鑰對
?、?修改 showdoc_api.sh 腳本,設置剛獲得的 api_key 和 api_token 秘鑰對。
設置 api_key 和 api_token 秘鑰對
?、?編寫(xiě) users/login2 接口,添加 ShowDoc 所需的注釋。
編寫(xiě) users/login2 接口
是不是看著(zhù)就蠻亂的,IDEA 還報錯 @param 找不到 username 和 password 參數。
?、?執行 showdoc_api.sh 腳本,掃描 Java代碼注釋?zhuān)?API 接口文檔。
生成 API 接口文檔
?、?查看生成 API 接口文檔。
查看 API 接口文檔
如果胖友希望基于 Java 注釋生成 API 接口文檔,艿艿還是相對 JApiDocs 工具。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 JApiDocs 入門(mén)》 文章。
JApiDocs 效果
ShowDoc 提供給了開(kāi)放 API 的方式,導入 Markdown 文檔。所以,我們可以編寫(xiě)程序,調用它的 API 接口,創(chuàng )建或更新 API 接口文檔。
開(kāi)放 API 的官方文檔文檔地址是, 。
接口地址 :
接口參數 :
接口參數
我們來(lái)導入一個(gè)簡(jiǎn)單的文檔,效果如下圖所示:
{<br />??"api_key":?"60fc53cea6af4758c1686cb22ba20566472255580",<br />??"api_token":?"0bbb5f564a9ee66333115b1abb8f8d541979489118",<br />??"page_title":?"公眾號",<br />??"page_content":?"芋道源碼,求一波關(guān)注呀~"<br />}<br />
友情提示:api_key 和 api_token 參數,記得改成自己的秘鑰對,不然就導入到艿艿的項目里啦~~~
調用開(kāi)放 API文檔效果
在新建項目時(shí),ShowDoc 支持導入 Swagger 或者 Postman 的 JSON 文檔,方便我們快速遷移到 ShowDoc 作為 API 接口的平臺。
我們來(lái)體驗下 ShowDoc 提供的導入 Swagger 文檔的功能,使用 項目,lab-24/lab-24-apidoc-swagger-starter 示例,提供的 Swagger JSON 文件。
?、?啟動(dòng) Spring Boot 項目,獲得其 Swagger JSON 文件。
下載 Swagger JSON 文件
友情提示:胖友也可以訪(fǎng)問(wèn) 地址,直接進(jìn)行下載!
?、?新建 ShowDoc 項目,點(diǎn)擊【導入文件】,選擇 Swagger JSON 文件。
導入 Swagger JSON 文件
?、?導入完成后,點(diǎn)擊自動(dòng)新建的項目,查看下導入的 API 文檔的效果。
導入 Swagger JSON 文件
接口都成功導入了,可惜 Swagger 中的 example 都缺失了,這就導致我們需要手動(dòng)補全下接口的示例。
ShowDoc 目前只支持新建項目時(shí),導入 Swagger 接口文檔。但是如果 Swagger 接口文檔變更時(shí),無(wú)法進(jìn)行更新 ShowDoc 中的文檔。
如果我們僅僅是把 Swagger 遷移到 ShowDoc 中,肯定是基本能夠滿(mǎn)足。但是,如果我們希望使用 Swagger 編寫(xiě)接口文檔,手動(dòng)或者自動(dòng)導入 ShowDoc 進(jìn)行展示,這樣就無(wú)法滿(mǎn)足了。
這里艿艿推薦下 YApi 工具,支持定時(shí)采集 Swagger 接口,智能 合并 API 接口文檔。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 YApi 入門(mén)》 文章。
YApi + Swagger
在上家公司,艿艿就采用 Swagger + YApi 的組合,Swagger 方便后端編寫(xiě) API 接口文檔,YApi 提供接口的展示 、編輯 、Mock 、調試 、自動(dòng)化測試 。
ShowDoc 支持通過(guò)掃描數據庫,自動(dòng)生成表結構的數據庫文檔。
對應的官方文檔地址是, 。
下面, 我們來(lái)把艿艿的一個(gè)開(kāi)源項目 的數據庫,導入 ShowDoc 生成數據庫文檔。
?、?下載 腳本,并設置數據庫相關(guān)的參數。
下載 show_db 腳本
?、?執行 show_db 腳本,看到“成功”說(shuō)明成功。查看數據庫文檔的效果,效果還是還不錯。
查看數據庫文檔
國內還有一款不錯的數據庫文檔的生成工具 Screw,具體可以看看艿艿寫(xiě)的《芋道 Spring Boot 數據表結構文檔》,地址是 。
演示效果
至此,我們已經(jīng)完成 ShowDoc 的入門(mén),還是蠻不錯的一個(gè)工具。做個(gè)簡(jiǎn)單的小總結:
Talk is Cheap,胖友可以選擇動(dòng)手玩玩 ShowDoc 工具。
- END -
歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長(cháng)按下方二維碼噢:
已在知識星球更新源碼解析如下:
最近更新《芋道 SpringBoot 2.X 入門(mén)》系列,已經(jīng) 101 余篇,覆蓋了MyBatis、Redis、MongoDB、ES、分庫分表、讀寫(xiě)分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。
提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務(wù)項目。 查看全部
干掉 Swagger + Postman?測試接口直接生成API文檔
?、?點(diǎn)擊右上角的【+】按鈕,我們來(lái)新建一個(gè)頁(yè)面,編寫(xiě)一個(gè)用戶(hù)注冊的 API 接口文檔。
新建頁(yè)面
?、?點(diǎn)擊【API 接口模板】按鈕,ShowDoc 會(huì )幫我們生成 API 接口文檔的示例,采用的是 Markdown 的格式。
API 接口模板
?、?簡(jiǎn)單修改 Markdown 的內容,然后點(diǎn)擊右上角的【保存】按鈕,生成文檔。
保存接口
?、?點(diǎn)擊右上角的【返回】按鈕,可以看到剛創(chuàng )建的 API 接口文檔。
接口預覽
在右邊,艿艿圈了【分享】【目錄】【歷史版本】三個(gè)按鈕,胖友可以自己去體驗下。
ShowDoc 提供 API 接口的 Mock 功能,方便后端在定義 API 接口后,提供模擬數據。
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的右邊的【編輯頁(yè)面】按鈕,然后點(diǎn)擊【Mock】按鈕,我們可以看到一個(gè) Mock 的彈窗。
Mock 彈窗
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
友情提示:ShowDoc 提供的 Mock 能力還是比較基礎的,實(shí)際項目中,我們可能希望根據不同的請求參數,返回不同的 Mock 結果。
如果胖友有這塊需求,可以看看 YApi: 。
通過(guò)手寫(xiě) Markdown 的方式,生成 API 文檔的方式,是非常非常非常繁瑣 的?。?!所以,ShowDoc 自己也不推薦采用這種方式,而是主推 RunApi 工具,一邊調試接口,一邊自動(dòng)生成 。
咱先看看 RunApi 的自我介紹,也是賊長(cháng)一大串:
RunApi 是一個(gè)以接口為核心的開(kāi)發(fā)測試工具(功能上類(lèi)似 Postman)。
目前有客戶(hù)端版(推薦,支持 Win/Mac/Linux全平臺)和在線(xiàn)精簡(jiǎn)版 ,包含接口測試 / 自動(dòng)流程測試 / Mock 數據 / 項目協(xié)作等功能。
它和 ShowDoc 相輔相成:
相信使用 ShowDoc + RunApi 這兩個(gè)工具組合,能夠極大地提高IT團隊的效率。
管你看沒(méi)看懂,跟著(zhù)艿艿一起,體驗一下就完事了!
?、?在 地址下,提供了不同操作系統的 RunApi 客戶(hù)端的下載。
客戶(hù)端
?、?下載并安裝完成后,使用 ShowDoc 注冊的賬號,進(jìn)行登陸。
Runapi 登陸
雖然我們在 ShowDoc 中,已經(jīng)新建了項目,但是我們在 RunApi 中是無(wú)法看到的。因此,我們需要重新新建屬于 RunApi 的項目。
項目對比
?、?點(diǎn)擊 RunApi 客戶(hù)端的【新建項目】按鈕,填寫(xiě)項目名和描述,然后點(diǎn)擊【確認】按鈕進(jìn)行保存。
新建項目
?、?瀏覽器刷新 ShowDoc 頁(yè)面,可以看到剛創(chuàng )建的項目。
查看項目
?、?點(diǎn)擊【+】按鈕,選擇要新增的類(lèi)型為“帶調試功能的API接口”。
新建 API 接口
?、?啟動(dòng)一個(gè) Spring Boot 項目,提供一個(gè)需要調試的 API 接口。
友情提示:胖友可以克隆 項目,使用 lab-24/lab-24-apidoc-showdoc 示例。
嘿嘿,順手求個(gè) Star 關(guān)注,艿艿寫(xiě)了 40000+ Spring Boot 和 Spring Cloud 的使用示例代碼。
啟動(dòng) Spring Boot 項目
?、?使用 RunApi 調試下 /users/login 接口。
調試 API 接口
?、?點(diǎn)擊【返回示例和參數說(shuō)明】,補全返回結果的接口文檔。
補全響應結果
?、?點(diǎn)擊【保存】按鈕,生成 API 接口文檔。
?、?點(diǎn)擊【文檔鏈接】按鈕,獲得 API 接口文檔的地址。
文檔鏈接
?、?點(diǎn)擊 API 文檔的訪(fǎng)問(wèn)鏈接,查看 API 文檔。
RunAPI 文檔預覽
當然,我們也可以在 ShowDoc 中,進(jìn)行訪(fǎng)問(wèn)。
ShowDoc 文檔預覽
有一點(diǎn)要注意,使用 RunApi 生成的 API 接口文檔,無(wú)法在使用 Markdown 進(jìn)行編輯噢!原因也很簡(jiǎn)單,編寫(xiě)后的 Markdown 文件,可能會(huì )導致無(wú)法逆向被 RunApi 使用,格式被破壞了!
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的下邊的【Mock】按鈕,我們可以看到一個(gè) Mock 的界面。
Mock 界面
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
RunApi 還提供了 3 個(gè)高級特性,胖友后面可以自己體驗下。
強烈推薦 ?。?!
環(huán)境變量
例如說(shuō),設置“本地環(huán)境”、“測試環(huán)境”等多套環(huán)境變量,方便模擬請求不通過(guò)環(huán)境下的 API 噢。
前執行腳本
例如說(shuō),可以模擬登陸,獲得用戶(hù)的訪(fǎng)問(wèn) token 令牌。
后執行腳本
例如說(shuō),斷言響應的結果,是否為期望的 200 。
RunApi 提供的自動(dòng) 生成 API 接口文檔的方式,確實(shí)能夠避免一部分煩瑣 的手寫(xiě) Markdown 的過(guò)程。同時(shí),它能夠結合我們日常開(kāi)發(fā),模擬調用 API 接口的時(shí),復用了請求參數與響應結果。
但是我們如果仔細去思考,這是不是意味著(zhù)可能此時(shí)此刻,我們已經(jīng)開(kāi)發(fā)完 API 接口了?!那么,假如團隊采用的是前后端分離的架構,并且前端和后端是兩撥人,那么前端會(huì )希望后端提前就定義好 API 接口的文檔,而不是在后端具體完成好 API 接口的開(kāi)發(fā)后,再提供接口文檔。
所以我們在使用 RunApi 的時(shí)候,有可能是先使用它來(lái)**“手動(dòng)”** 定義好 API 接口文檔,然后復用它來(lái)模擬測試 API 接口。
嘿嘿~胖友也可以思考下,結合 RunApi 的這種模式,怎么結合到我們的日常開(kāi)發(fā)流程中,歡迎留言討論。
ShowDoc 支持通過(guò)掃描代碼注釋的方式,自動(dòng)生成 API 接口文檔,目前自持 Java、C++、PHP、Node 等等主流的編程語(yǔ)言。
艿艿看了下官方文檔 對這塊功能的介紹,感受上使用體驗會(huì )非常不好。一起來(lái)看下官方提供的示例:
????/**<br />????*?showdoc<br />????*?@catalog?測試文檔/用戶(hù)相關(guān)<br />????*?@title?用戶(hù)登錄<br />????*?@description?用戶(hù)登錄的接口<br />????*?@method?get<br />????*?@url?https://www.showdoc.cc/home/user/login<br />????*?@header?token?可選?string?設備token?<br />????*?@param?username?必選?string?用戶(hù)名?<br />????*?@param?password?必選?string?密碼??<br />????*?@param?name?可選?string?用戶(hù)昵稱(chēng)??<br />????*?@return?{"error_code":0,"data":{"uid":"1","username":"12154545","name":"吳系掛","groupid":2,"reg_time":"1436864169","last_login_time":"0"}}<br />????*?@return_param?groupid?int?用戶(hù)組id<br />????*?@return_param?name?string?用戶(hù)昵稱(chēng)<br />????*?@remark?這里是備注信息<br />????*?@number?99<br />????*/<br />????public?Object?login(String?username,?String?password,?String?name)?{<br />????????//?...?省略具體代碼<br />????}<br />
需要使用到 @catalog、@title 等等自定義的注釋標簽,且原有的 @param 需要安裝一定的格式來(lái)保證 API 接口的參數的說(shuō)明,@return 的示例會(huì )導致注釋非常長(cháng)。
自定義注釋
這樣就導致,雖然只使用代碼注釋的方式,實(shí)際對代碼還是有一定的入侵,影響代碼的可讀性。
還是老樣子,我們使用 項目,lab-24/lab-24-apidoc-showdoc 示例,編寫(xiě)一個(gè) users/login2 接口,并使用 ShowDoc 掃碼 Java代碼注釋?zhuān)?API 接口文檔。
?、?下載 腳本,到項目的根目錄。
下載 showdoc_api 腳本
?、?在項目的設置頁(yè),獲得 ShowDoc 的開(kāi)放 API 的 api_key 和 api_token 秘鑰對。
進(jìn)入項目的設置頁(yè)獲得 api_key 和 api_token 秘鑰對
?、?修改 showdoc_api.sh 腳本,設置剛獲得的 api_key 和 api_token 秘鑰對。
設置 api_key 和 api_token 秘鑰對
?、?編寫(xiě) users/login2 接口,添加 ShowDoc 所需的注釋。
編寫(xiě) users/login2 接口
是不是看著(zhù)就蠻亂的,IDEA 還報錯 @param 找不到 username 和 password 參數。
?、?執行 showdoc_api.sh 腳本,掃描 Java代碼注釋?zhuān)?API 接口文檔。
生成 API 接口文檔
?、?查看生成 API 接口文檔。
查看 API 接口文檔
如果胖友希望基于 Java 注釋生成 API 接口文檔,艿艿還是相對 JApiDocs 工具。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 JApiDocs 入門(mén)》 文章。
JApiDocs 效果
ShowDoc 提供給了開(kāi)放 API 的方式,導入 Markdown 文檔。所以,我們可以編寫(xiě)程序,調用它的 API 接口,創(chuàng )建或更新 API 接口文檔。
開(kāi)放 API 的官方文檔文檔地址是, 。
接口地址 :
接口參數 :
接口參數
我們來(lái)導入一個(gè)簡(jiǎn)單的文檔,效果如下圖所示:
{<br />??"api_key":?"60fc53cea6af4758c1686cb22ba20566472255580",<br />??"api_token":?"0bbb5f564a9ee66333115b1abb8f8d541979489118",<br />??"page_title":?"公眾號",<br />??"page_content":?"芋道源碼,求一波關(guān)注呀~"<br />}<br />
友情提示:api_key 和 api_token 參數,記得改成自己的秘鑰對,不然就導入到艿艿的項目里啦~~~
調用開(kāi)放 API文檔效果
在新建項目時(shí),ShowDoc 支持導入 Swagger 或者 Postman 的 JSON 文檔,方便我們快速遷移到 ShowDoc 作為 API 接口的平臺。
我們來(lái)體驗下 ShowDoc 提供的導入 Swagger 文檔的功能,使用 項目,lab-24/lab-24-apidoc-swagger-starter 示例,提供的 Swagger JSON 文件。
?、?啟動(dòng) Spring Boot 項目,獲得其 Swagger JSON 文件。
下載 Swagger JSON 文件
友情提示:胖友也可以訪(fǎng)問(wèn) 地址,直接進(jìn)行下載!
?、?新建 ShowDoc 項目,點(diǎn)擊【導入文件】,選擇 Swagger JSON 文件。
導入 Swagger JSON 文件
?、?導入完成后,點(diǎn)擊自動(dòng)新建的項目,查看下導入的 API 文檔的效果。
導入 Swagger JSON 文件
接口都成功導入了,可惜 Swagger 中的 example 都缺失了,這就導致我們需要手動(dòng)補全下接口的示例。
ShowDoc 目前只支持新建項目時(shí),導入 Swagger 接口文檔。但是如果 Swagger 接口文檔變更時(shí),無(wú)法進(jìn)行更新 ShowDoc 中的文檔。
如果我們僅僅是把 Swagger 遷移到 ShowDoc 中,肯定是基本能夠滿(mǎn)足。但是,如果我們希望使用 Swagger 編寫(xiě)接口文檔,手動(dòng)或者自動(dòng)導入 ShowDoc 進(jìn)行展示,這樣就無(wú)法滿(mǎn)足了。
這里艿艿推薦下 YApi 工具,支持定時(shí)采集 Swagger 接口,智能 合并 API 接口文檔。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 YApi 入門(mén)》 文章。
YApi + Swagger
在上家公司,艿艿就采用 Swagger + YApi 的組合,Swagger 方便后端編寫(xiě) API 接口文檔,YApi 提供接口的展示 、編輯 、Mock 、調試 、自動(dòng)化測試 。
ShowDoc 支持通過(guò)掃描數據庫,自動(dòng)生成表結構的數據庫文檔。
對應的官方文檔地址是, 。
下面, 我們來(lái)把艿艿的一個(gè)開(kāi)源項目 的數據庫,導入 ShowDoc 生成數據庫文檔。
?、?下載 腳本,并設置數據庫相關(guān)的參數。
下載 show_db 腳本
?、?執行 show_db 腳本,看到“成功”說(shuō)明成功。查看數據庫文檔的效果,效果還是還不錯。
查看數據庫文檔
國內還有一款不錯的數據庫文檔的生成工具 Screw,具體可以看看艿艿寫(xiě)的《芋道 Spring Boot 數據表結構文檔》,地址是 。
演示效果
至此,我們已經(jīng)完成 ShowDoc 的入門(mén),還是蠻不錯的一個(gè)工具。做個(gè)簡(jiǎn)單的小總結:
Talk is Cheap,胖友可以選擇動(dòng)手玩玩 ShowDoc 工具。
- END -
歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長(cháng)按下方二維碼噢:
已在知識星球更新源碼解析如下:
最近更新《芋道 SpringBoot 2.X 入門(mén)》系列,已經(jīng) 101 余篇,覆蓋了MyBatis、Redis、MongoDB、ES、分庫分表、讀寫(xiě)分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。
提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務(wù)項目。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 146 次瀏覽 ? 2022-05-09 04:23
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
如何使用新一代輕量級分布式日志管理神器 Graylog 來(lái)收集日志
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 97 次瀏覽 ? 2022-05-04 14:05
公眾號關(guān)注「奇妙的 Linux 世界」
設為「星標」,每天帶你玩轉 Linux !
當我們公司內部部署很多服務(wù)以及測試、正式環(huán)境的時(shí)候,查看日志就變成了一個(gè)非常剛需的需求了。是多個(gè)環(huán)境的日志統一收集,然后使用 Nginx 對外提供服務(wù),還是使用專(zhuān)用的日志收集服務(wù) ELK 呢?
這就變成了一個(gè)問(wèn)題!而 Graylog 作為整合方案,使用 Elasticsearch 來(lái)存儲,使用 MongoDB 來(lái)緩存,并且還有帶流量控制的(throttling),同時(shí)其界面查詢(xún)簡(jiǎn)單易用且易于擴展。所以,使用 Graylog 成為了不二之選,為我們省了不少心。
1Filebeat 工具介紹
Filebeat 日志文件托運服務(wù)
Filebeat 是一個(gè)日志文件托運工具,在你的服務(wù)器上安裝客戶(hù)端后,Filebeat 會(huì )自動(dòng)監控給定的日志目錄或者指定的日志文件,追蹤讀取這些文件,不停的讀取,并且轉發(fā)這些信息到 Elasticsearch 或者 Logstarsh 或者 Graylog 中存放。
Filebeat 工作流程介紹
當你安裝并啟用 Filebeat 程序的時(shí)候,它會(huì )啟動(dòng)一個(gè)或多個(gè)探測器(prospectors)去檢測你指定的日志目錄或文件,對于探測器找出的每一個(gè)日志文件,Filebeat 都會(huì )啟動(dòng)一個(gè)收割進(jìn)程(harvester),每一個(gè)收割進(jìn)程讀取一個(gè)日志文件的最新內容,并發(fā)送這些新的日志數據到處理程序(spooler),處理程序會(huì )集合這些事件,最后 Filebeat 會(huì )發(fā)送集合的數據到你指定的地址上去(我們這里就是發(fā)送給 Graylog 服務(wù)了)。
Filebeat 圖示理解記憶
我們這里不適用 Logstash 服務(wù),主要是因為 Filebeat 相比于 Logstash 更加輕量級。當我們需要收集信息的機器配置或資源并不是特別多時(shí),且并沒(méi)有那么復雜的時(shí)候,還是建議使用 Filebeat 來(lái)收集日志。日常使用中,Filebeat 的安裝部署方式多樣且運行十分穩定。
圖示服務(wù)架構理解記憶2Filebeat 配置文件
配置 Filebeat 工具的核心就是如何編寫(xiě)其對應的配置文件!
對應 Filebeat 工具的配置主要是通過(guò)編寫(xiě)其配置文件來(lái)控制的,對于通過(guò) rpm 或者 deb 包來(lái)安裝的情況,配置文件默認會(huì )存儲在,/etc/filebeat/filebeat.yml 這個(gè)路徑下面。而對于,對于 MAC 或者 Win 系統來(lái)說(shuō),請查看解壓文件中相關(guān)文件,其中都有涉及。
下面展示了 Filebeat 工具的主配置文件,注釋信息中都對其各個(gè)字段含義進(jìn)行了詳細的解釋?zhuān)疫@里就不再贅述了。需要注意的是,我們將日志的輸入來(lái)源統統定義去讀取 inputs.d 目錄下的所有 yml 配置。所以,我們可以更加不用的服務(wù)(測試、正式服務(wù))來(lái)定義不同的配置文件,根據物理機部署的實(shí)際情況具體配置。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br /><br />
下面展示一個(gè)簡(jiǎn)單的 inputs.d 目錄下面的 yml 配置文件的具體內容,其主要作用就是配置單獨服務(wù)的獨立日志數據,以及追加不同的數據 tag 類(lèi)型。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br />
需要注意的是,針對于不同的日志類(lèi)型,filebeat 還提供了不同了模塊來(lái)配置不同的服務(wù)日志以及其不同的模塊特性,比如我們常見(jiàn)的 PostgreSQl、Redis、Iptables 等。
#?iptables<br />-?module:?iptables<br />??log:<br />????enabled:?true<br />????var.paths:?["/var/log/iptables.log"]<br />????var.input:?"file"<br /><br />#?postgres<br />-?module:?postgresql<br />??log:<br />????enabled:?true<br />????var.paths:?["/path/to/log/postgres/*.log*"]<br /><br />#?nginx<br />-?module:?nginx<br />??access:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/access.log*"]<br />??error:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/error.log*"]<br />
3Graylog 服務(wù)介紹
服務(wù)日志收集方案:Filebeat + Graylog!
Graylog 日志監控系統
Graylog 是一個(gè)開(kāi)源的日志聚合、分析、審計、展現和預警工具。在功能上來(lái)說(shuō),和 ELK 類(lèi)似,但又比 ELK 要簡(jiǎn)單很多。依靠著(zhù)更加簡(jiǎn)潔,高效,部署使用簡(jiǎn)單的優(yōu)勢很快受到許多人的青睞。當然,在擴展性上面確實(shí)沒(méi)有比 ELK 好,但是其有商業(yè)版本可以選擇。
Graylog 工作流程介紹
部署 Graylog 最簡(jiǎn)單的架構就是單機部署,復雜的也是部署集群模式,架構圖示如下所示。我們可以看到其中包含了三個(gè)組件,分別是 Elasticsearch、MongoDb 和 Graylog。其中,Elasticsearch 用來(lái)持久化存儲和檢索日志文件數據(IO 密集),MongoDb 用來(lái)存儲關(guān)于 Graylog 的相關(guān)配置,而 Graylog 來(lái)提供 Web 界面和對外接口的(CPU 密集)。
最小化單機部署
最優(yōu)化集群部署4Graylog 組件功能
配置 Graylog 服務(wù)的核心就是理解對應組件的功能以及其運作方式!
簡(jiǎn)單來(lái)講,Input 表示日志數據的來(lái)源,對不同來(lái)源的日志可以通過(guò) Extractors 來(lái)進(jìn)行日志的字段轉換,比如將 Nginx 的狀態(tài)碼變成對應的英文表述等。然后,通過(guò)不同的標簽類(lèi)型分組成不用的 Stream,并將這些日志數據存儲到指定的 Index 庫中進(jìn)行持久化保存。
Graylog中的核心服務(wù)組件
Graylog 通過(guò) Input 搜集日志,每個(gè) Input 單獨配置 Extractors 用來(lái)做字段轉換。Graylog 中日志搜索的基本單位是 Stream,每個(gè) Stream 可以有自己?jiǎn)为毜?Elastic Index Set,也可以共享一個(gè) Index Set。
Extractor 在 System/Input 中配置。Graylog 中很方便的一點(diǎn)就是可以加載一條日志,然后基于這個(gè)實(shí)際的例子進(jìn)行配置并能直接看到結果。內置的 Extractor 基本可以完成各種字段提取和轉換的任務(wù),但是也有些限制,在應用里寫(xiě)日志的時(shí)候就需要考慮到這些限制。Input 可以配置多個(gè) Extractors,按照順序依次執行。
系統會(huì )有一個(gè)默認的 Stream,所有日志默認都會(huì )保存到這個(gè) Stream 中,除非匹配了某個(gè) Stream,并且這個(gè) Stream 里配置了不保存日志到默認 Stream??梢酝ㄟ^(guò)菜單 Streams 創(chuàng )建更多的 Stream,新創(chuàng )建的 Stream 是暫停狀態(tài),需要在配置完成后手動(dòng)啟動(dòng)。Stream 通過(guò)配置條件匹配日志,滿(mǎn)足條件的日志添加 stream ID 標識字段并保存到對應的 Elastic Index Set 中。
Index Set 通過(guò)菜單 System/Indices 創(chuàng )建。日志存儲的性能,可靠性和過(guò)期策略都通過(guò) Index Set 來(lái)配置。性能和可靠性就是配置 Elastic Index 的一些參數,主要參數包括,Shards 和 Replicas。
除了上面提到的日志處理流程,Graylog 還提供了 Pipeline 腳本實(shí)現更靈活的日志處理方案。這里不詳細闡述,只介紹如果使用 Pipelines 來(lái)過(guò)濾不需要的日志。下面是丟棄 level > 6 的所有日志的 Pipeline Rule 的例子。從數據采集(input),字段解析(extractor),分流到 stream,再到 Pipeline 的清洗,一氣呵成,無(wú)需在通過(guò)其他方式進(jìn)行二次加工。
Sidecar 是一個(gè)輕量級的日志采集器,通過(guò)訪(fǎng)問(wèn) Graylog 進(jìn)行集中式管理,支持 Linux 和 windows 系統。Sidecar 守護進(jìn)程會(huì )定期訪(fǎng)問(wèn) Graylog 的 REST API 接口獲取 Sidecar 配置文件中定義的標簽(tag),Sidecar 在首次運行時(shí)會(huì )從 Graylog 服務(wù)器拉取配置文件中指定標簽(tag)的配置信息同步到本地。目前 Sidecar 支持 NXLog,Filebeat 和 Winlogbeat。他們都通過(guò) Graylog 中的 web 界面進(jìn)行統一配置,支持 Beats、CEF、Gelf、Json API、NetFlow 等輸出類(lèi)型。Graylog 最厲害的在于可以在配置文件中指定 Sidecar 把日志發(fā)送到哪個(gè) Graylog 群集,并對 Graylog 群集中的多個(gè) input 進(jìn)行負載均衡,這樣在遇到日志量非常龐大的時(shí)候,Graylog 也能應付自如。
rule?"discard?debug?messages"<br />when<br />??to_long($message.level)?>?6<br />then<br />??drop_message();<br />end<br />
日志集中保存到 Graylog 后就可以方便的使用搜索了。不過(guò)有時(shí)候還是需要對數據進(jìn)行近一步的處理。主要有兩個(gè)途徑,分別是直接訪(fǎng)問(wèn) Elastic 中保存的數據,或者通過(guò) Graylog 的 Output 轉發(fā)到其它服務(wù)。
5服務(wù)安裝和部署
主要介紹部署 Filebeat + Graylog 的安裝步驟和注意事項!
使用 Graylog 來(lái)收集日志
部署 Filebeat 工具
官方提供了多種的部署方式,包括通過(guò) rpm 和 deb 包安裝服務(wù),以及源代碼編譯的方式安裝服務(wù),同時(shí)包括了使用 Docker 或者 kubernetes 的方式安裝服務(wù)。我們根據自己的實(shí)際需要,進(jìn)行安裝即可。
#?Ubuntu(deb)<br />$?curl?-L?-O?https://artifacts.elastic.co/d ... %3Bbr />$?sudo?dpkg?-i?filebeat-7.8.1-amd64.deb<br />$?sudo?systemctl?enable?filebeat<br />$?sudo?service?filebeat?start<br /><br />#?使用docker啟動(dòng)<br />docker?run?-d?--name=filebeat?--user=root?\<br />??--volume="./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro"?\<br />??--volume="/var/lib/docker/containers:/var/lib/docker/containers:ro"?\<br />??--volume="/var/run/docker.sock:/var/run/docker.sock:ro"?\<br />??docker.elastic.co/beats/filebeat:7.8.1?filebeat?-e?-strict.perms=false?\<br />??-E?output.elasticsearch.hosts=["elasticsearch:9200"]<br />
使用 Graylog 來(lái)收集日志
部署 Graylog 服務(wù)
我們這里主要介紹使用 Docker 容器來(lái)部署服務(wù),如果你需要使用其他方式來(lái)部署的話(huà),請自行查看官方文檔對應章節的安裝部署步驟。在服務(wù)部署之前,我們需要給 Graylog 服務(wù)生成等相關(guān)信息,生成部署如下所示:
<p>#?生成password_secret密碼(最少16位)<br />$?sudo?apt?install?-y?pwgen<br />$?pwgen?-N?1?-s?16<br />zscMb65...FxR9ag<br /><br />#?生成后續Web登錄時(shí)所需要使用的密碼<br />$?echo?-n?"Enter?Password:?"?&&?head?-1? 查看全部
如何使用新一代輕量級分布式日志管理神器 Graylog 來(lái)收集日志
公眾號關(guān)注「奇妙的 Linux 世界」
設為「星標」,每天帶你玩轉 Linux !
當我們公司內部部署很多服務(wù)以及測試、正式環(huán)境的時(shí)候,查看日志就變成了一個(gè)非常剛需的需求了。是多個(gè)環(huán)境的日志統一收集,然后使用 Nginx 對外提供服務(wù),還是使用專(zhuān)用的日志收集服務(wù) ELK 呢?
這就變成了一個(gè)問(wèn)題!而 Graylog 作為整合方案,使用 Elasticsearch 來(lái)存儲,使用 MongoDB 來(lái)緩存,并且還有帶流量控制的(throttling),同時(shí)其界面查詢(xún)簡(jiǎn)單易用且易于擴展。所以,使用 Graylog 成為了不二之選,為我們省了不少心。
1Filebeat 工具介紹
Filebeat 日志文件托運服務(wù)
Filebeat 是一個(gè)日志文件托運工具,在你的服務(wù)器上安裝客戶(hù)端后,Filebeat 會(huì )自動(dòng)監控給定的日志目錄或者指定的日志文件,追蹤讀取這些文件,不停的讀取,并且轉發(fā)這些信息到 Elasticsearch 或者 Logstarsh 或者 Graylog 中存放。
Filebeat 工作流程介紹
當你安裝并啟用 Filebeat 程序的時(shí)候,它會(huì )啟動(dòng)一個(gè)或多個(gè)探測器(prospectors)去檢測你指定的日志目錄或文件,對于探測器找出的每一個(gè)日志文件,Filebeat 都會(huì )啟動(dòng)一個(gè)收割進(jìn)程(harvester),每一個(gè)收割進(jìn)程讀取一個(gè)日志文件的最新內容,并發(fā)送這些新的日志數據到處理程序(spooler),處理程序會(huì )集合這些事件,最后 Filebeat 會(huì )發(fā)送集合的數據到你指定的地址上去(我們這里就是發(fā)送給 Graylog 服務(wù)了)。
Filebeat 圖示理解記憶
我們這里不適用 Logstash 服務(wù),主要是因為 Filebeat 相比于 Logstash 更加輕量級。當我們需要收集信息的機器配置或資源并不是特別多時(shí),且并沒(méi)有那么復雜的時(shí)候,還是建議使用 Filebeat 來(lái)收集日志。日常使用中,Filebeat 的安裝部署方式多樣且運行十分穩定。
圖示服務(wù)架構理解記憶2Filebeat 配置文件
配置 Filebeat 工具的核心就是如何編寫(xiě)其對應的配置文件!
對應 Filebeat 工具的配置主要是通過(guò)編寫(xiě)其配置文件來(lái)控制的,對于通過(guò) rpm 或者 deb 包來(lái)安裝的情況,配置文件默認會(huì )存儲在,/etc/filebeat/filebeat.yml 這個(gè)路徑下面。而對于,對于 MAC 或者 Win 系統來(lái)說(shuō),請查看解壓文件中相關(guān)文件,其中都有涉及。
下面展示了 Filebeat 工具的主配置文件,注釋信息中都對其各個(gè)字段含義進(jìn)行了詳細的解釋?zhuān)疫@里就不再贅述了。需要注意的是,我們將日志的輸入來(lái)源統統定義去讀取 inputs.d 目錄下的所有 yml 配置。所以,我們可以更加不用的服務(wù)(測試、正式服務(wù))來(lái)定義不同的配置文件,根據物理機部署的實(shí)際情況具體配置。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br /><br />
下面展示一個(gè)簡(jiǎn)單的 inputs.d 目錄下面的 yml 配置文件的具體內容,其主要作用就是配置單獨服務(wù)的獨立日志數據,以及追加不同的數據 tag 類(lèi)型。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br />
需要注意的是,針對于不同的日志類(lèi)型,filebeat 還提供了不同了模塊來(lái)配置不同的服務(wù)日志以及其不同的模塊特性,比如我們常見(jiàn)的 PostgreSQl、Redis、Iptables 等。
#?iptables<br />-?module:?iptables<br />??log:<br />????enabled:?true<br />????var.paths:?["/var/log/iptables.log"]<br />????var.input:?"file"<br /><br />#?postgres<br />-?module:?postgresql<br />??log:<br />????enabled:?true<br />????var.paths:?["/path/to/log/postgres/*.log*"]<br /><br />#?nginx<br />-?module:?nginx<br />??access:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/access.log*"]<br />??error:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/error.log*"]<br />
3Graylog 服務(wù)介紹
服務(wù)日志收集方案:Filebeat + Graylog!
Graylog 日志監控系統
Graylog 是一個(gè)開(kāi)源的日志聚合、分析、審計、展現和預警工具。在功能上來(lái)說(shuō),和 ELK 類(lèi)似,但又比 ELK 要簡(jiǎn)單很多。依靠著(zhù)更加簡(jiǎn)潔,高效,部署使用簡(jiǎn)單的優(yōu)勢很快受到許多人的青睞。當然,在擴展性上面確實(shí)沒(méi)有比 ELK 好,但是其有商業(yè)版本可以選擇。
Graylog 工作流程介紹
部署 Graylog 最簡(jiǎn)單的架構就是單機部署,復雜的也是部署集群模式,架構圖示如下所示。我們可以看到其中包含了三個(gè)組件,分別是 Elasticsearch、MongoDb 和 Graylog。其中,Elasticsearch 用來(lái)持久化存儲和檢索日志文件數據(IO 密集),MongoDb 用來(lái)存儲關(guān)于 Graylog 的相關(guān)配置,而 Graylog 來(lái)提供 Web 界面和對外接口的(CPU 密集)。
最小化單機部署
最優(yōu)化集群部署4Graylog 組件功能
配置 Graylog 服務(wù)的核心就是理解對應組件的功能以及其運作方式!
簡(jiǎn)單來(lái)講,Input 表示日志數據的來(lái)源,對不同來(lái)源的日志可以通過(guò) Extractors 來(lái)進(jìn)行日志的字段轉換,比如將 Nginx 的狀態(tài)碼變成對應的英文表述等。然后,通過(guò)不同的標簽類(lèi)型分組成不用的 Stream,并將這些日志數據存儲到指定的 Index 庫中進(jìn)行持久化保存。
Graylog中的核心服務(wù)組件
Graylog 通過(guò) Input 搜集日志,每個(gè) Input 單獨配置 Extractors 用來(lái)做字段轉換。Graylog 中日志搜索的基本單位是 Stream,每個(gè) Stream 可以有自己?jiǎn)为毜?Elastic Index Set,也可以共享一個(gè) Index Set。
Extractor 在 System/Input 中配置。Graylog 中很方便的一點(diǎn)就是可以加載一條日志,然后基于這個(gè)實(shí)際的例子進(jìn)行配置并能直接看到結果。內置的 Extractor 基本可以完成各種字段提取和轉換的任務(wù),但是也有些限制,在應用里寫(xiě)日志的時(shí)候就需要考慮到這些限制。Input 可以配置多個(gè) Extractors,按照順序依次執行。
系統會(huì )有一個(gè)默認的 Stream,所有日志默認都會(huì )保存到這個(gè) Stream 中,除非匹配了某個(gè) Stream,并且這個(gè) Stream 里配置了不保存日志到默認 Stream??梢酝ㄟ^(guò)菜單 Streams 創(chuàng )建更多的 Stream,新創(chuàng )建的 Stream 是暫停狀態(tài),需要在配置完成后手動(dòng)啟動(dòng)。Stream 通過(guò)配置條件匹配日志,滿(mǎn)足條件的日志添加 stream ID 標識字段并保存到對應的 Elastic Index Set 中。
Index Set 通過(guò)菜單 System/Indices 創(chuàng )建。日志存儲的性能,可靠性和過(guò)期策略都通過(guò) Index Set 來(lái)配置。性能和可靠性就是配置 Elastic Index 的一些參數,主要參數包括,Shards 和 Replicas。
除了上面提到的日志處理流程,Graylog 還提供了 Pipeline 腳本實(shí)現更靈活的日志處理方案。這里不詳細闡述,只介紹如果使用 Pipelines 來(lái)過(guò)濾不需要的日志。下面是丟棄 level > 6 的所有日志的 Pipeline Rule 的例子。從數據采集(input),字段解析(extractor),分流到 stream,再到 Pipeline 的清洗,一氣呵成,無(wú)需在通過(guò)其他方式進(jìn)行二次加工。
Sidecar 是一個(gè)輕量級的日志采集器,通過(guò)訪(fǎng)問(wèn) Graylog 進(jìn)行集中式管理,支持 Linux 和 windows 系統。Sidecar 守護進(jìn)程會(huì )定期訪(fǎng)問(wèn) Graylog 的 REST API 接口獲取 Sidecar 配置文件中定義的標簽(tag),Sidecar 在首次運行時(shí)會(huì )從 Graylog 服務(wù)器拉取配置文件中指定標簽(tag)的配置信息同步到本地。目前 Sidecar 支持 NXLog,Filebeat 和 Winlogbeat。他們都通過(guò) Graylog 中的 web 界面進(jìn)行統一配置,支持 Beats、CEF、Gelf、Json API、NetFlow 等輸出類(lèi)型。Graylog 最厲害的在于可以在配置文件中指定 Sidecar 把日志發(fā)送到哪個(gè) Graylog 群集,并對 Graylog 群集中的多個(gè) input 進(jìn)行負載均衡,這樣在遇到日志量非常龐大的時(shí)候,Graylog 也能應付自如。
rule?"discard?debug?messages"<br />when<br />??to_long($message.level)?>?6<br />then<br />??drop_message();<br />end<br />
日志集中保存到 Graylog 后就可以方便的使用搜索了。不過(guò)有時(shí)候還是需要對數據進(jìn)行近一步的處理。主要有兩個(gè)途徑,分別是直接訪(fǎng)問(wèn) Elastic 中保存的數據,或者通過(guò) Graylog 的 Output 轉發(fā)到其它服務(wù)。
5服務(wù)安裝和部署
主要介紹部署 Filebeat + Graylog 的安裝步驟和注意事項!
使用 Graylog 來(lái)收集日志
部署 Filebeat 工具
官方提供了多種的部署方式,包括通過(guò) rpm 和 deb 包安裝服務(wù),以及源代碼編譯的方式安裝服務(wù),同時(shí)包括了使用 Docker 或者 kubernetes 的方式安裝服務(wù)。我們根據自己的實(shí)際需要,進(jìn)行安裝即可。
#?Ubuntu(deb)<br />$?curl?-L?-O?https://artifacts.elastic.co/d ... %3Bbr />$?sudo?dpkg?-i?filebeat-7.8.1-amd64.deb<br />$?sudo?systemctl?enable?filebeat<br />$?sudo?service?filebeat?start<br /><br />#?使用docker啟動(dòng)<br />docker?run?-d?--name=filebeat?--user=root?\<br />??--volume="./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro"?\<br />??--volume="/var/lib/docker/containers:/var/lib/docker/containers:ro"?\<br />??--volume="/var/run/docker.sock:/var/run/docker.sock:ro"?\<br />??docker.elastic.co/beats/filebeat:7.8.1?filebeat?-e?-strict.perms=false?\<br />??-E?output.elasticsearch.hosts=["elasticsearch:9200"]<br />
使用 Graylog 來(lái)收集日志
部署 Graylog 服務(wù)
我們這里主要介紹使用 Docker 容器來(lái)部署服務(wù),如果你需要使用其他方式來(lái)部署的話(huà),請自行查看官方文檔對應章節的安裝部署步驟。在服務(wù)部署之前,我們需要給 Graylog 服務(wù)生成等相關(guān)信息,生成部署如下所示:
<p>#?生成password_secret密碼(最少16位)<br />$?sudo?apt?install?-y?pwgen<br />$?pwgen?-N?1?-s?16<br />zscMb65...FxR9ag<br /><br />#?生成后續Web登錄時(shí)所需要使用的密碼<br />$?echo?-n?"Enter?Password:?"?&&?head?-1?
超好用的收集信息工具
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 145 次瀏覽 ? 2022-05-04 14:00
什么是 OSINT?
如果您聽(tīng)說(shuō)過(guò)這個(gè)名字,OSINT代表開(kāi)源情報,它指的是可以從免費公共來(lái)源合法收集的有關(guān)個(gè)人或組織的任何信息。在實(shí)踐中,這往往意味著(zhù)在互聯(lián)網(wǎng)上找到的信息,但從技術(shù)上講,任何公共信息都屬于OSINT類(lèi)別,無(wú)論是公共圖書(shū)館的書(shū)籍或報告,報紙上的文章還是新聞稿中的聲明。
OSINT 還包括可在不同類(lèi)型的介質(zhì)中找到的信息。雖然我們通常認為它是基于文本的,但圖像,視頻,網(wǎng)絡(luò )研討會(huì ),公開(kāi)演講和會(huì )議中的信息都屬于該術(shù)語(yǔ)。
OSINT的用途是什么?
通過(guò)收集有關(guān)特定目標的公開(kāi)可用信息源,以更好地了解其特征并縮小搜索區域以查找可能的漏洞。數據信息可以生成的情報來(lái)構建威脅模型?;蛘哂嗅槍π缘木W(wǎng)絡(luò )攻擊,如軍事攻擊,從偵察開(kāi)始,數字偵察的第一階段是被動(dòng)地獲取情報,而不向目標發(fā)出警報。一旦可以從公共來(lái)源收集有關(guān)您的情報類(lèi)型,就可以使用它來(lái)幫助您或您的安全團隊制定更好的防御策略。
OSINT工具
用于情報收集的最明顯的工具之一是Google,Bing等網(wǎng)絡(luò )搜索引擎。事實(shí)上,有幾十個(gè)搜索引擎,對于特定類(lèi)型的查詢(xún),有些搜索引擎可能會(huì )返回比其他搜索引擎更好的結果。那么,問(wèn)題是,如何以有效的方式查詢(xún)這許多引擎呢?
Searx是解決此問(wèn)題并使Web查詢(xún)更有效的一個(gè)很好的工具。Searx是元搜索引擎,允許您匿名并同時(shí)收集來(lái)自70多個(gè)搜索服務(wù)的結果。Searx是免費的,您甚至可以托管自己的實(shí)例,以獲得最終的隱私。用戶(hù)既不會(huì )被跟蹤,也不會(huì )被分析,并且默認情況下禁用cookie。Searx也可以通過(guò)Tor用于在線(xiàn)匿名。
有很多人一直在為OSINT開(kāi)發(fā)新工具,當然,跟上他們以及網(wǎng)絡(luò )安全世界中其他任何事情的好地方就是在Twitter上關(guān)注人們。然而,在Twitter上跟蹤事情可能很困難。幸運的是,還有一個(gè)名為T(mén)wint的OSINT工具。
Twint是一個(gè)用Python編寫(xiě)的Twitter報廢工具,可以很容易地在Twitter上匿名收集和搜索信息,而無(wú)需注冊Twitter服務(wù)本身或使用API密鑰,就像使用Recon-ng這樣的工具一樣。使用 Twint,根本不需要身份驗證或 API。只需安裝工具并開(kāi)始搜索即可。您可以按用戶(hù),地理位置和時(shí)間范圍以及其他可能性進(jìn)行搜索。這只是Twint的一些選擇,但也有許多其他選擇。
那么,如何使用 Twint 來(lái)幫助您跟上 OSINT 的發(fā)展呢?嗯,這很容易,是Twint在行動(dòng)中的一個(gè)很好的例子。由于 Twint 允許你指定一個(gè)--因為選項,以便僅從某個(gè)日期開(kāi)始拉取推文,因此你可以將其與 Twint 的搜索動(dòng)詞相結合,每天抓取標記有#OSINT的新推文。您可以使用 Twint 的--database選項(保存為 SQLite 格式)自動(dòng)執行該腳本并將結果饋送到數據庫中,以便在方便時(shí)查看。
另一個(gè)可以用來(lái)收集公共信息的好工具是Metagaofil。此工具使用Google搜索引擎從給定域中檢索公共PDF,Word文檔,Powerpoint和Excel文件。然后,它可以自主地從這些文檔中提取元數據,以生成列出用戶(hù)名、軟件版本、服務(wù)器和計算機名稱(chēng)等信息的報告。
查看全部
超好用的收集信息工具
什么是 OSINT?
如果您聽(tīng)說(shuō)過(guò)這個(gè)名字,OSINT代表開(kāi)源情報,它指的是可以從免費公共來(lái)源合法收集的有關(guān)個(gè)人或組織的任何信息。在實(shí)踐中,這往往意味著(zhù)在互聯(lián)網(wǎng)上找到的信息,但從技術(shù)上講,任何公共信息都屬于OSINT類(lèi)別,無(wú)論是公共圖書(shū)館的書(shū)籍或報告,報紙上的文章還是新聞稿中的聲明。
OSINT 還包括可在不同類(lèi)型的介質(zhì)中找到的信息。雖然我們通常認為它是基于文本的,但圖像,視頻,網(wǎng)絡(luò )研討會(huì ),公開(kāi)演講和會(huì )議中的信息都屬于該術(shù)語(yǔ)。
OSINT的用途是什么?
通過(guò)收集有關(guān)特定目標的公開(kāi)可用信息源,以更好地了解其特征并縮小搜索區域以查找可能的漏洞。數據信息可以生成的情報來(lái)構建威脅模型?;蛘哂嗅槍π缘木W(wǎng)絡(luò )攻擊,如軍事攻擊,從偵察開(kāi)始,數字偵察的第一階段是被動(dòng)地獲取情報,而不向目標發(fā)出警報。一旦可以從公共來(lái)源收集有關(guān)您的情報類(lèi)型,就可以使用它來(lái)幫助您或您的安全團隊制定更好的防御策略。
OSINT工具
用于情報收集的最明顯的工具之一是Google,Bing等網(wǎng)絡(luò )搜索引擎。事實(shí)上,有幾十個(gè)搜索引擎,對于特定類(lèi)型的查詢(xún),有些搜索引擎可能會(huì )返回比其他搜索引擎更好的結果。那么,問(wèn)題是,如何以有效的方式查詢(xún)這許多引擎呢?
Searx是解決此問(wèn)題并使Web查詢(xún)更有效的一個(gè)很好的工具。Searx是元搜索引擎,允許您匿名并同時(shí)收集來(lái)自70多個(gè)搜索服務(wù)的結果。Searx是免費的,您甚至可以托管自己的實(shí)例,以獲得最終的隱私。用戶(hù)既不會(huì )被跟蹤,也不會(huì )被分析,并且默認情況下禁用cookie。Searx也可以通過(guò)Tor用于在線(xiàn)匿名。
有很多人一直在為OSINT開(kāi)發(fā)新工具,當然,跟上他們以及網(wǎng)絡(luò )安全世界中其他任何事情的好地方就是在Twitter上關(guān)注人們。然而,在Twitter上跟蹤事情可能很困難。幸運的是,還有一個(gè)名為T(mén)wint的OSINT工具。
Twint是一個(gè)用Python編寫(xiě)的Twitter報廢工具,可以很容易地在Twitter上匿名收集和搜索信息,而無(wú)需注冊Twitter服務(wù)本身或使用API密鑰,就像使用Recon-ng這樣的工具一樣。使用 Twint,根本不需要身份驗證或 API。只需安裝工具并開(kāi)始搜索即可。您可以按用戶(hù),地理位置和時(shí)間范圍以及其他可能性進(jìn)行搜索。這只是Twint的一些選擇,但也有許多其他選擇。
那么,如何使用 Twint 來(lái)幫助您跟上 OSINT 的發(fā)展呢?嗯,這很容易,是Twint在行動(dòng)中的一個(gè)很好的例子。由于 Twint 允許你指定一個(gè)--因為選項,以便僅從某個(gè)日期開(kāi)始拉取推文,因此你可以將其與 Twint 的搜索動(dòng)詞相結合,每天抓取標記有#OSINT的新推文。您可以使用 Twint 的--database選項(保存為 SQLite 格式)自動(dòng)執行該腳本并將結果饋送到數據庫中,以便在方便時(shí)查看。
另一個(gè)可以用來(lái)收集公共信息的好工具是Metagaofil。此工具使用Google搜索引擎從給定域中檢索公共PDF,Word文檔,Powerpoint和Excel文件。然后,它可以自主地從這些文檔中提取元數據,以生成列出用戶(hù)名、軟件版本、服務(wù)器和計算機名稱(chēng)等信息的報告。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 128 次瀏覽 ? 2022-05-04 13:08
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
深入淺出前端監控
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 130 次瀏覽 ? 2022-05-02 22:02
重寫(xiě) fetch 方法
當然了,重寫(xiě)上述方法后除了異常請求可以被監控到之外,正常響應的請求狀態(tài)自然也能被采集到,比如 APM 會(huì )將對所有上報請求的持續時(shí)間進(jìn)行分析從而得出慢請求的占比:
PS:如果通過(guò) XHR 或 fetch 來(lái)上報監控數據的話(huà),上報請求也會(huì )被被攔截,可以有選擇地做一層過(guò)濾處理。
卡頓異常
卡頓指的是顯示器刷新時(shí)下一幀的畫(huà)面還沒(méi)有準備好,導致連續多次展示同樣的畫(huà)面,從而讓用戶(hù)感覺(jué)到頁(yè)面不流暢,也就是所謂的掉幀,衡量一個(gè)頁(yè)面是否卡頓的指標就是我們熟知的 FPS。
如何獲取 FPS
Chrome DevTool 中有一欄 Rendering 中包含 FPS 指標,但目前瀏覽器標準中暫時(shí)沒(méi)有提供相應 API ,只能手動(dòng)實(shí)現。這里需要借助 requestAnimationFrame 方法模擬實(shí)現,瀏覽器會(huì )在下一次重繪之前執行 rAF 的回調,因此可以通過(guò)計算每秒內 rAF 的執行次數來(lái)計算當前頁(yè)面的 FPS。
通過(guò) rAF 計算 FPS
如何上報“真實(shí)卡頓”
從技術(shù)角度看 FPS 低于 60 即視為卡頓,但在真實(shí)環(huán)境中用戶(hù)很多行為都可能造成 FPS 的波動(dòng),并不能無(wú)腦地把 FPS 低于 60 以下的 case 全部上報,會(huì )造成非常多無(wú)效數據,因此需要結合實(shí)際的用戶(hù)體驗重新定義“真正的卡頓”,這里貼一下司內 APM 平臺的上報策略:
頁(yè)面 FPS 持續低于預期:當前頁(yè)面連續 3s FPS 低于 20。用戶(hù)操作帶來(lái)的卡頓:當用戶(hù)進(jìn)行交互行為后,渲染新的一幀的時(shí)間超過(guò) 16ms + 100ms。崩潰異常
Web 頁(yè)面崩潰指在網(wǎng)頁(yè)運行過(guò)程頁(yè)面完全無(wú)響應的現象,通常有兩種情況會(huì )造成頁(yè)面崩潰:
JS 主線(xiàn)程出現無(wú)限循環(huán),觸發(fā)瀏覽器的保護策略,結束當前頁(yè)面的進(jìn)程。內存不足
發(fā)生崩潰時(shí)主線(xiàn)程被阻塞,因此對崩潰的監控只能在獨立于 JS 主線(xiàn)程的 Worker 線(xiàn)程中進(jìn)行,我們可以采用 Web Worker 心跳檢測的方式來(lái)對主線(xiàn)程進(jìn)行不斷的探測,如果主線(xiàn)程崩潰,就不會(huì )有任何響應,那就可以在 Worker 線(xiàn)程中進(jìn)行崩潰異常的上報。這里繼續貼一下 APM 的檢測策略:
Web Worker:
崩潰檢測
性能監控
性能監控并不只是簡(jiǎn)單的監控“頁(yè)面速度有多快”,需要從用戶(hù)體驗的角度全面衡量性能指標。(就是所謂的 RUM 指標)目前業(yè)界主流標準是 Google 最新定義的 Core Web Vitals:
可以看到最新標準中,以往熟知的 FP、FCP、FMP、TTI 等指標都被移除了,個(gè)人認為這些指標還是具備一定的參考價(jià)值,因此下文還是會(huì )將這些指標進(jìn)行相關(guān)介紹。(谷歌的話(huà)不聽(tīng)不聽(tīng))
Loading 加載
和 Loading 相關(guān)的指標有 FP 、FCP 、FMP 和 LCP,首先來(lái)看一下我們相對熟悉的幾個(gè)指標:
FP/FCP/FMP
一張流傳已久的圖
這兩個(gè)指標都通過(guò) PerformancePaintTiming API 獲?。?br />
通過(guò) PerformancePaintTiming 獲取 FP 和 FCP
下面再來(lái)看 FMP 的定義和獲取方式:
FMP 的計算相對復雜,因為瀏覽器并未提供相應的 API,在此之前我們先看一組圖:
從圖中可以發(fā)現頁(yè)面渲染過(guò)程中的一些規律:
在 1.577 秒,頁(yè)面渲染了一個(gè)搜索框,此時(shí)已經(jīng)有 60 個(gè)布局對象被添加到了布局樹(shù)中。在 1.760 秒,頁(yè)面頭部整體渲染完成,此時(shí)布局對象總數是 103 個(gè)。在 1.907 秒,頁(yè)面主體內容已經(jīng)繪制完成,此時(shí)有 261 個(gè)布局對象被添加到布局樹(shù)中從用戶(hù)體驗的角度看,此時(shí)的時(shí)間點(diǎn)就是是 FMP。
可以看到布局對象的數量與頁(yè)面完成度高度相關(guān)。業(yè)界目前比較認可的一個(gè)計算 FMP 的方式就是——「頁(yè)面在加載和渲染過(guò)程中最大布局變動(dòng)之后的那個(gè)繪制時(shí)間即為當前頁(yè)面的 FMP 」
實(shí)現原理則需要通過(guò) MutationObserver 監聽(tīng) document 整體的 DOM 變化,在回調計算出當前 DOM 樹(shù)的分數,分數變化最劇烈的時(shí)刻,即為 FMP 的時(shí)間點(diǎn)。
至于如何計算當前頁(yè)面 DOM 的分數,LightHouse 的源碼中會(huì )根據當前節點(diǎn)深度作為變量做一個(gè)權重的計算,具體實(shí)現可以參考 LightHouse 源碼。
const?curNodeScore?=?1?+?0.5?*?depth;<br />const?domScore?=?所有子節點(diǎn)分數求和<br />
上述計算方式性能開(kāi)銷(xiāo)大且未必準確,LightHouse 6.0 已明確廢棄了 FMP 打分項,建議在具體業(yè)務(wù)場(chǎng)景中根據實(shí)際情況手動(dòng)埋點(diǎn)來(lái)確定 FMP 具體的值,更準確也更高效。
LCP
沒(méi)錯,LCP (Largest Contentful Paint) 是就是用來(lái)代替 FMP 的一個(gè)性能指標 ,用于度量視口中最大的內容元素何時(shí)可見(jiàn),可以用來(lái)確定頁(yè)面的主要內容何時(shí)在屏幕上完成渲染。
使用 Largest Contentful Paint API 和 PerformanceObserver 即可獲取 LCP 指標的值:
獲取 LCP
Interactivity 交互TTI
TTI(Time To Interactive) 表示從頁(yè)面加載開(kāi)始到頁(yè)面處于完全可交互狀態(tài)所花費的時(shí)間, TTI 值越小,代表用戶(hù)可以更早地操作頁(yè)面,用戶(hù)體驗就更好。
這里定義一下什么是完全可交互狀態(tài)的頁(yè)面:
頁(yè)面已經(jīng)顯示有用內容。頁(yè)面上的可見(jiàn)元素關(guān)聯(lián)的事件響應函數已經(jīng)完成注冊。事件響應函數可以在事件發(fā)生后的 50ms 內開(kāi)始執行(主線(xiàn)程無(wú) Long Task)。
TTI 的算法略有些復雜,結合下圖看一下具體步驟:
TTI 示意圖
Long Task: 阻塞主線(xiàn)程達 50 毫秒或以上的任務(wù)。
從 FCP 時(shí)間開(kāi)始,向前搜索一個(gè)不小于 5s 的靜默窗口期。(靜默窗口期定義:窗口所對應的時(shí)間內沒(méi)有 Long Task,且進(jìn)行中的網(wǎng)絡(luò )請求數不超過(guò) 2 個(gè))找到靜默窗口期后,從靜默窗口期向后搜索到最近的一個(gè) Long Task,Long Task 的結束時(shí)間即為 TTI。如果一直找到 FCP 時(shí)刻仍然沒(méi)有找到 Long Task,以 FCP 時(shí)間作為 TTI。
其實(shí)現需要支持 Long Tasks API 和 Resource Timing API,具體實(shí)現感興趣的同學(xué)可以按照上述流程嘗試手動(dòng)實(shí)現。
FID
FID(First Input Delay) 用于度量用戶(hù)第一次與頁(yè)面交互的延遲時(shí)間,是用戶(hù)第一次與頁(yè)面交互到瀏覽器真正能夠開(kāi)始處理事件處理程序以響應該交互的時(shí)間。
其實(shí)現使用簡(jiǎn)潔的 PerformanceEventTiming API 即可,回調的觸發(fā)時(shí)機是用戶(hù)首次與頁(yè)面發(fā)生交互并得到瀏覽器響應(點(diǎn)擊鏈接、輸入文字等)。
獲取 FID
至于為何新的標準中采用 FID 而非 TTI,可能存在以下幾個(gè)因素:
Visual Stability 視覺(jué)穩定CLS
CLS(Cumulative Layout Shift) 是對在頁(yè)面的整個(gè)生命周期中發(fā)生的每一次意外布局變化的最大布局變化得分的度量,布局變化得分越小證明你的頁(yè)面越穩定。
聽(tīng)起來(lái)有點(diǎn)復雜,這里做一個(gè)簡(jiǎn)單的解釋?zhuān)?br /> 舉個(gè)例子,一個(gè)占據頁(yè)面高度 50% 的元素,向下偏移了 25%,那么其得分為 0.75 * 0.25,大于標準定義的 0.1 分,該頁(yè)面就視為視覺(jué)上沒(méi)那么穩定的頁(yè)面。
使用 Layout Instability API 和 PerformanceObserver 來(lái)獲取 CLS:
獲取 CLS
一點(diǎn)感受:在翻閱諸多參考資料后,私以為性能監控是一件長(cháng)期實(shí)踐、以實(shí)際業(yè)務(wù)為導向的事情,業(yè)內主流標準日新月異,到底監控什么指標是最貼合用戶(hù)體驗的我們不得而知,對于 FMP、FPS 這類(lèi)瀏覽器未提供 API 獲取方式的指標花費大量力氣去探索實(shí)現是否有足夠的收益也存在一定的疑問(wèn),但毋容置疑的是從自身頁(yè)面的業(yè)務(wù)屬性出發(fā),結合一些用戶(hù)反饋再進(jìn)行相關(guān)手段的優(yōu)化可能是更好的選擇。(更推薦深入了解瀏覽器渲染原理,寫(xiě)出性能極佳的頁(yè)面,讓 APM 同學(xué)失業(yè)
數據上報
得到所有錯誤、性能、用戶(hù)行為以及相應的環(huán)境信息后就要考慮如何進(jìn)行數據上報,理論上正常使用ajax 即可,但有一些數據上報可能出現在頁(yè)面關(guān)閉 (unload) 的時(shí)刻,這些請求會(huì )被瀏覽器的策略 cancel 掉,因此出現了以下幾種解決方案:
優(yōu)先使用 Navigator.sendBeacon,這個(gè) API 就是為了解決上述問(wèn)題而誕生,它通過(guò) HTTP POST 將數據異步傳輸到服務(wù)器且不會(huì )影響頁(yè)面卸載。如果不支持上述 API,動(dòng)態(tài)創(chuàng )建一個(gè)
/ > 標簽將數據通過(guò) url 拼接的方式傳遞。使用同步 XHR 進(jìn)行上報以延遲頁(yè)面卸載,不過(guò)現在很多瀏覽器禁止了該行為。
APM 采取了第一種方式,不支持 sendBeacon 則使用 XHR,偶爾丟日志的原因找到了。
由于監控數據通常量級都十分龐大,因此不能簡(jiǎn)單地采集一個(gè)就上報一個(gè),需要一些優(yōu)化手段:
總結
本文旨在提供一個(gè)相對體系的前端監控視圖,幫助各位了解前端監控領(lǐng)域我們能做什么、需要做什么。此外,如果能對頁(yè)面性能和異常處理有著(zhù)更深入的認知,無(wú)論是在開(kāi)發(fā)應用時(shí)的自我管理(減少 bug、有意識地書(shū)寫(xiě)高性能代碼),還是自研監控 SDK 都有所裨益。
如何設計監控 SDK 不是本文的重點(diǎn),部分監控指標的定義和實(shí)現細節也可能存在其他解法,實(shí)現一個(gè)完善且健壯的前端監控 SDK 還有很多技術(shù)細節,例如每個(gè)指標可以提供哪些配置項、如何設計上報的維度、如何做好兼容性等等,這些都需要在真實(shí)的業(yè)務(wù)場(chǎng)景中不斷打磨和優(yōu)化才能趨于成熟。
參考
Google Developer
?? 謝謝支持
以上便是本次分享的全部?jì)热?,希望對你有所幫助^_^ 查看全部
深入淺出前端監控
重寫(xiě) fetch 方法
當然了,重寫(xiě)上述方法后除了異常請求可以被監控到之外,正常響應的請求狀態(tài)自然也能被采集到,比如 APM 會(huì )將對所有上報請求的持續時(shí)間進(jìn)行分析從而得出慢請求的占比:
PS:如果通過(guò) XHR 或 fetch 來(lái)上報監控數據的話(huà),上報請求也會(huì )被被攔截,可以有選擇地做一層過(guò)濾處理。
卡頓異常
卡頓指的是顯示器刷新時(shí)下一幀的畫(huà)面還沒(méi)有準備好,導致連續多次展示同樣的畫(huà)面,從而讓用戶(hù)感覺(jué)到頁(yè)面不流暢,也就是所謂的掉幀,衡量一個(gè)頁(yè)面是否卡頓的指標就是我們熟知的 FPS。
如何獲取 FPS
Chrome DevTool 中有一欄 Rendering 中包含 FPS 指標,但目前瀏覽器標準中暫時(shí)沒(méi)有提供相應 API ,只能手動(dòng)實(shí)現。這里需要借助 requestAnimationFrame 方法模擬實(shí)現,瀏覽器會(huì )在下一次重繪之前執行 rAF 的回調,因此可以通過(guò)計算每秒內 rAF 的執行次數來(lái)計算當前頁(yè)面的 FPS。
通過(guò) rAF 計算 FPS
如何上報“真實(shí)卡頓”
從技術(shù)角度看 FPS 低于 60 即視為卡頓,但在真實(shí)環(huán)境中用戶(hù)很多行為都可能造成 FPS 的波動(dòng),并不能無(wú)腦地把 FPS 低于 60 以下的 case 全部上報,會(huì )造成非常多無(wú)效數據,因此需要結合實(shí)際的用戶(hù)體驗重新定義“真正的卡頓”,這里貼一下司內 APM 平臺的上報策略:
頁(yè)面 FPS 持續低于預期:當前頁(yè)面連續 3s FPS 低于 20。用戶(hù)操作帶來(lái)的卡頓:當用戶(hù)進(jìn)行交互行為后,渲染新的一幀的時(shí)間超過(guò) 16ms + 100ms。崩潰異常
Web 頁(yè)面崩潰指在網(wǎng)頁(yè)運行過(guò)程頁(yè)面完全無(wú)響應的現象,通常有兩種情況會(huì )造成頁(yè)面崩潰:
JS 主線(xiàn)程出現無(wú)限循環(huán),觸發(fā)瀏覽器的保護策略,結束當前頁(yè)面的進(jìn)程。內存不足
發(fā)生崩潰時(shí)主線(xiàn)程被阻塞,因此對崩潰的監控只能在獨立于 JS 主線(xiàn)程的 Worker 線(xiàn)程中進(jìn)行,我們可以采用 Web Worker 心跳檢測的方式來(lái)對主線(xiàn)程進(jìn)行不斷的探測,如果主線(xiàn)程崩潰,就不會(huì )有任何響應,那就可以在 Worker 線(xiàn)程中進(jìn)行崩潰異常的上報。這里繼續貼一下 APM 的檢測策略:
Web Worker:
崩潰檢測
性能監控
性能監控并不只是簡(jiǎn)單的監控“頁(yè)面速度有多快”,需要從用戶(hù)體驗的角度全面衡量性能指標。(就是所謂的 RUM 指標)目前業(yè)界主流標準是 Google 最新定義的 Core Web Vitals:
可以看到最新標準中,以往熟知的 FP、FCP、FMP、TTI 等指標都被移除了,個(gè)人認為這些指標還是具備一定的參考價(jià)值,因此下文還是會(huì )將這些指標進(jìn)行相關(guān)介紹。(谷歌的話(huà)不聽(tīng)不聽(tīng))
Loading 加載
和 Loading 相關(guān)的指標有 FP 、FCP 、FMP 和 LCP,首先來(lái)看一下我們相對熟悉的幾個(gè)指標:
FP/FCP/FMP
一張流傳已久的圖
這兩個(gè)指標都通過(guò) PerformancePaintTiming API 獲?。?br />
通過(guò) PerformancePaintTiming 獲取 FP 和 FCP
下面再來(lái)看 FMP 的定義和獲取方式:
FMP 的計算相對復雜,因為瀏覽器并未提供相應的 API,在此之前我們先看一組圖:
從圖中可以發(fā)現頁(yè)面渲染過(guò)程中的一些規律:
在 1.577 秒,頁(yè)面渲染了一個(gè)搜索框,此時(shí)已經(jīng)有 60 個(gè)布局對象被添加到了布局樹(shù)中。在 1.760 秒,頁(yè)面頭部整體渲染完成,此時(shí)布局對象總數是 103 個(gè)。在 1.907 秒,頁(yè)面主體內容已經(jīng)繪制完成,此時(shí)有 261 個(gè)布局對象被添加到布局樹(shù)中從用戶(hù)體驗的角度看,此時(shí)的時(shí)間點(diǎn)就是是 FMP。
可以看到布局對象的數量與頁(yè)面完成度高度相關(guān)。業(yè)界目前比較認可的一個(gè)計算 FMP 的方式就是——「頁(yè)面在加載和渲染過(guò)程中最大布局變動(dòng)之后的那個(gè)繪制時(shí)間即為當前頁(yè)面的 FMP 」
實(shí)現原理則需要通過(guò) MutationObserver 監聽(tīng) document 整體的 DOM 變化,在回調計算出當前 DOM 樹(shù)的分數,分數變化最劇烈的時(shí)刻,即為 FMP 的時(shí)間點(diǎn)。
至于如何計算當前頁(yè)面 DOM 的分數,LightHouse 的源碼中會(huì )根據當前節點(diǎn)深度作為變量做一個(gè)權重的計算,具體實(shí)現可以參考 LightHouse 源碼。
const?curNodeScore?=?1?+?0.5?*?depth;<br />const?domScore?=?所有子節點(diǎn)分數求和<br />
上述計算方式性能開(kāi)銷(xiāo)大且未必準確,LightHouse 6.0 已明確廢棄了 FMP 打分項,建議在具體業(yè)務(wù)場(chǎng)景中根據實(shí)際情況手動(dòng)埋點(diǎn)來(lái)確定 FMP 具體的值,更準確也更高效。
LCP
沒(méi)錯,LCP (Largest Contentful Paint) 是就是用來(lái)代替 FMP 的一個(gè)性能指標 ,用于度量視口中最大的內容元素何時(shí)可見(jiàn),可以用來(lái)確定頁(yè)面的主要內容何時(shí)在屏幕上完成渲染。
使用 Largest Contentful Paint API 和 PerformanceObserver 即可獲取 LCP 指標的值:
獲取 LCP
Interactivity 交互TTI
TTI(Time To Interactive) 表示從頁(yè)面加載開(kāi)始到頁(yè)面處于完全可交互狀態(tài)所花費的時(shí)間, TTI 值越小,代表用戶(hù)可以更早地操作頁(yè)面,用戶(hù)體驗就更好。
這里定義一下什么是完全可交互狀態(tài)的頁(yè)面:
頁(yè)面已經(jīng)顯示有用內容。頁(yè)面上的可見(jiàn)元素關(guān)聯(lián)的事件響應函數已經(jīng)完成注冊。事件響應函數可以在事件發(fā)生后的 50ms 內開(kāi)始執行(主線(xiàn)程無(wú) Long Task)。
TTI 的算法略有些復雜,結合下圖看一下具體步驟:
TTI 示意圖
Long Task: 阻塞主線(xiàn)程達 50 毫秒或以上的任務(wù)。
從 FCP 時(shí)間開(kāi)始,向前搜索一個(gè)不小于 5s 的靜默窗口期。(靜默窗口期定義:窗口所對應的時(shí)間內沒(méi)有 Long Task,且進(jìn)行中的網(wǎng)絡(luò )請求數不超過(guò) 2 個(gè))找到靜默窗口期后,從靜默窗口期向后搜索到最近的一個(gè) Long Task,Long Task 的結束時(shí)間即為 TTI。如果一直找到 FCP 時(shí)刻仍然沒(méi)有找到 Long Task,以 FCP 時(shí)間作為 TTI。
其實(shí)現需要支持 Long Tasks API 和 Resource Timing API,具體實(shí)現感興趣的同學(xué)可以按照上述流程嘗試手動(dòng)實(shí)現。
FID
FID(First Input Delay) 用于度量用戶(hù)第一次與頁(yè)面交互的延遲時(shí)間,是用戶(hù)第一次與頁(yè)面交互到瀏覽器真正能夠開(kāi)始處理事件處理程序以響應該交互的時(shí)間。
其實(shí)現使用簡(jiǎn)潔的 PerformanceEventTiming API 即可,回調的觸發(fā)時(shí)機是用戶(hù)首次與頁(yè)面發(fā)生交互并得到瀏覽器響應(點(diǎn)擊鏈接、輸入文字等)。
獲取 FID
至于為何新的標準中采用 FID 而非 TTI,可能存在以下幾個(gè)因素:
Visual Stability 視覺(jué)穩定CLS
CLS(Cumulative Layout Shift) 是對在頁(yè)面的整個(gè)生命周期中發(fā)生的每一次意外布局變化的最大布局變化得分的度量,布局變化得分越小證明你的頁(yè)面越穩定。
聽(tīng)起來(lái)有點(diǎn)復雜,這里做一個(gè)簡(jiǎn)單的解釋?zhuān)?br /> 舉個(gè)例子,一個(gè)占據頁(yè)面高度 50% 的元素,向下偏移了 25%,那么其得分為 0.75 * 0.25,大于標準定義的 0.1 分,該頁(yè)面就視為視覺(jué)上沒(méi)那么穩定的頁(yè)面。
使用 Layout Instability API 和 PerformanceObserver 來(lái)獲取 CLS:
獲取 CLS
一點(diǎn)感受:在翻閱諸多參考資料后,私以為性能監控是一件長(cháng)期實(shí)踐、以實(shí)際業(yè)務(wù)為導向的事情,業(yè)內主流標準日新月異,到底監控什么指標是最貼合用戶(hù)體驗的我們不得而知,對于 FMP、FPS 這類(lèi)瀏覽器未提供 API 獲取方式的指標花費大量力氣去探索實(shí)現是否有足夠的收益也存在一定的疑問(wèn),但毋容置疑的是從自身頁(yè)面的業(yè)務(wù)屬性出發(fā),結合一些用戶(hù)反饋再進(jìn)行相關(guān)手段的優(yōu)化可能是更好的選擇。(更推薦深入了解瀏覽器渲染原理,寫(xiě)出性能極佳的頁(yè)面,讓 APM 同學(xué)失業(yè)
數據上報
得到所有錯誤、性能、用戶(hù)行為以及相應的環(huán)境信息后就要考慮如何進(jìn)行數據上報,理論上正常使用ajax 即可,但有一些數據上報可能出現在頁(yè)面關(guān)閉 (unload) 的時(shí)刻,這些請求會(huì )被瀏覽器的策略 cancel 掉,因此出現了以下幾種解決方案:
優(yōu)先使用 Navigator.sendBeacon,這個(gè) API 就是為了解決上述問(wèn)題而誕生,它通過(guò) HTTP POST 將數據異步傳輸到服務(wù)器且不會(huì )影響頁(yè)面卸載。如果不支持上述 API,動(dòng)態(tài)創(chuàng )建一個(gè)
/ > 標簽將數據通過(guò) url 拼接的方式傳遞。使用同步 XHR 進(jìn)行上報以延遲頁(yè)面卸載,不過(guò)現在很多瀏覽器禁止了該行為。
APM 采取了第一種方式,不支持 sendBeacon 則使用 XHR,偶爾丟日志的原因找到了。
由于監控數據通常量級都十分龐大,因此不能簡(jiǎn)單地采集一個(gè)就上報一個(gè),需要一些優(yōu)化手段:
總結
本文旨在提供一個(gè)相對體系的前端監控視圖,幫助各位了解前端監控領(lǐng)域我們能做什么、需要做什么。此外,如果能對頁(yè)面性能和異常處理有著(zhù)更深入的認知,無(wú)論是在開(kāi)發(fā)應用時(shí)的自我管理(減少 bug、有意識地書(shū)寫(xiě)高性能代碼),還是自研監控 SDK 都有所裨益。
如何設計監控 SDK 不是本文的重點(diǎn),部分監控指標的定義和實(shí)現細節也可能存在其他解法,實(shí)現一個(gè)完善且健壯的前端監控 SDK 還有很多技術(shù)細節,例如每個(gè)指標可以提供哪些配置項、如何設計上報的維度、如何做好兼容性等等,這些都需要在真實(shí)的業(yè)務(wù)場(chǎng)景中不斷打磨和優(yōu)化才能趨于成熟。
參考
Google Developer
?? 謝謝支持
以上便是本次分享的全部?jì)热?,希望對你有所幫助^_^
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 163 次瀏覽 ? 2022-05-02 21:59
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
文章采集api 性能指標的信仰危機
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 101 次瀏覽 ? 2022-05-02 19:45
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。 查看全部
文章采集api 性能指標的信仰危機
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。
文章采集api 性能指標的信仰危機
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 142 次瀏覽 ? 2022-05-02 02:40
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。 查看全部
文章采集api 性能指標的信仰危機
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。
云原生愛(ài)好者周刊:尋找 Netlify 開(kāi)源替代品
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 71 次瀏覽 ? 2022-05-01 23:16
隨著(zhù)云原生技術(shù)的快速發(fā)展,技術(shù)的不斷迭代,對于日志的采集、處理及轉發(fā)提出了更高的要求。云原生架構下的日志方案相比基于物理機或者是虛擬機場(chǎng)景的日志架構設計存在很大差別。作為 CNCF 的畢業(yè)項目,Fluent Bit 無(wú)疑為解決云環(huán)境中的日志記錄問(wèn)題的首選解決方案之一。但是在 Kubernetes 中安裝部署以及配置 Fluent Bit 都具有一定的門(mén)檻,加大了用戶(hù)的使用成本。
本文從寫(xiě)作對個(gè)人的價(jià)值談到技術(shù)內容的創(chuàng )作選型,再到文章的排版和輔助工具,希望能幫助大家開(kāi)啟自己的技術(shù)內容創(chuàng )作之路。
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標[3]
對于 Prometheus 這種底層的時(shí)間序列數據庫來(lái)說(shuō),規模大了之后,免不了需要一定的手動(dòng)維護,這對于 Prometheus 的性能至關(guān)重要。這篇文章介紹了如何手動(dòng)刪除和丟棄無(wú)用的指標。
云原生動(dòng)態(tài)Harbor v2.5.0 引入 Cosign[4]
成品(Artifact)簽名和簽名驗證是關(guān)鍵的安全功能,允許你驗證成品的完整性。Harbor 通過(guò)與Notary 和 Cosign 的集成支持內容信任。
Harbor v2.5 集成了對 Cosign 的支持,這是一個(gè) OCI 成品簽名和驗證解決方案,是 Sigstore 項目的一部分。
將 Cosign 與 Harbor 結合使用的一個(gè)關(guān)鍵特性是能夠使用 Harbor 的復制功能來(lái)復制簽名及其相關(guān)的已簽名成品。這意味著(zhù),如果一個(gè)復制規則(replication rule)應用于一個(gè)已簽名成品,Harbo 將把復制規則應用于簽名,就像它應用于已簽名成品一樣。
Tanzu 應用平臺 1.1 版本發(fā)布[5]
Tanzu 應用平臺由 VMware 推出,旨在幫助用戶(hù)在任何公有云或本地 Kubernetes 集群上快速構建和部署軟件。Tanzu 應用平臺提供了一套豐富的開(kāi)發(fā)人員工具,并為支持生產(chǎn)的企業(yè)提供了一條預先鋪好的路徑,通過(guò)降低開(kāi)發(fā)人員工具的復雜性來(lái)更快地開(kāi)發(fā)創(chuàng )收應用程序。
1.1 版本提供了大量新功能,使企業(yè)能夠加快實(shí)現價(jià)值的時(shí)間、簡(jiǎn)化用戶(hù)體驗、建立更強大的安全態(tài)勢并保護他們已經(jīng)進(jìn)行的投資。這些領(lǐng)先的能力使企業(yè)能夠:
Kubernetes 1.24 發(fā)布推遲[6]
經(jīng)過(guò)一段時(shí)間的討論,發(fā)布團隊決定將預定的 Kubernetes 1.24 發(fā)布日推遲到 2022 年 5 月 3 日星期二。這比 2022 年 4 月 19 日星期二的原定發(fā)布日期延遲了兩周。
這是阻止發(fā)布 bug 的結果。該 bug 將在最新的 Golang 次要版本 Go 1.18.1 中修復,預計將于今天晚些時(shí)候發(fā)布。由于 Go 發(fā)布的延遲,發(fā)布團隊已采取措施將預定的 Kubernetes 發(fā)布日期延長(cháng)兩周,以便有足夠的時(shí)間進(jìn)行測試和穩定。
更新的時(shí)間表現在是:
4 月 19 日星期二的 1.24.0-rc.0。
4 月 26 日星期二的 1.24.0-rc.1。
1.24.0 于 5 月 3 日星期二正式發(fā)布。
WasmEdge 0.9.1 發(fā)布了!此版本集成了高性能 networking、JavaScript 流式 SSR 和 Fetch API 支持、新的 bindgen 框架、安卓和 OpenHarmony 操作系統支持、擴展的 Kubernetes 支持以及更好的內存管理。
Flagger 添加了網(wǎng)關(guān) API 支持[7]
Flagger 1.19.0 版本帶來(lái)了 Kubernetes Gateway API 的支持。
Flagger 是一個(gè)漸進(jìn)式的交付工具,它為運行在 Kubernetes 上的應用程序自動(dòng)化發(fā)布過(guò)程。它通過(guò)逐步將流量轉移到新版本,同時(shí)測量指標和運行一致性測試,降低了在生產(chǎn)中引入新軟件版本的風(fēng)險。
由于增加了對 Gateway API 的支持,Flagger 現在可以與所有的實(shí)現一起工作,這意味著(zhù)從今天起,這些都是原生支持:Contour, Emissary-Ingress, Google Kubernetes Engine, HAProxy Ingress, HashiCorp Consul, Istio, Kong and Traefik。
Flagger 團隊已經(jīng)使用 v1beta2 網(wǎng)關(guān) API 成功測試了 Contour 和 Istio。從 Flagger v1.19 開(kāi)始,網(wǎng)關(guān) API 是使用 Contour 實(shí)現的端到端測試套件的一部分。
引用鏈接[1]
Coolify:
[2]
Podman Desktop:
[3]
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標:
[4]
Harbor v2.5.0 引入 Cosign:
[5]
Tanzu 應用平臺 1.1 版本發(fā)布:
[6]
Kubernetes 1.24 發(fā)布推遲:
[7]
Flagger 添加了網(wǎng)關(guān) API 支持:
KubeSphere ()是在 Kubernetes 之上構建的開(kāi)源容器混合云,提供全棧的 IT 自動(dòng)化運維的能力,簡(jiǎn)化企業(yè)的 DevOps 工作流。
KubeSphere已被Aqara智能家居、愛(ài)立信、本來(lái)生活、東軟、華云、新浪、三一重工、華夏銀行、四川航空、國藥集團、微眾銀行、杭州數跑科技、紫金保險、去哪兒網(wǎng)、中通、中國人民銀行、中國銀行、中國人保壽險、中國太平保險、中國移動(dòng)、中國聯(lián)通、中國電信、天翼云、中移金科、Radore、ZaloPay等海內外數千家企業(yè)采用。KubeSphere 提供了開(kāi)發(fā)者友好的向導式操作界面和豐富的企業(yè)級功能,包括Kubernetes多云與多集群管理、DevOps(CI/CD)、應用生命周期管理、邊緣計算、微服務(wù)治理(ServiceMesh)、多租戶(hù)管理、可觀(guān)測性、存儲與網(wǎng)絡(luò )管理、GPUsupport等功能,幫助企業(yè)快速構建一個(gè)強大和功能豐富的容器云平臺。
?GitHub:官網(wǎng)(中國站):??微信群:請搜索添加群助手微信號kubesphere企業(yè)服務(wù):e.cloud
查看全部
云原生愛(ài)好者周刊:尋找 Netlify 開(kāi)源替代品
隨著(zhù)云原生技術(shù)的快速發(fā)展,技術(shù)的不斷迭代,對于日志的采集、處理及轉發(fā)提出了更高的要求。云原生架構下的日志方案相比基于物理機或者是虛擬機場(chǎng)景的日志架構設計存在很大差別。作為 CNCF 的畢業(yè)項目,Fluent Bit 無(wú)疑為解決云環(huán)境中的日志記錄問(wèn)題的首選解決方案之一。但是在 Kubernetes 中安裝部署以及配置 Fluent Bit 都具有一定的門(mén)檻,加大了用戶(hù)的使用成本。
本文從寫(xiě)作對個(gè)人的價(jià)值談到技術(shù)內容的創(chuàng )作選型,再到文章的排版和輔助工具,希望能幫助大家開(kāi)啟自己的技術(shù)內容創(chuàng )作之路。
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標[3]
對于 Prometheus 這種底層的時(shí)間序列數據庫來(lái)說(shuō),規模大了之后,免不了需要一定的手動(dòng)維護,這對于 Prometheus 的性能至關(guān)重要。這篇文章介紹了如何手動(dòng)刪除和丟棄無(wú)用的指標。
云原生動(dòng)態(tài)Harbor v2.5.0 引入 Cosign[4]
成品(Artifact)簽名和簽名驗證是關(guān)鍵的安全功能,允許你驗證成品的完整性。Harbor 通過(guò)與Notary 和 Cosign 的集成支持內容信任。
Harbor v2.5 集成了對 Cosign 的支持,這是一個(gè) OCI 成品簽名和驗證解決方案,是 Sigstore 項目的一部分。
將 Cosign 與 Harbor 結合使用的一個(gè)關(guān)鍵特性是能夠使用 Harbor 的復制功能來(lái)復制簽名及其相關(guān)的已簽名成品。這意味著(zhù),如果一個(gè)復制規則(replication rule)應用于一個(gè)已簽名成品,Harbo 將把復制規則應用于簽名,就像它應用于已簽名成品一樣。
Tanzu 應用平臺 1.1 版本發(fā)布[5]
Tanzu 應用平臺由 VMware 推出,旨在幫助用戶(hù)在任何公有云或本地 Kubernetes 集群上快速構建和部署軟件。Tanzu 應用平臺提供了一套豐富的開(kāi)發(fā)人員工具,并為支持生產(chǎn)的企業(yè)提供了一條預先鋪好的路徑,通過(guò)降低開(kāi)發(fā)人員工具的復雜性來(lái)更快地開(kāi)發(fā)創(chuàng )收應用程序。
1.1 版本提供了大量新功能,使企業(yè)能夠加快實(shí)現價(jià)值的時(shí)間、簡(jiǎn)化用戶(hù)體驗、建立更強大的安全態(tài)勢并保護他們已經(jīng)進(jìn)行的投資。這些領(lǐng)先的能力使企業(yè)能夠:
Kubernetes 1.24 發(fā)布推遲[6]
經(jīng)過(guò)一段時(shí)間的討論,發(fā)布團隊決定將預定的 Kubernetes 1.24 發(fā)布日推遲到 2022 年 5 月 3 日星期二。這比 2022 年 4 月 19 日星期二的原定發(fā)布日期延遲了兩周。
這是阻止發(fā)布 bug 的結果。該 bug 將在最新的 Golang 次要版本 Go 1.18.1 中修復,預計將于今天晚些時(shí)候發(fā)布。由于 Go 發(fā)布的延遲,發(fā)布團隊已采取措施將預定的 Kubernetes 發(fā)布日期延長(cháng)兩周,以便有足夠的時(shí)間進(jìn)行測試和穩定。
更新的時(shí)間表現在是:
4 月 19 日星期二的 1.24.0-rc.0。
4 月 26 日星期二的 1.24.0-rc.1。
1.24.0 于 5 月 3 日星期二正式發(fā)布。
WasmEdge 0.9.1 發(fā)布了!此版本集成了高性能 networking、JavaScript 流式 SSR 和 Fetch API 支持、新的 bindgen 框架、安卓和 OpenHarmony 操作系統支持、擴展的 Kubernetes 支持以及更好的內存管理。
Flagger 添加了網(wǎng)關(guān) API 支持[7]
Flagger 1.19.0 版本帶來(lái)了 Kubernetes Gateway API 的支持。
Flagger 是一個(gè)漸進(jìn)式的交付工具,它為運行在 Kubernetes 上的應用程序自動(dòng)化發(fā)布過(guò)程。它通過(guò)逐步將流量轉移到新版本,同時(shí)測量指標和運行一致性測試,降低了在生產(chǎn)中引入新軟件版本的風(fēng)險。
由于增加了對 Gateway API 的支持,Flagger 現在可以與所有的實(shí)現一起工作,這意味著(zhù)從今天起,這些都是原生支持:Contour, Emissary-Ingress, Google Kubernetes Engine, HAProxy Ingress, HashiCorp Consul, Istio, Kong and Traefik。
Flagger 團隊已經(jīng)使用 v1beta2 網(wǎng)關(guān) API 成功測試了 Contour 和 Istio。從 Flagger v1.19 開(kāi)始,網(wǎng)關(guān) API 是使用 Contour 實(shí)現的端到端測試套件的一部分。
引用鏈接[1]
Coolify:
[2]
Podman Desktop:
[3]
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標:
[4]
Harbor v2.5.0 引入 Cosign:
[5]
Tanzu 應用平臺 1.1 版本發(fā)布:
[6]
Kubernetes 1.24 發(fā)布推遲:
[7]
Flagger 添加了網(wǎng)關(guān) API 支持:
KubeSphere ()是在 Kubernetes 之上構建的開(kāi)源容器混合云,提供全棧的 IT 自動(dòng)化運維的能力,簡(jiǎn)化企業(yè)的 DevOps 工作流。
KubeSphere已被Aqara智能家居、愛(ài)立信、本來(lái)生活、東軟、華云、新浪、三一重工、華夏銀行、四川航空、國藥集團、微眾銀行、杭州數跑科技、紫金保險、去哪兒網(wǎng)、中通、中國人民銀行、中國銀行、中國人保壽險、中國太平保險、中國移動(dòng)、中國聯(lián)通、中國電信、天翼云、中移金科、Radore、ZaloPay等海內外數千家企業(yè)采用。KubeSphere 提供了開(kāi)發(fā)者友好的向導式操作界面和豐富的企業(yè)級功能,包括Kubernetes多云與多集群管理、DevOps(CI/CD)、應用生命周期管理、邊緣計算、微服務(wù)治理(ServiceMesh)、多租戶(hù)管理、可觀(guān)測性、存儲與網(wǎng)絡(luò )管理、GPUsupport等功能,幫助企業(yè)快速構建一個(gè)強大和功能豐富的容器云平臺。
?GitHub:官網(wǎng)(中國站):??微信群:請搜索添加群助手微信號kubesphere企業(yè)服務(wù):e.cloud
須臾現碼蟲(chóng),一鍵納乾坤——Hubble在微盟微前端中的應用
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 85 次瀏覽 ? 2022-04-29 20:30
通過(guò)Hubble的使用可以在一定程度上減少測試與研發(fā)在提bug、定位問(wèn)題上的溝通的成本,測試同學(xué)不用大段文字描述,研發(fā)同學(xué)能夠直觀(guān)地通過(guò)回放觀(guān)看bug出現的情況,以及根據接口或者報錯信息快速定位問(wèn)題以及復現bug。四、功能解析1.接入apm為了能記錄到接口請求的記錄,自行實(shí)現了一個(gè)rrweb插件,通過(guò)對瀏覽器原生的xhr 和 fetch api的覆寫(xiě),以實(shí)現請求信息的AOP。鑒于已存在A(yíng)PM系統,所以不對接口請求的請求體和響應體進(jìn)行記錄,只記錄下接口header中的apm trace id,在回放的時(shí)候可以通過(guò)這個(gè)trace id直接跳轉到APM系統中,來(lái)查看請求信息,協(xié)助排查和定位問(wèn)題。2.調試網(wǎng)頁(yè)免登錄Hubble的免登錄功能,是通過(guò)采集cookies中的saasAuth token來(lái)實(shí)現的。在管理頁(yè)面點(diǎn)擊免登錄查看時(shí),會(huì )跳轉到帶hubble特殊查詢(xún)參數的url,然后加載hubble時(shí)根據查詢(xún)參數判斷是免登錄查看模式的話(huà),將url中帶有的token寫(xiě)入到cookies中,然后跳轉到不帶特殊參數的頁(yè)面上,以實(shí)現跳過(guò)登錄環(huán)節完成鑒權。需要在頁(yè)面調用其他接口前完成Hubble的加載與判斷。token有時(shí)效性,可能會(huì )出現失效情況。為了避免非手動(dòng)退出來(lái)切換賬號所產(chǎn)生的混亂,建議打開(kāi)新的無(wú)痕窗口后粘貼免登錄鏈接查看。3.裁剪功能在解決錄制片段過(guò)長(cháng)的角度上,借助歸一化的概念,可以將裁剪到的所需時(shí)間段以外的事件,壓縮到一段比較短的時(shí)間內去播放,這樣就能實(shí)現近似裁剪功能了。
但是這屬于比較取巧的方案,后續會(huì )嘗試直接合并增量數據到全量snapshot數據上,這樣既能減少采集到的數據量,同時(shí)減輕剛開(kāi)始播放時(shí)的處理器計算壓力。4.未捕獲錯誤采集通過(guò)對window.onerror、unrejectionhandler和error事件的監聽(tīng),并將采集到的錯誤信息以自定義事件的形式插入到rrweb的record序列中,在回放時(shí)就可以通過(guò)面板查看到錯誤信息,輔助定位問(wèn)題。五、遇到的問(wèn)題1.樣式泄漏處理在開(kāi)發(fā)使用過(guò)程中,Hubble的瀏覽器端出現了樣式污染的問(wèn)題,除了對自己編寫(xiě)的組件內的過(guò)于普遍的樣式名進(jìn)行更改之外,還需要對整個(gè)Hubble進(jìn)行css的scope化。這里使用了部門(mén)內實(shí)現的postcss插件,在遍歷css rules的時(shí)候(使用postcss的walkRules API),對規則內的所有css選擇器前面,添加了一個(gè)當前包名 .${packageJson.name} 的一個(gè)類(lèi)作為父選擇器,同時(shí)在Hubble掛載的dom上也加上了這個(gè)className。同時(shí),在一些使用了css變量的UI組件庫,有些會(huì )將css變量定義在 :root 上,這是一個(gè)全局的偽類(lèi),如果不進(jìn)行處理的話(huà),css變量會(huì )泄漏并污染到全局。
于是在上述的postcss插件中也加入了:root 到 作用域類(lèi)名替換的規則。2.打包加載優(yōu)化為了優(yōu)化初始化速度(更快進(jìn)入錄制狀態(tài))和防止大體積bundle加載帶來(lái)的阻塞,且后續能支持插件化、sdk可拼裝,打包形式上從iife改為system。這樣在初始加載時(shí)能夠優(yōu)先加載主要功能并運行起來(lái),ui部分進(jìn)行延遲加載;同時(shí)拆解成system形式的包之后,后續可以根據配置來(lái)動(dòng)態(tài)加載功能,預留出擴展能力。六、未來(lái)預計添加的功能1.開(kāi)放接入能力基于systemjs的動(dòng)態(tài)加載腳本的能力,Hubble可以通過(guò)配置來(lái)動(dòng)態(tài)加載插件。后續考慮在這基礎上開(kāi)放出一些api以及自定義插件功能,比如可以使用hubble的addCustomEvent API來(lái)添加自定義事件,或者采集靜態(tài)數據直接上傳到hubble的后端。2.涂鴉評論功能在錄制的記錄上,有時(shí)候需要給錄制到的內容進(jìn)行標注評論以輔助傳遞信息,增強理解?,F計劃在后續添加涂鴉評論功能。涂鴉基于canvas,可以提交面板上編輯,記錄下打標注的地方以及持續時(shí)長(cháng),也考慮添加圖層功能來(lái)支持更復雜的標注能力。七、擴展閱讀Hubble主要是圍繞rrweb 這個(gè)dom錄制框架進(jìn)行開(kāi)發(fā)的。
rrweb是通過(guò)MutationObserver API來(lái)監聽(tīng)頁(yè)面上dom的變動(dòng),以及用戶(hù)輸入的各種操作事件進(jìn)行捕獲采集,然后通過(guò)rrweb的DOM序列化算法將DOM結構json化,以及事件行為的格式化,形成一個(gè)變動(dòng)更新列表,然后在回放的時(shí)候,通過(guò)將序列化的dom數據通過(guò)rebuild,和事件行為的重放,重現在一個(gè)iframe沙盒中,來(lái)實(shí)現頁(yè)面操作的回放。其中,rrweb主要有這些事件類(lèi)型:dom加載完成、加載、全量快照、增量快照、元數據、自定義事件、插件事件。而其中的增量快照則有這些數據來(lái)源:dom Mutation、鼠標鍵盤(pán)滾輪觸摸等操作、窗口resize、輸入框輸入、樣式變動(dòng)等。錄制開(kāi)始后,rrweb會(huì )將每次dom變動(dòng),監聽(tīng)到的事件,自定義觸發(fā)事件等錄制到的數據通過(guò)一個(gè)數組來(lái)保存,每個(gè)事件對應著(zhù)一個(gè)事件對象,其中含有觸發(fā)時(shí)的時(shí)間戳、事件類(lèi)型、內容載體payload等。在rrweb上生成一個(gè)dom的全量快照時(shí),會(huì )給當前的dom元素一個(gè)個(gè)分配一個(gè)id,用來(lái)記錄和追蹤其變化。當增量數據中dom的變動(dòng)要apply到snapshot對應的dom樹(shù)上時(shí),會(huì )根據id查找出目標dom節點(diǎn),將MutationObserver 監聽(tīng)到的dom變化應用到數據模型上。
?。╮rweb維護了一個(gè)node Map,以方便快速查找到節點(diǎn))當在播放器進(jìn)行操作時(shí),比如進(jìn)行時(shí)間跳轉(goto),會(huì )通過(guò)狀態(tài)機和事件管道,先暫停再調用播放。調用播放函數時(shí)傳入了跳轉的timeOffset,這時(shí)會(huì )進(jìn)行如下處理:暫停時(shí)會(huì )記錄播放的最后event,然后再開(kāi)始時(shí),首先會(huì )計算出跳轉后的時(shí)間偏移量,來(lái)定義一個(gè)基準時(shí)間戳(跳轉后的時(shí)間戳)。對于小于基準時(shí)間戳的事件,會(huì )以同步的方式全部apply起來(lái),而剩余的事件則是用定時(shí)器觸發(fā)。同時(shí),會(huì )把基準事件戳與上次播放的最后的event中含有的時(shí)間戳進(jìn)行比對,如果往前跳則清除節點(diǎn)Map數據,以同步方式重新計算;如果是往后跳則將同步計算的結果合并到已有的節點(diǎn)Map上。在定時(shí)器的使用上,由于setInterval會(huì )受到性能等各方面影響,這種事件定時(shí)器在精度上不能滿(mǎn)足需求。于是rrweb使用了requestAnimationFrame的API來(lái)作為定時(shí)器(機制上因為不受到eventloop的影響,精度能達到1ms級別),使用performance.now()來(lái)作為獲取每次觸發(fā)定時(shí)器callback的時(shí)間偏移量(減去初始值),從而準確地觸發(fā)rrweb待播放List中的事件。八、結語(yǔ)不通過(guò)口述或者截圖等方式、而是通過(guò)錄屏的方式進(jìn)行記錄,同時(shí)可以記錄接口等數據,這樣可以在復現前端場(chǎng)景上節省溝通成本、快速定位問(wèn)題,從而提高效率。我們也會(huì )在后續的迭代中,尋找合適的場(chǎng)景落地,嘗試更多方案,助力開(kāi)發(fā)提效。 查看全部
須臾現碼蟲(chóng),一鍵納乾坤——Hubble在微盟微前端中的應用
通過(guò)Hubble的使用可以在一定程度上減少測試與研發(fā)在提bug、定位問(wèn)題上的溝通的成本,測試同學(xué)不用大段文字描述,研發(fā)同學(xué)能夠直觀(guān)地通過(guò)回放觀(guān)看bug出現的情況,以及根據接口或者報錯信息快速定位問(wèn)題以及復現bug。四、功能解析1.接入apm為了能記錄到接口請求的記錄,自行實(shí)現了一個(gè)rrweb插件,通過(guò)對瀏覽器原生的xhr 和 fetch api的覆寫(xiě),以實(shí)現請求信息的AOP。鑒于已存在A(yíng)PM系統,所以不對接口請求的請求體和響應體進(jìn)行記錄,只記錄下接口header中的apm trace id,在回放的時(shí)候可以通過(guò)這個(gè)trace id直接跳轉到APM系統中,來(lái)查看請求信息,協(xié)助排查和定位問(wèn)題。2.調試網(wǎng)頁(yè)免登錄Hubble的免登錄功能,是通過(guò)采集cookies中的saasAuth token來(lái)實(shí)現的。在管理頁(yè)面點(diǎn)擊免登錄查看時(shí),會(huì )跳轉到帶hubble特殊查詢(xún)參數的url,然后加載hubble時(shí)根據查詢(xún)參數判斷是免登錄查看模式的話(huà),將url中帶有的token寫(xiě)入到cookies中,然后跳轉到不帶特殊參數的頁(yè)面上,以實(shí)現跳過(guò)登錄環(huán)節完成鑒權。需要在頁(yè)面調用其他接口前完成Hubble的加載與判斷。token有時(shí)效性,可能會(huì )出現失效情況。為了避免非手動(dòng)退出來(lái)切換賬號所產(chǎn)生的混亂,建議打開(kāi)新的無(wú)痕窗口后粘貼免登錄鏈接查看。3.裁剪功能在解決錄制片段過(guò)長(cháng)的角度上,借助歸一化的概念,可以將裁剪到的所需時(shí)間段以外的事件,壓縮到一段比較短的時(shí)間內去播放,這樣就能實(shí)現近似裁剪功能了。
但是這屬于比較取巧的方案,后續會(huì )嘗試直接合并增量數據到全量snapshot數據上,這樣既能減少采集到的數據量,同時(shí)減輕剛開(kāi)始播放時(shí)的處理器計算壓力。4.未捕獲錯誤采集通過(guò)對window.onerror、unrejectionhandler和error事件的監聽(tīng),并將采集到的錯誤信息以自定義事件的形式插入到rrweb的record序列中,在回放時(shí)就可以通過(guò)面板查看到錯誤信息,輔助定位問(wèn)題。五、遇到的問(wèn)題1.樣式泄漏處理在開(kāi)發(fā)使用過(guò)程中,Hubble的瀏覽器端出現了樣式污染的問(wèn)題,除了對自己編寫(xiě)的組件內的過(guò)于普遍的樣式名進(jìn)行更改之外,還需要對整個(gè)Hubble進(jìn)行css的scope化。這里使用了部門(mén)內實(shí)現的postcss插件,在遍歷css rules的時(shí)候(使用postcss的walkRules API),對規則內的所有css選擇器前面,添加了一個(gè)當前包名 .${packageJson.name} 的一個(gè)類(lèi)作為父選擇器,同時(shí)在Hubble掛載的dom上也加上了這個(gè)className。同時(shí),在一些使用了css變量的UI組件庫,有些會(huì )將css變量定義在 :root 上,這是一個(gè)全局的偽類(lèi),如果不進(jìn)行處理的話(huà),css變量會(huì )泄漏并污染到全局。
于是在上述的postcss插件中也加入了:root 到 作用域類(lèi)名替換的規則。2.打包加載優(yōu)化為了優(yōu)化初始化速度(更快進(jìn)入錄制狀態(tài))和防止大體積bundle加載帶來(lái)的阻塞,且后續能支持插件化、sdk可拼裝,打包形式上從iife改為system。這樣在初始加載時(shí)能夠優(yōu)先加載主要功能并運行起來(lái),ui部分進(jìn)行延遲加載;同時(shí)拆解成system形式的包之后,后續可以根據配置來(lái)動(dòng)態(tài)加載功能,預留出擴展能力。六、未來(lái)預計添加的功能1.開(kāi)放接入能力基于systemjs的動(dòng)態(tài)加載腳本的能力,Hubble可以通過(guò)配置來(lái)動(dòng)態(tài)加載插件。后續考慮在這基礎上開(kāi)放出一些api以及自定義插件功能,比如可以使用hubble的addCustomEvent API來(lái)添加自定義事件,或者采集靜態(tài)數據直接上傳到hubble的后端。2.涂鴉評論功能在錄制的記錄上,有時(shí)候需要給錄制到的內容進(jìn)行標注評論以輔助傳遞信息,增強理解?,F計劃在后續添加涂鴉評論功能。涂鴉基于canvas,可以提交面板上編輯,記錄下打標注的地方以及持續時(shí)長(cháng),也考慮添加圖層功能來(lái)支持更復雜的標注能力。七、擴展閱讀Hubble主要是圍繞rrweb 這個(gè)dom錄制框架進(jìn)行開(kāi)發(fā)的。
rrweb是通過(guò)MutationObserver API來(lái)監聽(tīng)頁(yè)面上dom的變動(dòng),以及用戶(hù)輸入的各種操作事件進(jìn)行捕獲采集,然后通過(guò)rrweb的DOM序列化算法將DOM結構json化,以及事件行為的格式化,形成一個(gè)變動(dòng)更新列表,然后在回放的時(shí)候,通過(guò)將序列化的dom數據通過(guò)rebuild,和事件行為的重放,重現在一個(gè)iframe沙盒中,來(lái)實(shí)現頁(yè)面操作的回放。其中,rrweb主要有這些事件類(lèi)型:dom加載完成、加載、全量快照、增量快照、元數據、自定義事件、插件事件。而其中的增量快照則有這些數據來(lái)源:dom Mutation、鼠標鍵盤(pán)滾輪觸摸等操作、窗口resize、輸入框輸入、樣式變動(dòng)等。錄制開(kāi)始后,rrweb會(huì )將每次dom變動(dòng),監聽(tīng)到的事件,自定義觸發(fā)事件等錄制到的數據通過(guò)一個(gè)數組來(lái)保存,每個(gè)事件對應著(zhù)一個(gè)事件對象,其中含有觸發(fā)時(shí)的時(shí)間戳、事件類(lèi)型、內容載體payload等。在rrweb上生成一個(gè)dom的全量快照時(shí),會(huì )給當前的dom元素一個(gè)個(gè)分配一個(gè)id,用來(lái)記錄和追蹤其變化。當增量數據中dom的變動(dòng)要apply到snapshot對應的dom樹(shù)上時(shí),會(huì )根據id查找出目標dom節點(diǎn),將MutationObserver 監聽(tīng)到的dom變化應用到數據模型上。
?。╮rweb維護了一個(gè)node Map,以方便快速查找到節點(diǎn))當在播放器進(jìn)行操作時(shí),比如進(jìn)行時(shí)間跳轉(goto),會(huì )通過(guò)狀態(tài)機和事件管道,先暫停再調用播放。調用播放函數時(shí)傳入了跳轉的timeOffset,這時(shí)會(huì )進(jìn)行如下處理:暫停時(shí)會(huì )記錄播放的最后event,然后再開(kāi)始時(shí),首先會(huì )計算出跳轉后的時(shí)間偏移量,來(lái)定義一個(gè)基準時(shí)間戳(跳轉后的時(shí)間戳)。對于小于基準時(shí)間戳的事件,會(huì )以同步的方式全部apply起來(lái),而剩余的事件則是用定時(shí)器觸發(fā)。同時(shí),會(huì )把基準事件戳與上次播放的最后的event中含有的時(shí)間戳進(jìn)行比對,如果往前跳則清除節點(diǎn)Map數據,以同步方式重新計算;如果是往后跳則將同步計算的結果合并到已有的節點(diǎn)Map上。在定時(shí)器的使用上,由于setInterval會(huì )受到性能等各方面影響,這種事件定時(shí)器在精度上不能滿(mǎn)足需求。于是rrweb使用了requestAnimationFrame的API來(lái)作為定時(shí)器(機制上因為不受到eventloop的影響,精度能達到1ms級別),使用performance.now()來(lái)作為獲取每次觸發(fā)定時(shí)器callback的時(shí)間偏移量(減去初始值),從而準確地觸發(fā)rrweb待播放List中的事件。八、結語(yǔ)不通過(guò)口述或者截圖等方式、而是通過(guò)錄屏的方式進(jìn)行記錄,同時(shí)可以記錄接口等數據,這樣可以在復現前端場(chǎng)景上節省溝通成本、快速定位問(wèn)題,從而提高效率。我們也會(huì )在后續的迭代中,尋找合適的場(chǎng)景落地,嘗試更多方案,助力開(kāi)發(fā)提效。
京東到家自動(dòng)化測試平臺的探索與實(shí)踐
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 75 次瀏覽 ? 2022-04-28 20:45
HTTP服務(wù)的流量復制可以通過(guò)一些代理工具來(lái)實(shí)現。Mitmproxy是一款免費、開(kāi)放的基于Python開(kāi)發(fā)的交互式HTTPS代理工具。它可以用來(lái)捕獲HTTP/HTTPS請求,支持抓包、斷點(diǎn)調試、請求替換、構造請求、模擬弱網(wǎng)等功能。
工作原理如下:
流量復制的實(shí)現具體可以分為以下幾個(gè)步驟:
1. 在電腦或手機端配置Mitmproxy代理服務(wù)器地址,此時(shí)電腦或手機的所有請求都通過(guò)代理服務(wù)器進(jìn)行請求發(fā)出,當請求響應結束后,代理服務(wù)器識別出我們需要攔截的請求,并將請求和響應結果轉發(fā)到我們的自動(dòng)化測試平臺;2. 測試平臺收到代理服務(wù)器轉發(fā)過(guò)來(lái)的請求和響應結果后,會(huì )將數據按照服務(wù)維度進(jìn)行分類(lèi),作為初步的種子用例,持久化到數據庫中;3. 測試人員依據種子用例,轉換成正式的測試用例;
下圖代碼片段是按域名截取數據后,整合平臺所需要的數據和數據格式:
效果展示
2.2 微服務(wù)流量復制
微服務(wù)的流量復制我們是通過(guò)自研客戶(hù)端+配置采集規則來(lái)實(shí)現的。規則配置
交互邏輯
具體實(shí)現步驟如下:
1. 管理端配置服務(wù)的采集規則;2. 客戶(hù)端定時(shí)拉取采集規則;3. 符合采集規則,則將請求入參和出參寫(xiě)入本地文件;4. 客戶(hù)端定期上報流量采集內容到精衛平臺;5. 按照服務(wù),時(shí)間段等維度圈出要回歸的流量用例,生成回歸任務(wù);6. 執行任務(wù),進(jìn)行流量回放;7. 生成流量回放的測試報告;如果之前沒(méi)有維護過(guò)測試用例,也可以通過(guò)開(kāi)啟流量復制功能來(lái)快速的實(shí)現回歸測試;總之,通過(guò)流量復制,將線(xiàn)上的真實(shí)流量引入到灰度測試環(huán)境中進(jìn)行回放,不僅能夠降低人工參與的成本,還可以更加真實(shí)的還原線(xiàn)上場(chǎng)景,使問(wèn)題更加高效客觀(guān)的呈現。
2.3 自動(dòng)生成種子用例
在用例維護過(guò)程當中,如何快速生成一個(gè)正確的樣本示例是我們經(jīng)常面臨的問(wèn)題。為了解決這個(gè)問(wèn)題我們搭建了API接口文檔管理平臺。這個(gè)平臺目的主要是將服務(wù)定義元數據進(jìn)行實(shí)時(shí)的線(xiàn)上化管理,可以隨時(shí)可查看各個(gè)部署版本的接口定義元數據(包括版本、入參、類(lèi)型、格式、示例等)?;诰€(xiàn)上化的接口定義智能生成最新的入參結構,支持微服務(wù)和HTTP等協(xié)議。
在創(chuàng )建用例時(shí),精衛平臺會(huì )拉取服務(wù)的方法和接口定義的相關(guān)信息(入參定義,出參定義,參數示例),解析參數結構,快速生成種子用例,提高新用例的創(chuàng )建效率。
一個(gè)完整的新用例的創(chuàng )建過(guò)程如下:
1.選擇所需的種子用例;
2.調整入參數據;3.補全用例名稱(chēng)、用途等信息;4.設置斷言檢查點(diǎn)等信息;
2.4收益評估
1. 測試人員不需要再進(jìn)行抓包,查日志來(lái)獲取自動(dòng)化測試數據,減少了30%左右用來(lái)創(chuàng )建測試用例的時(shí)間;2. 可以實(shí)時(shí)獲取最新的接口定義元數據,避免了接口定義的不準確性,同時(shí)降低了線(xiàn)下跟研發(fā)獲取接口定義的時(shí)間成本;3. 通過(guò)預設的斷言配置,用例執行結果的正確性檢查借助平臺實(shí)現了自動(dòng)化,大幅度提升了測試效率;三、自動(dòng)化回歸測試精衛平臺的自動(dòng)化回歸測試分為接口自動(dòng)化和流程自動(dòng)化兩個(gè)維度。下面將從這兩個(gè)部分來(lái)介紹。3.1接口自動(dòng)化接口測試是測試系統組件間接口的一種測試方式,主要用于檢測系統內部、系統間的交互點(diǎn),常作為功能測試的基本單元。接口自動(dòng)化就是將一批接口測試用例打包并自動(dòng)執行,以達到節省人力、時(shí)間、資源成本,快速驗證回歸測試服務(wù)正確性,提升測試效率的目的。
3.1.1 設計方案
自動(dòng)化回歸測試依托于持續集成部署平臺,當服務(wù)部署發(fā)布后,借助api接口文檔管理平臺,可以自動(dòng)識別出變更的服務(wù)方法,觸發(fā)自動(dòng)化回歸測試任務(wù),自動(dòng)回歸有代碼變更方法的用例。
3.1.2 執行過(guò)程
1. 用例錄制:接口自動(dòng)化回歸的前提條件是已經(jīng)擁有了測試用例;2. 圈定回歸范圍:同一接口的測試用例按照用途會(huì )分為多組,比如:?jiǎn)卧獪y試用例,回歸測試用例,壓測用例等,圈定出錄制的回歸測試用例;
3. 創(chuàng )建回歸測試任務(wù):支持全量/增量回歸,全量回歸可以進(jìn)行代碼覆蓋率的統計;4. 執行回歸測試任務(wù):當服務(wù)部署后,自動(dòng)觸發(fā)回歸任務(wù)的執行;5. 生成測試報告:任務(wù)用例執行完成后,會(huì )生成一份測試報告,報告中含用例通過(guò)率、代碼覆蓋率、問(wèn)題處理建議等信息;
3.1.3成果收益
接口自動(dòng)化測試減少了測試的執行時(shí)間,降低了回歸測試的實(shí)現門(mén)檻,有效的縮短了產(chǎn)品交付周期,測試人員有更多的時(shí)間和精力投入到產(chǎn)品業(yè)務(wù)本身上面去。3.2 流程自動(dòng)化速搭平臺是京東到家為研發(fā)和測試人員提供的一站式服務(wù)發(fā)布平臺,其核心是通過(guò)我們現有能力(微服務(wù)或http服務(wù))的再次加工(編排),形成新的能力,精衛平臺借助此能力實(shí)現流程自動(dòng)化測試。
3.2.1 設計方案
業(yè)務(wù)架構圖
3.2.2執行過(guò)程
1. 構建步驟:步驟是組成流程的最小執行單元,單個(gè)步驟可以理解為一個(gè)服務(wù);2. 構建流程:把各個(gè)步驟按照業(yè)務(wù)邏輯編排起來(lái)構成流程;
3. 設計流程用例:定義流程入參、設置斷言,創(chuàng )建流程用例;
4. 構建流程任務(wù):按照業(yè)務(wù)圈定要執行的流程用例,以任務(wù)的方式集中執行;
5. 執行流程任務(wù):支持手動(dòng)觸發(fā)和定時(shí)執行等方式,以達到回歸或巡檢的目的;
6. 任務(wù)執行報告:通過(guò)率、代碼覆蓋率、執行結果日志等報告信息,如有異常情況發(fā)送告警通知。
3.2.3 成果收益
1. 已經(jīng)初步完成核心場(chǎng)景的全覆蓋自動(dòng)回歸,在需求迭代效率上有了很大的提升;2. 流程測試與用戶(hù)真實(shí)操作更相近,可以更好的站著(zhù)用戶(hù)的角度驗證產(chǎn)品,利用黃金流程的實(shí)時(shí)巡檢機制,系統在穩定性方面也得到了更好的保障;3.3 回歸機制不同的場(chǎng)景下回歸的機制會(huì )有所不同。比如:3.3.1 一鍵回歸
研發(fā)發(fā)起提測后,針對圈定的服務(wù)和方法可以進(jìn)行一鍵全量/增量的回歸測試。
3.3.2 自動(dòng)回歸自動(dòng)回歸測試的觸發(fā)方式有部署后自動(dòng)回歸,線(xiàn)上的定時(shí)巡檢等場(chǎng)景。1. 日常巡檢平臺支持cron表達式,對多任務(wù)、多用例進(jìn)行定時(shí)執行,并在失敗或者異常后進(jìn)行預警。
2. 應用部署后自動(dòng)回歸支持全量和增量回歸。應用部署后,對API文檔變更的內容進(jìn)行自動(dòng)回歸、生成測試報告,在失敗或者異常時(shí)進(jìn)行預警。四、提升測試質(zhì)量測試質(zhì)量的把控可以從技術(shù)和流程兩個(gè)方面來(lái)考慮,技術(shù)層面主要依賴(lài)于度量指標的提升(用例通過(guò)率,代碼覆蓋率等),流程方面可以通過(guò)設置質(zhì)量門(mén)禁等方式來(lái)保證提測質(zhì)量。4.1 代碼覆蓋率代碼覆蓋率是軟件測試中的一種度量,描述程序中源代碼被測試的比例和程度,所得比例稱(chēng)為代碼覆蓋率。平臺實(shí)現原理:
實(shí)現方式可參照另一篇文章:《》
4.2 設置質(zhì)量門(mén)禁根據測試金字塔模型,我們知道問(wèn)題越早暴露,解決問(wèn)題的成本越低。單元測試的充分性是提高整個(gè)測試效率的關(guān)鍵,設置質(zhì)量門(mén)禁(單元測試通過(guò)率)是保證提測質(zhì)量的重要手段。如何設置質(zhì)量門(mén)禁的呢?我們具體來(lái)看一下整個(gè)提測流程:1. 維護單元測試用例:研發(fā)維護服務(wù)的單元測試用例;2. 圈定提測范圍:研發(fā)選擇要回歸的服務(wù)列表;
3. 生成單元測試任務(wù):根據圈定的服務(wù)列表,篩選出對應的單元你測試用例,生成單元測試任務(wù);4. 執行測試任務(wù):批量執行單元測試用例,達到設置的門(mén)禁標準(通過(guò)率,覆蓋率等)才可進(jìn)入測試環(huán)節;
5. 進(jìn)入測試流程:達到提測標準后,進(jìn)入正式測試環(huán)節,測試人員針對提測服務(wù)和測試重點(diǎn)進(jìn)行針對性的測試。
五、總結及其它5.1總結精衛平臺作為實(shí)現持續集成/發(fā)布(CI/CD)的基礎設施,其目標是保證代碼具備隨時(shí)可以發(fā)布到線(xiàn)上的良好狀態(tài),維持團隊的持續交付能力。另外,平臺在效率提升方面也取得了顯著(zhù)效果:
5.2展望軟件度量是對軟件開(kāi)發(fā)項目、過(guò)程、及其產(chǎn)品進(jìn)行數據定義、收集以及分析的持續性量化過(guò)程。通過(guò)軟件度量可以改進(jìn)軟件開(kāi)發(fā)過(guò)程,促進(jìn)項目成功,開(kāi)發(fā)高質(zhì)量的軟件產(chǎn)品。平臺將繼續對整個(gè)產(chǎn)品交付過(guò)程中的指標數據進(jìn)行整理、挖掘,發(fā)現過(guò)程中存在的問(wèn)題和短板,優(yōu)化和反哺產(chǎn)品交付流程,在效率和穩定性等方面獲得更大的突破。5.3附錄
平臺架構
核心流程
查看全部
京東到家自動(dòng)化測試平臺的探索與實(shí)踐
HTTP服務(wù)的流量復制可以通過(guò)一些代理工具來(lái)實(shí)現。Mitmproxy是一款免費、開(kāi)放的基于Python開(kāi)發(fā)的交互式HTTPS代理工具。它可以用來(lái)捕獲HTTP/HTTPS請求,支持抓包、斷點(diǎn)調試、請求替換、構造請求、模擬弱網(wǎng)等功能。
工作原理如下:
流量復制的實(shí)現具體可以分為以下幾個(gè)步驟:
1. 在電腦或手機端配置Mitmproxy代理服務(wù)器地址,此時(shí)電腦或手機的所有請求都通過(guò)代理服務(wù)器進(jìn)行請求發(fā)出,當請求響應結束后,代理服務(wù)器識別出我們需要攔截的請求,并將請求和響應結果轉發(fā)到我們的自動(dòng)化測試平臺;2. 測試平臺收到代理服務(wù)器轉發(fā)過(guò)來(lái)的請求和響應結果后,會(huì )將數據按照服務(wù)維度進(jìn)行分類(lèi),作為初步的種子用例,持久化到數據庫中;3. 測試人員依據種子用例,轉換成正式的測試用例;
下圖代碼片段是按域名截取數據后,整合平臺所需要的數據和數據格式:
效果展示
2.2 微服務(wù)流量復制
微服務(wù)的流量復制我們是通過(guò)自研客戶(hù)端+配置采集規則來(lái)實(shí)現的。規則配置
交互邏輯
具體實(shí)現步驟如下:
1. 管理端配置服務(wù)的采集規則;2. 客戶(hù)端定時(shí)拉取采集規則;3. 符合采集規則,則將請求入參和出參寫(xiě)入本地文件;4. 客戶(hù)端定期上報流量采集內容到精衛平臺;5. 按照服務(wù),時(shí)間段等維度圈出要回歸的流量用例,生成回歸任務(wù);6. 執行任務(wù),進(jìn)行流量回放;7. 生成流量回放的測試報告;如果之前沒(méi)有維護過(guò)測試用例,也可以通過(guò)開(kāi)啟流量復制功能來(lái)快速的實(shí)現回歸測試;總之,通過(guò)流量復制,將線(xiàn)上的真實(shí)流量引入到灰度測試環(huán)境中進(jìn)行回放,不僅能夠降低人工參與的成本,還可以更加真實(shí)的還原線(xiàn)上場(chǎng)景,使問(wèn)題更加高效客觀(guān)的呈現。
2.3 自動(dòng)生成種子用例
在用例維護過(guò)程當中,如何快速生成一個(gè)正確的樣本示例是我們經(jīng)常面臨的問(wèn)題。為了解決這個(gè)問(wèn)題我們搭建了API接口文檔管理平臺。這個(gè)平臺目的主要是將服務(wù)定義元數據進(jìn)行實(shí)時(shí)的線(xiàn)上化管理,可以隨時(shí)可查看各個(gè)部署版本的接口定義元數據(包括版本、入參、類(lèi)型、格式、示例等)?;诰€(xiàn)上化的接口定義智能生成最新的入參結構,支持微服務(wù)和HTTP等協(xié)議。
在創(chuàng )建用例時(shí),精衛平臺會(huì )拉取服務(wù)的方法和接口定義的相關(guān)信息(入參定義,出參定義,參數示例),解析參數結構,快速生成種子用例,提高新用例的創(chuàng )建效率。
一個(gè)完整的新用例的創(chuàng )建過(guò)程如下:
1.選擇所需的種子用例;
2.調整入參數據;3.補全用例名稱(chēng)、用途等信息;4.設置斷言檢查點(diǎn)等信息;
2.4收益評估
1. 測試人員不需要再進(jìn)行抓包,查日志來(lái)獲取自動(dòng)化測試數據,減少了30%左右用來(lái)創(chuàng )建測試用例的時(shí)間;2. 可以實(shí)時(shí)獲取最新的接口定義元數據,避免了接口定義的不準確性,同時(shí)降低了線(xiàn)下跟研發(fā)獲取接口定義的時(shí)間成本;3. 通過(guò)預設的斷言配置,用例執行結果的正確性檢查借助平臺實(shí)現了自動(dòng)化,大幅度提升了測試效率;三、自動(dòng)化回歸測試精衛平臺的自動(dòng)化回歸測試分為接口自動(dòng)化和流程自動(dòng)化兩個(gè)維度。下面將從這兩個(gè)部分來(lái)介紹。3.1接口自動(dòng)化接口測試是測試系統組件間接口的一種測試方式,主要用于檢測系統內部、系統間的交互點(diǎn),常作為功能測試的基本單元。接口自動(dòng)化就是將一批接口測試用例打包并自動(dòng)執行,以達到節省人力、時(shí)間、資源成本,快速驗證回歸測試服務(wù)正確性,提升測試效率的目的。
3.1.1 設計方案
自動(dòng)化回歸測試依托于持續集成部署平臺,當服務(wù)部署發(fā)布后,借助api接口文檔管理平臺,可以自動(dòng)識別出變更的服務(wù)方法,觸發(fā)自動(dòng)化回歸測試任務(wù),自動(dòng)回歸有代碼變更方法的用例。
3.1.2 執行過(guò)程
1. 用例錄制:接口自動(dòng)化回歸的前提條件是已經(jīng)擁有了測試用例;2. 圈定回歸范圍:同一接口的測試用例按照用途會(huì )分為多組,比如:?jiǎn)卧獪y試用例,回歸測試用例,壓測用例等,圈定出錄制的回歸測試用例;
3. 創(chuàng )建回歸測試任務(wù):支持全量/增量回歸,全量回歸可以進(jìn)行代碼覆蓋率的統計;4. 執行回歸測試任務(wù):當服務(wù)部署后,自動(dòng)觸發(fā)回歸任務(wù)的執行;5. 生成測試報告:任務(wù)用例執行完成后,會(huì )生成一份測試報告,報告中含用例通過(guò)率、代碼覆蓋率、問(wèn)題處理建議等信息;
3.1.3成果收益
接口自動(dòng)化測試減少了測試的執行時(shí)間,降低了回歸測試的實(shí)現門(mén)檻,有效的縮短了產(chǎn)品交付周期,測試人員有更多的時(shí)間和精力投入到產(chǎn)品業(yè)務(wù)本身上面去。3.2 流程自動(dòng)化速搭平臺是京東到家為研發(fā)和測試人員提供的一站式服務(wù)發(fā)布平臺,其核心是通過(guò)我們現有能力(微服務(wù)或http服務(wù))的再次加工(編排),形成新的能力,精衛平臺借助此能力實(shí)現流程自動(dòng)化測試。
3.2.1 設計方案
業(yè)務(wù)架構圖
3.2.2執行過(guò)程
1. 構建步驟:步驟是組成流程的最小執行單元,單個(gè)步驟可以理解為一個(gè)服務(wù);2. 構建流程:把各個(gè)步驟按照業(yè)務(wù)邏輯編排起來(lái)構成流程;
3. 設計流程用例:定義流程入參、設置斷言,創(chuàng )建流程用例;
4. 構建流程任務(wù):按照業(yè)務(wù)圈定要執行的流程用例,以任務(wù)的方式集中執行;
5. 執行流程任務(wù):支持手動(dòng)觸發(fā)和定時(shí)執行等方式,以達到回歸或巡檢的目的;
6. 任務(wù)執行報告:通過(guò)率、代碼覆蓋率、執行結果日志等報告信息,如有異常情況發(fā)送告警通知。
3.2.3 成果收益
1. 已經(jīng)初步完成核心場(chǎng)景的全覆蓋自動(dòng)回歸,在需求迭代效率上有了很大的提升;2. 流程測試與用戶(hù)真實(shí)操作更相近,可以更好的站著(zhù)用戶(hù)的角度驗證產(chǎn)品,利用黃金流程的實(shí)時(shí)巡檢機制,系統在穩定性方面也得到了更好的保障;3.3 回歸機制不同的場(chǎng)景下回歸的機制會(huì )有所不同。比如:3.3.1 一鍵回歸
研發(fā)發(fā)起提測后,針對圈定的服務(wù)和方法可以進(jìn)行一鍵全量/增量的回歸測試。
3.3.2 自動(dòng)回歸自動(dòng)回歸測試的觸發(fā)方式有部署后自動(dòng)回歸,線(xiàn)上的定時(shí)巡檢等場(chǎng)景。1. 日常巡檢平臺支持cron表達式,對多任務(wù)、多用例進(jìn)行定時(shí)執行,并在失敗或者異常后進(jìn)行預警。
2. 應用部署后自動(dòng)回歸支持全量和增量回歸。應用部署后,對API文檔變更的內容進(jìn)行自動(dòng)回歸、生成測試報告,在失敗或者異常時(shí)進(jìn)行預警。四、提升測試質(zhì)量測試質(zhì)量的把控可以從技術(shù)和流程兩個(gè)方面來(lái)考慮,技術(shù)層面主要依賴(lài)于度量指標的提升(用例通過(guò)率,代碼覆蓋率等),流程方面可以通過(guò)設置質(zhì)量門(mén)禁等方式來(lái)保證提測質(zhì)量。4.1 代碼覆蓋率代碼覆蓋率是軟件測試中的一種度量,描述程序中源代碼被測試的比例和程度,所得比例稱(chēng)為代碼覆蓋率。平臺實(shí)現原理:
實(shí)現方式可參照另一篇文章:《》
4.2 設置質(zhì)量門(mén)禁根據測試金字塔模型,我們知道問(wèn)題越早暴露,解決問(wèn)題的成本越低。單元測試的充分性是提高整個(gè)測試效率的關(guān)鍵,設置質(zhì)量門(mén)禁(單元測試通過(guò)率)是保證提測質(zhì)量的重要手段。如何設置質(zhì)量門(mén)禁的呢?我們具體來(lái)看一下整個(gè)提測流程:1. 維護單元測試用例:研發(fā)維護服務(wù)的單元測試用例;2. 圈定提測范圍:研發(fā)選擇要回歸的服務(wù)列表;
3. 生成單元測試任務(wù):根據圈定的服務(wù)列表,篩選出對應的單元你測試用例,生成單元測試任務(wù);4. 執行測試任務(wù):批量執行單元測試用例,達到設置的門(mén)禁標準(通過(guò)率,覆蓋率等)才可進(jìn)入測試環(huán)節;
5. 進(jìn)入測試流程:達到提測標準后,進(jìn)入正式測試環(huán)節,測試人員針對提測服務(wù)和測試重點(diǎn)進(jìn)行針對性的測試。
五、總結及其它5.1總結精衛平臺作為實(shí)現持續集成/發(fā)布(CI/CD)的基礎設施,其目標是保證代碼具備隨時(shí)可以發(fā)布到線(xiàn)上的良好狀態(tài),維持團隊的持續交付能力。另外,平臺在效率提升方面也取得了顯著(zhù)效果:
5.2展望軟件度量是對軟件開(kāi)發(fā)項目、過(guò)程、及其產(chǎn)品進(jìn)行數據定義、收集以及分析的持續性量化過(guò)程。通過(guò)軟件度量可以改進(jìn)軟件開(kāi)發(fā)過(guò)程,促進(jìn)項目成功,開(kāi)發(fā)高質(zhì)量的軟件產(chǎn)品。平臺將繼續對整個(gè)產(chǎn)品交付過(guò)程中的指標數據進(jìn)行整理、挖掘,發(fā)現過(guò)程中存在的問(wèn)題和短板,優(yōu)化和反哺產(chǎn)品交付流程,在效率和穩定性等方面獲得更大的突破。5.3附錄
平臺架構
核心流程
沒(méi)有數據治理思維,數字化轉型就是“白忙活”
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 93 次瀏覽 ? 2022-04-28 13:34
BUT,數據資產(chǎn)能怎么用?為什么無(wú)數據可用,或無(wú)可用數據?怎樣開(kāi)展數據治理?則是一頭霧水。這也導致很多企業(yè)的數字化轉型“白忙活一場(chǎng)”、“從頭再來(lái)”的重要原因。
《報告》依據數據治理及管理組織各層級所關(guān)注的側重點(diǎn),圖譜將工具劃分為三層——戰略層、管理層、操作層。
01/戰略層工具為提供數據質(zhì)量戰略規劃、評估、知道、監控的工具或功能,主要包括五大過(guò)程域:組織與職責、體系與制度、團隊與文化、計劃與監控、成本與評估。1. 組織與職責對數據治理組織及其職責進(jìn)行規劃、管理。
2. 體系與制度對數據治理相關(guān)體系、制度、流程進(jìn)行管理、發(fā)布。
3. 團隊與文化提供數據治理文化發(fā)布、查詢(xún)、學(xué)習培訓等。
4. 計劃與監控
提供數據治理項目管理及監控。
5.成效與評估
對治理成效提供評估依據及評估行為。
02/
管理層工具
為應落實(shí)數據治理戰略而進(jìn)行的數據管理活動(dòng)的工具或功能。主要包括八大過(guò)程域:
數據架構管理、元數據管理、數據標準管理、主數據管理、數據質(zhì)量管理、數據資產(chǎn)管理、數據安全管理、數據生存周期管理。
1.數據架構管理提供數據架構規劃、設計相關(guān)工具及功能,包括數據層次、數據模型和數據流向設計。
2.元數據管理提供統一的企業(yè)元數據存儲庫,支持相關(guān)血緣、影響分析及變更管理的監控。
3.數據標準管理提供統一的指標數據技術(shù)標準、 業(yè)務(wù)標準、管理標準的視圖,具備基本的增刪改查及廢止功能,可進(jìn)行標準符合性檢測。
4.主數據管理提供對企業(yè)主數據、參考數據統一管理, 支持主數據模型定義、數據約束及分發(fā)策略的管理。
5.數據質(zhì)量管理支持對數據質(zhì)量建立質(zhì)量規則,支持數據治理評估,并生成質(zhì)量報告,提供質(zhì)量整改機制。
6.數據資產(chǎn)管理提供企業(yè)以資產(chǎn)價(jià)值視角的數據管理功能,包括資產(chǎn)索引、資產(chǎn)開(kāi)發(fā)、資產(chǎn)服務(wù)等功能。
7.數據安全管理支持對數據進(jìn)行安全分級分類(lèi),定期監督和執行數據安全策略執行情況。
8.數據生存周期管理對數據進(jìn)行生存周期管理,定期監督和檢查數據歸檔和銷(xiāo)毀策略執行情況。
03/
操作層工具
數據操作層主要包括六大過(guò)程域:數據存儲工具、數據采集工具、數據處理工具、數據共享交換工具、AI計算支撐工具、數據分析應用工具。
1.數據存儲工具
基于數據治理戰略及數據架構、數據標準、元數據、質(zhì)量等管理要求,對數據進(jìn)行存儲。包括分布式存儲、傳統關(guān)系型存儲、文件存儲及圖數據庫存儲。
2.數據采集工具基于數據治理戰略要求,完成相關(guān)數據采集工作。支持不同采集方式及頻率,包括實(shí)時(shí)采集、離線(xiàn)采集、報表填報采集、API采集等。
3.數據處理工具基于數據質(zhì)量、標準、數據架構等要求,對數據進(jìn)行加工、轉換、清洗、集中等工作。
4.數據共享交換工具
基于業(yè)務(wù)與之間的數據共享需求,對不同異構數據執行交換或服務(wù)。包括文件、庫表、接口、實(shí)時(shí)流等。
5.Al計算支撐工具將人工智能技術(shù)運用到數據采集、處理、共享、評估、度量等活動(dòng)中。
6.數據分析應用工具通過(guò)數據可視化、報表等工具完成數據治理的報告、診斷分析、監控圖表等的開(kāi)發(fā)制作。
《數據治理工具圖譜研究報告》對上述工具能力圖譜進(jìn)行了詳細解釋?zhuān)皥D外,報告對每層工具能力要素進(jìn)行了更細一步的繪制,并收錄了部分行業(yè)案例采用的工具架構圖。
報告共研制、收錄了26個(gè)圖譜,其中研制了20個(gè)通用工具能力圖譜,收錄了6個(gè)數據治理案例工具能力圖譜。 查看全部
當前這個(gè)時(shí)代,人人都知道數據,或多或少也知道數據是資產(chǎn),治理好了很有用,畢竟企業(yè)數字化轉型的始終離不開(kāi)“數據”,始于數據,最終也是為了數據。
BUT,數據資產(chǎn)能怎么用?為什么無(wú)數據可用,或無(wú)可用數據?怎樣開(kāi)展數據治理?則是一頭霧水。這也導致很多企業(yè)的數字化轉型“白忙活一場(chǎng)”、“從頭再來(lái)”的重要原因。
《報告》依據數據治理及管理組織各層級所關(guān)注的側重點(diǎn),圖譜將工具劃分為三層——戰略層、管理層、操作層。
01/戰略層工具為提供數據質(zhì)量戰略規劃、評估、知道、監控的工具或功能,主要包括五大過(guò)程域:組織與職責、體系與制度、團隊與文化、計劃與監控、成本與評估。1. 組織與職責對數據治理組織及其職責進(jìn)行規劃、管理。
2. 體系與制度對數據治理相關(guān)體系、制度、流程進(jìn)行管理、發(fā)布。
3. 團隊與文化提供數據治理文化發(fā)布、查詢(xún)、學(xué)習培訓等。
4. 計劃與監控
提供數據治理項目管理及監控。
5.成效與評估
對治理成效提供評估依據及評估行為。
02/
管理層工具
為應落實(shí)數據治理戰略而進(jìn)行的數據管理活動(dòng)的工具或功能。主要包括八大過(guò)程域:
數據架構管理、元數據管理、數據標準管理、主數據管理、數據質(zhì)量管理、數據資產(chǎn)管理、數據安全管理、數據生存周期管理。
1.數據架構管理提供數據架構規劃、設計相關(guān)工具及功能,包括數據層次、數據模型和數據流向設計。
2.元數據管理提供統一的企業(yè)元數據存儲庫,支持相關(guān)血緣、影響分析及變更管理的監控。
3.數據標準管理提供統一的指標數據技術(shù)標準、 業(yè)務(wù)標準、管理標準的視圖,具備基本的增刪改查及廢止功能,可進(jìn)行標準符合性檢測。
4.主數據管理提供對企業(yè)主數據、參考數據統一管理, 支持主數據模型定義、數據約束及分發(fā)策略的管理。
5.數據質(zhì)量管理支持對數據質(zhì)量建立質(zhì)量規則,支持數據治理評估,并生成質(zhì)量報告,提供質(zhì)量整改機制。
6.數據資產(chǎn)管理提供企業(yè)以資產(chǎn)價(jià)值視角的數據管理功能,包括資產(chǎn)索引、資產(chǎn)開(kāi)發(fā)、資產(chǎn)服務(wù)等功能。
7.數據安全管理支持對數據進(jìn)行安全分級分類(lèi),定期監督和執行數據安全策略執行情況。
8.數據生存周期管理對數據進(jìn)行生存周期管理,定期監督和檢查數據歸檔和銷(xiāo)毀策略執行情況。
03/
操作層工具
數據操作層主要包括六大過(guò)程域:數據存儲工具、數據采集工具、數據處理工具、數據共享交換工具、AI計算支撐工具、數據分析應用工具。
1.數據存儲工具
基于數據治理戰略及數據架構、數據標準、元數據、質(zhì)量等管理要求,對數據進(jìn)行存儲。包括分布式存儲、傳統關(guān)系型存儲、文件存儲及圖數據庫存儲。
2.數據采集工具基于數據治理戰略要求,完成相關(guān)數據采集工作。支持不同采集方式及頻率,包括實(shí)時(shí)采集、離線(xiàn)采集、報表填報采集、API采集等。
3.數據處理工具基于數據質(zhì)量、標準、數據架構等要求,對數據進(jìn)行加工、轉換、清洗、集中等工作。
4.數據共享交換工具
基于業(yè)務(wù)與之間的數據共享需求,對不同異構數據執行交換或服務(wù)。包括文件、庫表、接口、實(shí)時(shí)流等。
5.Al計算支撐工具將人工智能技術(shù)運用到數據采集、處理、共享、評估、度量等活動(dòng)中。
6.數據分析應用工具通過(guò)數據可視化、報表等工具完成數據治理的報告、診斷分析、監控圖表等的開(kāi)發(fā)制作。
《數據治理工具圖譜研究報告》對上述工具能力圖譜進(jìn)行了詳細解釋?zhuān)皥D外,報告對每層工具能力要素進(jìn)行了更細一步的繪制,并收錄了部分行業(yè)案例采用的工具架構圖。
報告共研制、收錄了26個(gè)圖譜,其中研制了20個(gè)通用工具能力圖譜,收錄了6個(gè)數據治理案例工具能力圖譜。
文章采集api(優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口及解決方案 )
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 201 次瀏覽 ? 2022-04-19 09:28
)
優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口處理采集的數據標題和內容、關(guān)鍵詞、描述等??梢葬槍π缘呐浜蟽?yōu)采云采集的SEO功能和5118智能換詞API,處理原創(chuàng )度數更高的文章。@收錄 和 網(wǎng)站 權重起著(zhù)非常重要的作用。
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺;
詳細使用步驟優(yōu)采云API接口配置創(chuàng )建API處理規則API處理規則使用API??處理結果并發(fā)布優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方案
1. 優(yōu)采云API接口配置
一、API配置入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==點(diǎn)擊【第三方內容API接入】==點(diǎn)擊【第三方API配置管理】==最后點(diǎn)擊【+< @優(yōu)采云API] 創(chuàng )建接口配置;
二、配置API接口信息:
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺。
【API key】是從優(yōu)采云(Puppy AI)后臺獲取對應的API key,填寫(xiě)后記得保存;
2. 創(chuàng )建 API 處理規則
API處理規則,可以通過(guò)調用API接口設置處理哪些字段的內容;
一、API處理規則入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==,點(diǎn)擊【第三方內容API接入】==進(jìn)入【API處理規則管理】頁(yè)面,最后點(diǎn)擊【+添加API處理規則]創(chuàng )建API處理規則;
二、API處理規則配置:
3. API 處理規則使用
API處理規則有兩種使用方式:手動(dòng)執行和自動(dòng)執行:
一、手動(dòng)執行API處理規則:
在采集任務(wù)的【結果數據&發(fā)布】選項卡中,點(diǎn)擊【SEO&API&翻譯等工具】按鈕==>選擇【第三方API執行】欄==>選擇對應的API處理規則= => 執行;
二、自動(dòng)執行API處理規則:
啟用 API 處理的自動(dòng)執行。任務(wù)完成后采集會(huì )自動(dòng)執行API處理。一般配合定時(shí)采集和自動(dòng)發(fā)布功能使用非常方便;
在任務(wù)的【自動(dòng)化:發(fā)布&SEO&翻譯】選項卡【自動(dòng)執行第三方API配置】==勾選【采集,自動(dòng)執行API】選項==選擇要執行的API處理規則= ="選擇API接口處理的數據范圍(一般選擇'待發(fā)布',都將導致所有數據重復執行),最后點(diǎn)擊保存;
4. API 處理結果并發(fā)布
一、查看API接口處理結果:
API接口處理的內容會(huì )保存為一個(gè)新的字段,如:標題處理后的新字段:title_優(yōu)采云,內容處理后的新字段:content_優(yōu)采云,在[Result Data & Publish ]和數據預覽界面可以查看。
二、發(fā)布API接口處理后的內容:
發(fā)布文章前,修改發(fā)布目標的第二步映射字段,重新選擇標題和內容到API接口處理后添加的對應字段title_優(yōu)采云和content_優(yōu)采云;
提示:如果發(fā)布目標中無(wú)法選擇新字段,請在任務(wù)下復制或新建發(fā)布目標,然后在新發(fā)布目標中選擇新字段即可。詳細教程請參考發(fā)布目標中不能選擇的字段;
5. 優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方法
一、API處理規則和SEO規則如何協(xié)同工作?
系統默認對title和content字段進(jìn)行SEO功能,需要修改為SEO規則中的title_優(yōu)采云和content_優(yōu)采云字段;
查看全部
文章采集api(優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口及解決方案
)
優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口處理采集的數據標題和內容、關(guān)鍵詞、描述等??梢葬槍π缘呐浜蟽?yōu)采云采集的SEO功能和5118智能換詞API,處理原創(chuàng )度數更高的文章。@收錄 和 網(wǎng)站 權重起著(zhù)非常重要的作用。
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺;
詳細使用步驟優(yōu)采云API接口配置創(chuàng )建API處理規則API處理規則使用API??處理結果并發(fā)布優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方案
1. 優(yōu)采云API接口配置
一、API配置入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==點(diǎn)擊【第三方內容API接入】==點(diǎn)擊【第三方API配置管理】==最后點(diǎn)擊【+< @優(yōu)采云API] 創(chuàng )建接口配置;

二、配置API接口信息:
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺。
【API key】是從優(yōu)采云(Puppy AI)后臺獲取對應的API key,填寫(xiě)后記得保存;


2. 創(chuàng )建 API 處理規則
API處理規則,可以通過(guò)調用API接口設置處理哪些字段的內容;
一、API處理規則入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==,點(diǎn)擊【第三方內容API接入】==進(jìn)入【API處理規則管理】頁(yè)面,最后點(diǎn)擊【+添加API處理規則]創(chuàng )建API處理規則;
二、API處理規則配置:

3. API 處理規則使用
API處理規則有兩種使用方式:手動(dòng)執行和自動(dòng)執行:
一、手動(dòng)執行API處理規則:
在采集任務(wù)的【結果數據&發(fā)布】選項卡中,點(diǎn)擊【SEO&API&翻譯等工具】按鈕==>選擇【第三方API執行】欄==>選擇對應的API處理規則= => 執行;

二、自動(dòng)執行API處理規則:
啟用 API 處理的自動(dòng)執行。任務(wù)完成后采集會(huì )自動(dòng)執行API處理。一般配合定時(shí)采集和自動(dòng)發(fā)布功能使用非常方便;
在任務(wù)的【自動(dòng)化:發(fā)布&SEO&翻譯】選項卡【自動(dòng)執行第三方API配置】==勾選【采集,自動(dòng)執行API】選項==選擇要執行的API處理規則= ="選擇API接口處理的數據范圍(一般選擇'待發(fā)布',都將導致所有數據重復執行),最后點(diǎn)擊保存;

4. API 處理結果并發(fā)布
一、查看API接口處理結果:
API接口處理的內容會(huì )保存為一個(gè)新的字段,如:標題處理后的新字段:title_優(yōu)采云,內容處理后的新字段:content_優(yōu)采云,在[Result Data & Publish ]和數據預覽界面可以查看。


二、發(fā)布API接口處理后的內容:
發(fā)布文章前,修改發(fā)布目標的第二步映射字段,重新選擇標題和內容到API接口處理后添加的對應字段title_優(yōu)采云和content_優(yōu)采云;
提示:如果發(fā)布目標中無(wú)法選擇新字段,請在任務(wù)下復制或新建發(fā)布目標,然后在新發(fā)布目標中選擇新字段即可。詳細教程請參考發(fā)布目標中不能選擇的字段;

5. 優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方法
一、API處理規則和SEO規則如何協(xié)同工作?
系統默認對title和content字段進(jìn)行SEO功能,需要修改為SEO規則中的title_優(yōu)采云和content_優(yōu)采云字段;
文章采集api(就是錯誤博客(圖片或視頻亦包括在內)分享)
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 108 次瀏覽 ? 2022-04-19 07:01
此外,偽原創(chuàng )大部分都被同義詞和同義詞所取代?;旧?,市場(chǎng)上沒(méi)有 AI偽原創(chuàng )。如果確實(shí)存在,那么直接給關(guān)鍵詞,剩下的可以自己寫(xiě)。市面上大部分的偽原創(chuàng )提供者都替換了同義詞和同義詞,所以最好不要這樣做。
3、構建文章
使用大量的詞搭建文章,比如10萬(wàn)個(gè)相關(guān)詞做一個(gè)表格文章頁(yè)面,通過(guò)對詞和句子的布局,看起來(lái)沒(méi)有不協(xié)調的感覺(jué)。另請參閱此方法。很多網(wǎng)站都獲得了很大的流量,而bug博客本身也獲得了數萬(wàn)這樣的收錄流量。
二、優(yōu)采云構建文章
優(yōu)采云構建文章 很簡(jiǎn)單,bug 博客為您提供了一切。
1、優(yōu)采云導入模板
下載優(yōu)采云,即優(yōu)采云采集,創(chuàng )建人員列表組,右鍵組,導入準備好的“.ljobx”文件,這是 優(yōu)采云@ 的模板>采集。
2、內容采集規則
導入后,雙擊打開(kāi),直接跳過(guò)“URL采集規則”,直接進(jìn)入“內容采集規則”,那么,我們需要構建標題、頁(yè)面對于原創(chuàng ) 關(guān)鍵詞,頁(yè)面描述、作者、縮略圖、標簽等,都來(lái)自txt文檔,內存中有幾萬(wàn)行數據,所以構建< @原創(chuàng )文章 。當然,這只是一種模式。如果你想有更好的收錄效果,那么你需要考慮如何使用這種模式來(lái)創(chuàng )造更好的內容,或者改變模式來(lái)產(chǎn)生更像原創(chuàng )的內容。
以上是Error Blog()分享的內容為“優(yōu)采云采集三種構建方式原創(chuàng )文章”。謝謝閱讀。更多原創(chuàng )文章搜索“bug blog”。
特別聲明:以上內容(包括圖片或視頻)由自媒體平臺“網(wǎng)易”用戶(hù)上傳發(fā)布。本平臺僅提供信息存儲服務(wù)。 查看全部
文章采集api(就是錯誤博客(圖片或視頻亦包括在內)分享)
此外,偽原創(chuàng )大部分都被同義詞和同義詞所取代?;旧?,市場(chǎng)上沒(méi)有 AI偽原創(chuàng )。如果確實(shí)存在,那么直接給關(guān)鍵詞,剩下的可以自己寫(xiě)。市面上大部分的偽原創(chuàng )提供者都替換了同義詞和同義詞,所以最好不要這樣做。
3、構建文章
使用大量的詞搭建文章,比如10萬(wàn)個(gè)相關(guān)詞做一個(gè)表格文章頁(yè)面,通過(guò)對詞和句子的布局,看起來(lái)沒(méi)有不協(xié)調的感覺(jué)。另請參閱此方法。很多網(wǎng)站都獲得了很大的流量,而bug博客本身也獲得了數萬(wàn)這樣的收錄流量。
二、優(yōu)采云構建文章
優(yōu)采云構建文章 很簡(jiǎn)單,bug 博客為您提供了一切。
1、優(yōu)采云導入模板
下載優(yōu)采云,即優(yōu)采云采集,創(chuàng )建人員列表組,右鍵組,導入準備好的“.ljobx”文件,這是 優(yōu)采云@ 的模板>采集。
2、內容采集規則
導入后,雙擊打開(kāi),直接跳過(guò)“URL采集規則”,直接進(jìn)入“內容采集規則”,那么,我們需要構建標題、頁(yè)面對于原創(chuàng ) 關(guān)鍵詞,頁(yè)面描述、作者、縮略圖、標簽等,都來(lái)自txt文檔,內存中有幾萬(wàn)行數據,所以構建< @原創(chuàng )文章 。當然,這只是一種模式。如果你想有更好的收錄效果,那么你需要考慮如何使用這種模式來(lái)創(chuàng )造更好的內容,或者改變模式來(lái)產(chǎn)生更像原創(chuàng )的內容。
以上是Error Blog()分享的內容為“優(yōu)采云采集三種構建方式原創(chuàng )文章”。謝謝閱讀。更多原創(chuàng )文章搜索“bug blog”。
特別聲明:以上內容(包括圖片或視頻)由自媒體平臺“網(wǎng)易”用戶(hù)上傳發(fā)布。本平臺僅提供信息存儲服務(wù)。
文章采集api( 京東云API分組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲 )
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 136 次瀏覽 ? 2022-04-19 00:42
京東云API分組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲
)
日志服務(wù)
目前,您可以在京東云的API群組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲、日志檢索、智能分析等功能,通過(guò)日志解決業(yè)務(wù)運營(yíng)、業(yè)務(wù)監控、日志分析等問(wèn)題。
入口一:
互聯(lián)網(wǎng)中間件 > API網(wǎng)關(guān) > 開(kāi)放API > API組管理 > 日志服務(wù)
入口二:
管理 > 日志服務(wù)
操作步驟: 第一步:進(jìn)入API組管理頁(yè)面,點(diǎn)擊“Log”按鈕
第二步:在日志集管理模塊中,點(diǎn)擊“創(chuàng )建日志集”按鈕,打開(kāi)創(chuàng )建日志集頁(yè)面。
步驟 3:設置日志集名稱(chēng)、描述(可選)和保存時(shí)間。點(diǎn)擊“確定”按鈕后,彈出提示“日志集創(chuàng )建成功,現在去添加日志主題嗎?”
第四步:點(diǎn)擊“確定”按鈕后,跳轉到日志集詳情,創(chuàng )建日志主題。
第五步:添加日志主題名稱(chēng)后,點(diǎn)擊“確定”按鈕,彈出提示“日志主題創(chuàng )建成功,現在去添加采集配置嗎?”
第六步:點(diǎn)擊“確定”后,進(jìn)入采集配置頁(yè)面。點(diǎn)擊“添加采集配置”進(jìn)入添加采集配置頁(yè)面,在“產(chǎn)品”對應選項中選擇“API網(wǎng)關(guān)”,點(diǎn)擊“確定”按鈕完成配置。第七步:返回日志集管理中的日志主題列表頁(yè)面,點(diǎn)擊日志集ID/名稱(chēng),點(diǎn)擊“預覽”按鈕可以查看日志主題下的最新日志數據。如果需要查詢(xún)日志數據,可以到日志檢索查詢(xún)。
第八步:在日志主題列表中選擇要查看的日志主題,點(diǎn)擊“搜索”按鈕,或者切換到左側菜單的日志搜索模塊,可以進(jìn)行相應的全文搜索或鍵值搜索在日志上:
全文搜索
鍵值檢索
(1)快速搜索
(2)高級搜索
查看全部
文章采集api(
京東云API分組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲
)
日志服務(wù)
目前,您可以在京東云的API群組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲、日志檢索、智能分析等功能,通過(guò)日志解決業(yè)務(wù)運營(yíng)、業(yè)務(wù)監控、日志分析等問(wèn)題。
入口一:
互聯(lián)網(wǎng)中間件 > API網(wǎng)關(guān) > 開(kāi)放API > API組管理 > 日志服務(wù)
入口二:
管理 > 日志服務(wù)
操作步驟: 第一步:進(jìn)入API組管理頁(yè)面,點(diǎn)擊“Log”按鈕

第二步:在日志集管理模塊中,點(diǎn)擊“創(chuàng )建日志集”按鈕,打開(kāi)創(chuàng )建日志集頁(yè)面。

步驟 3:設置日志集名稱(chēng)、描述(可選)和保存時(shí)間。點(diǎn)擊“確定”按鈕后,彈出提示“日志集創(chuàng )建成功,現在去添加日志主題嗎?”


第四步:點(diǎn)擊“確定”按鈕后,跳轉到日志集詳情,創(chuàng )建日志主題。


第五步:添加日志主題名稱(chēng)后,點(diǎn)擊“確定”按鈕,彈出提示“日志主題創(chuàng )建成功,現在去添加采集配置嗎?”

第六步:點(diǎn)擊“確定”后,進(jìn)入采集配置頁(yè)面。點(diǎn)擊“添加采集配置”進(jìn)入添加采集配置頁(yè)面,在“產(chǎn)品”對應選項中選擇“API網(wǎng)關(guān)”,點(diǎn)擊“確定”按鈕完成配置。第七步:返回日志集管理中的日志主題列表頁(yè)面,點(diǎn)擊日志集ID/名稱(chēng),點(diǎn)擊“預覽”按鈕可以查看日志主題下的最新日志數據。如果需要查詢(xún)日志數據,可以到日志檢索查詢(xún)。

第八步:在日志主題列表中選擇要查看的日志主題,點(diǎn)擊“搜索”按鈕,或者切換到左側菜單的日志搜索模塊,可以進(jìn)行相應的全文搜索或鍵值搜索在日志上:
全文搜索

鍵值檢索
(1)快速搜索

(2)高級搜索
文章采集api(搭建一套前端監控平臺需要考慮的幾個(gè)問(wèn)題?|本文)
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 95 次瀏覽 ? 2022-04-18 20:32
隨著(zhù)業(yè)務(wù)的快速發(fā)展,我們越來(lái)越重視對生產(chǎn)環(huán)境問(wèn)題的感知能力。作為離用戶(hù)最近的一層,前端性能是否可靠、穩定、好用在很大程度上決定了用戶(hù)對整個(gè)產(chǎn)品的體驗和感受。因此,前端的監控也不容忽視。
搭建前端監控平臺需要考慮很多方面,比如數據采集、埋藏模式、數據處理分析、告警、監控平臺在具體業(yè)務(wù)中的應用等等。在所有這些環(huán)節中、準確、完整、全面的數據采集是一切的前提,也為用戶(hù)后續的精細化運營(yíng)提供了依據。
前端技術(shù)的飛速發(fā)展給數據帶來(lái)了變化和挑戰采集,傳統的人工管理模式已經(jīng)不能滿(mǎn)足需求。如何讓前端數據采集在新的技術(shù)背景下工作更加完整高效是本文的重點(diǎn)。
前端監控數據采集
在采集數據之前,考慮一下采集什么樣的數據。我們關(guān)注兩類(lèi)數據,一類(lèi)與用戶(hù)體驗相關(guān),如首屏時(shí)間、文件加載時(shí)間、頁(yè)面性能等;另一個(gè)是幫助我們及時(shí)感知產(chǎn)品上線(xiàn)后是否出現異常,比如資源錯誤、API響應時(shí)間等。具體來(lái)說(shuō),我們的前端數據采集主要分為:
路由交換機
Vue、React、Angular等前端技術(shù)的快速發(fā)展,使得單頁(yè)應用流行起來(lái)。我們都知道,傳統的頁(yè)面應用使用一些超鏈接來(lái)實(shí)現頁(yè)面切換和跳轉,而單頁(yè)面應用使用自己的路由系統來(lái)管理各個(gè)前端頁(yè)面切換,比如vue-router、react-router等,只有跳轉時(shí)刷新本地資源,js、css等公共資源只需加載一次,使得傳統的網(wǎng)頁(yè)進(jìn)出方式只有在第一次打開(kāi)時(shí)才會(huì )被記錄。在單頁(yè)應用中切換所有后續路由有兩種方式,一種是Hash,另一種是HTML5推出的History API。
1. 鏈接
href是頁(yè)面初始化的第一個(gè)入口,這里只需要簡(jiǎn)單的報告“進(jìn)入頁(yè)面”事件。
2. 哈希變化
哈希路由的一個(gè)明顯標志是帶有“#”。Hash的優(yōu)點(diǎn)是兼容性更好,但問(wèn)題是URL中的“#”不美觀(guān)。我們主要通過(guò)監聽(tīng) URL 中的 hashchange 來(lái)捕獲具體的 hash 值進(jìn)行檢測。
window.addEventListener('hashchange', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
需要注意的是,如果瀏覽器在新版本的vue-router中支持history,即使模式選擇hash,也會(huì )先選擇history模式。雖然表達式暫時(shí)還是#,但實(shí)際上是模擬出來(lái)的,所以不要以為你在如果模式選擇hash,那肯定是hash。
3. 歷史 API
History利用HTML5 History接口中新增的pushState()和replaceState()方法進(jìn)行路由切換,是目前主流的非刷新切換路由方式。與 hashchange 只能更改 # 后面的代碼片段相比,History API(pushState、replaceState)給了前端完全的自由。
PopState 是瀏覽器返回事件的回調,但是更新路由的 pushState 和 replaceState 沒(méi)有回調事件。因此,URL 更改需要分別在 history.pushState() 和 history.replaceState() 方法中處理。在這里,我們使用類(lèi)似Java的AOP編程思想來(lái)改造pushState和replaceState。
AOP(Aspect-oriented programming)是面向方面的編程,它提倡對同一類(lèi)型的問(wèn)題進(jìn)行統一處理。AOP的核心思想是讓某個(gè)模塊能夠被復用。它采用橫向抽取機制,將功能代碼與業(yè)務(wù)邏輯代碼分離,在不修改源代碼的情況下擴展功能。與封裝相比,隔離更徹底。
下面介紹我們具體的改造方法:
// 第一階段:我們對原生方法進(jìn)行包裝,調用前執行 dispatchEvent 了一個(gè)同樣的事件
function aop (type) {
var source = window.history[type];
return function () {
var event = new Event(type);
event.arguments = arguments;
window.dispatchEvent(event);
var rewrite = source.apply(this, arguments);
return rewrite;
};
}
// 第二階段:將 pushState 和 replaceState 進(jìn)行基于 AOP 思想的代碼注入
window.history.pushState = aop('pushState');
window.history.replaceState = aop('replaceState'); // 更改路由,不會(huì )留下歷史記錄
// 第三階段:捕獲pushState 和 replaceState
window.addEventListener('pushState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.addEventListener('replaceState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.history.pushState的實(shí)際調用關(guān)系如圖:
至此,我們完成了pushState和replaceState的轉換,實(shí)現了路由切換的有效抓包??梢钥闯?,我們在不侵入業(yè)務(wù)代碼的情況下擴展了window.history.pushState,調用時(shí)會(huì )主動(dòng)dispatchEvent一個(gè)pushState。
但是這里我們也可以看到一個(gè)缺點(diǎn),就是如果AOP代理函數出現JS錯誤,會(huì )阻塞后續的調用關(guān)系,從而無(wú)法調用實(shí)際的window.history.pushState。因此,在使用該方法時(shí),需要對AOP代理功能的內容進(jìn)行一次完整的try catch,以防止出現業(yè)務(wù)異常。
*提示:如果要自動(dòng)捕捉頁(yè)面停留時(shí)間,只需在觸發(fā)下一頁(yè)進(jìn)入事件時(shí),將上一頁(yè)的時(shí)間與當前時(shí)間做個(gè)差值即可。這時(shí)候可以上報【離開(kāi)頁(yè)面】事件。
錯誤
在前端項目中,由于 JavaScript 本身是一種弱類(lèi)型語(yǔ)言,再加上瀏覽器環(huán)境的復雜性、網(wǎng)絡(luò )問(wèn)題等,很容易出現錯誤。因此,做好網(wǎng)頁(yè)錯誤監控,不斷優(yōu)化代碼,提高代碼的健壯性是非常重要的。
JsError的捕獲可以幫助我們分析和監控在線(xiàn)問(wèn)題,和我們在Chrome瀏覽器的調試工具Console中看到的一致。
1. 窗口.onerror
我們通常使用 window.onerror 來(lái)捕獲 JS 錯誤的異常信息。有兩種方法可以捕獲 JS 錯誤,window.onerror 和 window.addEventListener('error')。一般不建議使用 addEventListener('error') 來(lái)捕獲 JS 異常,主要是它沒(méi)有堆棧信息,而且還需要區分捕獲的信息,因為它會(huì )捕獲所有的異常信息,包括資源加載錯誤. 等待。
window.onerror = function (msg, url, lineno, colno, stack) {
// 上報 【js錯誤】事件
}
2. 未被抓?。ǔ兄Z)
當 Promise 發(fā)生 JS 錯誤或者業(yè)務(wù)沒(méi)有處理拒絕信息時(shí),會(huì )拋出 unhandledrejection,并且這個(gè)錯誤不會(huì )被 window.onerror 和 window.addEventListener('error') 這個(gè)特殊的窗口捕獲。addEventListener('unhandledrejection') 用于捕獲處理:
window.addEventListener('unhandledrejection', function (e) {
var reg_url = /\(([^)]*)\)/;
var fileMsg = e.reason.stack.split('\n')[1].match(reg_url)[1];
var fileArr = fileMsg.split(':');
var lineno = fileArr[fileArr.length - 2];
var colno = fileArr[fileArr.length - 1];
var url = fileMsg.slice(0, -lno.length - cno.length - 2);}, true);
var msg = e.reason.message;
// 上報 【js錯誤】事件
}
我們注意到unhandledrejection繼承自PromiseRejectionEvent,而PromiseRejectionEvent繼承自Event,所以msg、url、lineno、colno、stack以字符串的形式放在e.reason.stack中,我們需要將上面的參數解析出來(lái)與onerror參數對齊,為后續監測平臺各項指標的統一奠定了基礎。
3. 常見(jiàn)問(wèn)題
如果抓到的msg都是“Script error.”,問(wèn)題是你的JS地址和當前網(wǎng)頁(yè)不在同一個(gè)域下。因為我們經(jīng)常需要對網(wǎng)絡(luò )版的靜態(tài)資源進(jìn)行CDN,會(huì )導致經(jīng)常訪(fǎng)問(wèn)的頁(yè)面和腳本文件來(lái)自不同的域名。這時(shí)候如果不進(jìn)行額外配置,瀏覽器很容易出現“腳本錯誤”。出于安全考慮。我們可以利用當前流行的 Webpack bundler 來(lái)處理此類(lèi)問(wèn)題。
// webpack config 配置
// 處理 html 注入 js 添加跨域標識
plugins: [
new HtmlWebpackPlugin({
filename: 'html/index.html',
template: HTML_PATH,
attributes: {
crossorigin: 'anonymous'
}
}),
new HtmlWebpackPluginCrossorigin({
inject: true
})
]
// 處理按需加載的 js 添加跨域標識
output: {
crossOriginLoading: true
}
大多數場(chǎng)景下,生產(chǎn)環(huán)境中的代碼都是壓縮合并的,這使得我們抓到的錯誤很難映射到具體的源碼中,給我們解決問(wèn)題帶來(lái)了很大的麻煩。這里有兩個(gè)解決方案。想法。
在生產(chǎn)環(huán)境中,我們需要添加sourceMap的配置,這樣會(huì )帶來(lái)安全隱患,因為這樣外網(wǎng)可以通過(guò)sourceMap進(jìn)行source map的映射。為了降低風(fēng)險,我們可以做到以下幾點(diǎn):
此時(shí),我們已經(jīng)有了 .map 文件。接下來(lái)我們需要做的就是通過(guò)捕獲的lineno、colno、url調用mozilla/source-map庫進(jìn)行源碼映射,然后就可以得到真正的源碼錯誤信息了。
表現
性能指標的獲取比較簡(jiǎn)單,在onload之后讀取window.performance就可以了,里面收錄了性能、內存等信息。這部分內容在很多現有的文章中都有介紹。由于篇幅所限,本文不再過(guò)多展開(kāi)。稍后,我們將在相關(guān)主題文章中進(jìn)行相關(guān)討論。感興趣的朋友可以添加“馬蜂窩技術(shù)”公眾號繼續關(guān)注。
資源錯誤
首先,我們需要明確資源錯誤捕獲的使用場(chǎng)景,更多的是感知DNS劫持和CDN節點(diǎn)異常等,具體方法如下:
window.addEventListener('error', function (e) {
var target = e.target || e.srcElement;
if (target instanceof HTMLScriptElement) {
// 上報 【資源錯誤】事件
}
}, true)
這只是一個(gè)基本的演示。在實(shí)際環(huán)境中,我們會(huì )關(guān)心更多的Element錯誤,比如css、img、woff等,大家可以根據不同的場(chǎng)景添加。
*資源錯誤的使用場(chǎng)景更多地依賴(lài)于其他維度,例如:地區、運營(yíng)商等,我們將在后面的頁(yè)面中詳細解釋。
API
在市面上的主流框架(如axios、jQuery.ajax等)中,基本上所有的API請求都是基于xmlHttpRequest或者fetch,所以捕獲全局接口錯誤的方式就是封裝xmlHttpRequest或者fetch。在這里,我們的SDK還是使用了上面提到的AOP思想來(lái)攔截API。 查看全部
文章采集api(搭建一套前端監控平臺需要考慮的幾個(gè)問(wèn)題?|本文)
隨著(zhù)業(yè)務(wù)的快速發(fā)展,我們越來(lái)越重視對生產(chǎn)環(huán)境問(wèn)題的感知能力。作為離用戶(hù)最近的一層,前端性能是否可靠、穩定、好用在很大程度上決定了用戶(hù)對整個(gè)產(chǎn)品的體驗和感受。因此,前端的監控也不容忽視。
搭建前端監控平臺需要考慮很多方面,比如數據采集、埋藏模式、數據處理分析、告警、監控平臺在具體業(yè)務(wù)中的應用等等。在所有這些環(huán)節中、準確、完整、全面的數據采集是一切的前提,也為用戶(hù)后續的精細化運營(yíng)提供了依據。
前端技術(shù)的飛速發(fā)展給數據帶來(lái)了變化和挑戰采集,傳統的人工管理模式已經(jīng)不能滿(mǎn)足需求。如何讓前端數據采集在新的技術(shù)背景下工作更加完整高效是本文的重點(diǎn)。
前端監控數據采集
在采集數據之前,考慮一下采集什么樣的數據。我們關(guān)注兩類(lèi)數據,一類(lèi)與用戶(hù)體驗相關(guān),如首屏時(shí)間、文件加載時(shí)間、頁(yè)面性能等;另一個(gè)是幫助我們及時(shí)感知產(chǎn)品上線(xiàn)后是否出現異常,比如資源錯誤、API響應時(shí)間等。具體來(lái)說(shuō),我們的前端數據采集主要分為:
路由交換機
Vue、React、Angular等前端技術(shù)的快速發(fā)展,使得單頁(yè)應用流行起來(lái)。我們都知道,傳統的頁(yè)面應用使用一些超鏈接來(lái)實(shí)現頁(yè)面切換和跳轉,而單頁(yè)面應用使用自己的路由系統來(lái)管理各個(gè)前端頁(yè)面切換,比如vue-router、react-router等,只有跳轉時(shí)刷新本地資源,js、css等公共資源只需加載一次,使得傳統的網(wǎng)頁(yè)進(jìn)出方式只有在第一次打開(kāi)時(shí)才會(huì )被記錄。在單頁(yè)應用中切換所有后續路由有兩種方式,一種是Hash,另一種是HTML5推出的History API。
1. 鏈接
href是頁(yè)面初始化的第一個(gè)入口,這里只需要簡(jiǎn)單的報告“進(jìn)入頁(yè)面”事件。
2. 哈希變化
哈希路由的一個(gè)明顯標志是帶有“#”。Hash的優(yōu)點(diǎn)是兼容性更好,但問(wèn)題是URL中的“#”不美觀(guān)。我們主要通過(guò)監聽(tīng) URL 中的 hashchange 來(lái)捕獲具體的 hash 值進(jìn)行檢測。
window.addEventListener('hashchange', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
需要注意的是,如果瀏覽器在新版本的vue-router中支持history,即使模式選擇hash,也會(huì )先選擇history模式。雖然表達式暫時(shí)還是#,但實(shí)際上是模擬出來(lái)的,所以不要以為你在如果模式選擇hash,那肯定是hash。
3. 歷史 API
History利用HTML5 History接口中新增的pushState()和replaceState()方法進(jìn)行路由切換,是目前主流的非刷新切換路由方式。與 hashchange 只能更改 # 后面的代碼片段相比,History API(pushState、replaceState)給了前端完全的自由。
PopState 是瀏覽器返回事件的回調,但是更新路由的 pushState 和 replaceState 沒(méi)有回調事件。因此,URL 更改需要分別在 history.pushState() 和 history.replaceState() 方法中處理。在這里,我們使用類(lèi)似Java的AOP編程思想來(lái)改造pushState和replaceState。
AOP(Aspect-oriented programming)是面向方面的編程,它提倡對同一類(lèi)型的問(wèn)題進(jìn)行統一處理。AOP的核心思想是讓某個(gè)模塊能夠被復用。它采用橫向抽取機制,將功能代碼與業(yè)務(wù)邏輯代碼分離,在不修改源代碼的情況下擴展功能。與封裝相比,隔離更徹底。
下面介紹我們具體的改造方法:
// 第一階段:我們對原生方法進(jìn)行包裝,調用前執行 dispatchEvent 了一個(gè)同樣的事件
function aop (type) {
var source = window.history[type];
return function () {
var event = new Event(type);
event.arguments = arguments;
window.dispatchEvent(event);
var rewrite = source.apply(this, arguments);
return rewrite;
};
}
// 第二階段:將 pushState 和 replaceState 進(jìn)行基于 AOP 思想的代碼注入
window.history.pushState = aop('pushState');
window.history.replaceState = aop('replaceState'); // 更改路由,不會(huì )留下歷史記錄
// 第三階段:捕獲pushState 和 replaceState
window.addEventListener('pushState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.addEventListener('replaceState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.history.pushState的實(shí)際調用關(guān)系如圖:
至此,我們完成了pushState和replaceState的轉換,實(shí)現了路由切換的有效抓包??梢钥闯?,我們在不侵入業(yè)務(wù)代碼的情況下擴展了window.history.pushState,調用時(shí)會(huì )主動(dòng)dispatchEvent一個(gè)pushState。
但是這里我們也可以看到一個(gè)缺點(diǎn),就是如果AOP代理函數出現JS錯誤,會(huì )阻塞后續的調用關(guān)系,從而無(wú)法調用實(shí)際的window.history.pushState。因此,在使用該方法時(shí),需要對AOP代理功能的內容進(jìn)行一次完整的try catch,以防止出現業(yè)務(wù)異常。
*提示:如果要自動(dòng)捕捉頁(yè)面停留時(shí)間,只需在觸發(fā)下一頁(yè)進(jìn)入事件時(shí),將上一頁(yè)的時(shí)間與當前時(shí)間做個(gè)差值即可。這時(shí)候可以上報【離開(kāi)頁(yè)面】事件。
錯誤
在前端項目中,由于 JavaScript 本身是一種弱類(lèi)型語(yǔ)言,再加上瀏覽器環(huán)境的復雜性、網(wǎng)絡(luò )問(wèn)題等,很容易出現錯誤。因此,做好網(wǎng)頁(yè)錯誤監控,不斷優(yōu)化代碼,提高代碼的健壯性是非常重要的。
JsError的捕獲可以幫助我們分析和監控在線(xiàn)問(wèn)題,和我們在Chrome瀏覽器的調試工具Console中看到的一致。
1. 窗口.onerror
我們通常使用 window.onerror 來(lái)捕獲 JS 錯誤的異常信息。有兩種方法可以捕獲 JS 錯誤,window.onerror 和 window.addEventListener('error')。一般不建議使用 addEventListener('error') 來(lái)捕獲 JS 異常,主要是它沒(méi)有堆棧信息,而且還需要區分捕獲的信息,因為它會(huì )捕獲所有的異常信息,包括資源加載錯誤. 等待。
window.onerror = function (msg, url, lineno, colno, stack) {
// 上報 【js錯誤】事件
}
2. 未被抓?。ǔ兄Z)
當 Promise 發(fā)生 JS 錯誤或者業(yè)務(wù)沒(méi)有處理拒絕信息時(shí),會(huì )拋出 unhandledrejection,并且這個(gè)錯誤不會(huì )被 window.onerror 和 window.addEventListener('error') 這個(gè)特殊的窗口捕獲。addEventListener('unhandledrejection') 用于捕獲處理:
window.addEventListener('unhandledrejection', function (e) {
var reg_url = /\(([^)]*)\)/;
var fileMsg = e.reason.stack.split('\n')[1].match(reg_url)[1];
var fileArr = fileMsg.split(':');
var lineno = fileArr[fileArr.length - 2];
var colno = fileArr[fileArr.length - 1];
var url = fileMsg.slice(0, -lno.length - cno.length - 2);}, true);
var msg = e.reason.message;
// 上報 【js錯誤】事件
}
我們注意到unhandledrejection繼承自PromiseRejectionEvent,而PromiseRejectionEvent繼承自Event,所以msg、url、lineno、colno、stack以字符串的形式放在e.reason.stack中,我們需要將上面的參數解析出來(lái)與onerror參數對齊,為后續監測平臺各項指標的統一奠定了基礎。
3. 常見(jiàn)問(wèn)題
如果抓到的msg都是“Script error.”,問(wèn)題是你的JS地址和當前網(wǎng)頁(yè)不在同一個(gè)域下。因為我們經(jīng)常需要對網(wǎng)絡(luò )版的靜態(tài)資源進(jìn)行CDN,會(huì )導致經(jīng)常訪(fǎng)問(wèn)的頁(yè)面和腳本文件來(lái)自不同的域名。這時(shí)候如果不進(jìn)行額外配置,瀏覽器很容易出現“腳本錯誤”。出于安全考慮。我們可以利用當前流行的 Webpack bundler 來(lái)處理此類(lèi)問(wèn)題。
// webpack config 配置
// 處理 html 注入 js 添加跨域標識
plugins: [
new HtmlWebpackPlugin({
filename: 'html/index.html',
template: HTML_PATH,
attributes: {
crossorigin: 'anonymous'
}
}),
new HtmlWebpackPluginCrossorigin({
inject: true
})
]
// 處理按需加載的 js 添加跨域標識
output: {
crossOriginLoading: true
}
大多數場(chǎng)景下,生產(chǎn)環(huán)境中的代碼都是壓縮合并的,這使得我們抓到的錯誤很難映射到具體的源碼中,給我們解決問(wèn)題帶來(lái)了很大的麻煩。這里有兩個(gè)解決方案。想法。
在生產(chǎn)環(huán)境中,我們需要添加sourceMap的配置,這樣會(huì )帶來(lái)安全隱患,因為這樣外網(wǎng)可以通過(guò)sourceMap進(jìn)行source map的映射。為了降低風(fēng)險,我們可以做到以下幾點(diǎn):
此時(shí),我們已經(jīng)有了 .map 文件。接下來(lái)我們需要做的就是通過(guò)捕獲的lineno、colno、url調用mozilla/source-map庫進(jìn)行源碼映射,然后就可以得到真正的源碼錯誤信息了。
表現
性能指標的獲取比較簡(jiǎn)單,在onload之后讀取window.performance就可以了,里面收錄了性能、內存等信息。這部分內容在很多現有的文章中都有介紹。由于篇幅所限,本文不再過(guò)多展開(kāi)。稍后,我們將在相關(guān)主題文章中進(jìn)行相關(guān)討論。感興趣的朋友可以添加“馬蜂窩技術(shù)”公眾號繼續關(guān)注。
資源錯誤
首先,我們需要明確資源錯誤捕獲的使用場(chǎng)景,更多的是感知DNS劫持和CDN節點(diǎn)異常等,具體方法如下:
window.addEventListener('error', function (e) {
var target = e.target || e.srcElement;
if (target instanceof HTMLScriptElement) {
// 上報 【資源錯誤】事件
}
}, true)
這只是一個(gè)基本的演示。在實(shí)際環(huán)境中,我們會(huì )關(guān)心更多的Element錯誤,比如css、img、woff等,大家可以根據不同的場(chǎng)景添加。
*資源錯誤的使用場(chǎng)景更多地依賴(lài)于其他維度,例如:地區、運營(yíng)商等,我們將在后面的頁(yè)面中詳細解釋。
API
在市面上的主流框架(如axios、jQuery.ajax等)中,基本上所有的API請求都是基于xmlHttpRequest或者fetch,所以捕獲全局接口錯誤的方式就是封裝xmlHttpRequest或者fetch。在這里,我們的SDK還是使用了上面提到的AOP思想來(lái)攔截API。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 162 次瀏覽 ? 2022-05-14 20:49
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 91 次瀏覽 ? 2022-05-13 16:48
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 130 次瀏覽 ? 2022-05-09 10:00
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
干掉 Swagger + Postman?測試接口直接生成API文檔
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 81 次瀏覽 ? 2022-05-09 04:25
?、?點(diǎn)擊右上角的【+】按鈕,我們來(lái)新建一個(gè)頁(yè)面,編寫(xiě)一個(gè)用戶(hù)注冊的 API 接口文檔。
新建頁(yè)面
?、?點(diǎn)擊【API 接口模板】按鈕,ShowDoc 會(huì )幫我們生成 API 接口文檔的示例,采用的是 Markdown 的格式。
API 接口模板
?、?簡(jiǎn)單修改 Markdown 的內容,然后點(diǎn)擊右上角的【保存】按鈕,生成文檔。
保存接口
?、?點(diǎn)擊右上角的【返回】按鈕,可以看到剛創(chuàng )建的 API 接口文檔。
接口預覽
在右邊,艿艿圈了【分享】【目錄】【歷史版本】三個(gè)按鈕,胖友可以自己去體驗下。
ShowDoc 提供 API 接口的 Mock 功能,方便后端在定義 API 接口后,提供模擬數據。
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的右邊的【編輯頁(yè)面】按鈕,然后點(diǎn)擊【Mock】按鈕,我們可以看到一個(gè) Mock 的彈窗。
Mock 彈窗
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
友情提示:ShowDoc 提供的 Mock 能力還是比較基礎的,實(shí)際項目中,我們可能希望根據不同的請求參數,返回不同的 Mock 結果。
如果胖友有這塊需求,可以看看 YApi: 。
通過(guò)手寫(xiě) Markdown 的方式,生成 API 文檔的方式,是非常非常非常繁瑣 的?。?!所以,ShowDoc 自己也不推薦采用這種方式,而是主推 RunApi 工具,一邊調試接口,一邊自動(dòng)生成 。
咱先看看 RunApi 的自我介紹,也是賊長(cháng)一大串:
RunApi 是一個(gè)以接口為核心的開(kāi)發(fā)測試工具(功能上類(lèi)似 Postman)。
目前有客戶(hù)端版(推薦,支持 Win/Mac/Linux全平臺)和在線(xiàn)精簡(jiǎn)版 ,包含接口測試 / 自動(dòng)流程測試 / Mock 數據 / 項目協(xié)作等功能。
它和 ShowDoc 相輔相成:
相信使用 ShowDoc + RunApi 這兩個(gè)工具組合,能夠極大地提高IT團隊的效率。
管你看沒(méi)看懂,跟著(zhù)艿艿一起,體驗一下就完事了!
?、?在 地址下,提供了不同操作系統的 RunApi 客戶(hù)端的下載。
客戶(hù)端
?、?下載并安裝完成后,使用 ShowDoc 注冊的賬號,進(jìn)行登陸。
Runapi 登陸
雖然我們在 ShowDoc 中,已經(jīng)新建了項目,但是我們在 RunApi 中是無(wú)法看到的。因此,我們需要重新新建屬于 RunApi 的項目。
項目對比
?、?點(diǎn)擊 RunApi 客戶(hù)端的【新建項目】按鈕,填寫(xiě)項目名和描述,然后點(diǎn)擊【確認】按鈕進(jìn)行保存。
新建項目
?、?瀏覽器刷新 ShowDoc 頁(yè)面,可以看到剛創(chuàng )建的項目。
查看項目
?、?點(diǎn)擊【+】按鈕,選擇要新增的類(lèi)型為“帶調試功能的API接口”。
新建 API 接口
?、?啟動(dòng)一個(gè) Spring Boot 項目,提供一個(gè)需要調試的 API 接口。
友情提示:胖友可以克隆 項目,使用 lab-24/lab-24-apidoc-showdoc 示例。
嘿嘿,順手求個(gè) Star 關(guān)注,艿艿寫(xiě)了 40000+ Spring Boot 和 Spring Cloud 的使用示例代碼。
啟動(dòng) Spring Boot 項目
?、?使用 RunApi 調試下 /users/login 接口。
調試 API 接口
?、?點(diǎn)擊【返回示例和參數說(shuō)明】,補全返回結果的接口文檔。
補全響應結果
?、?點(diǎn)擊【保存】按鈕,生成 API 接口文檔。
?、?點(diǎn)擊【文檔鏈接】按鈕,獲得 API 接口文檔的地址。
文檔鏈接
?、?點(diǎn)擊 API 文檔的訪(fǎng)問(wèn)鏈接,查看 API 文檔。
RunAPI 文檔預覽
當然,我們也可以在 ShowDoc 中,進(jìn)行訪(fǎng)問(wèn)。
ShowDoc 文檔預覽
有一點(diǎn)要注意,使用 RunApi 生成的 API 接口文檔,無(wú)法在使用 Markdown 進(jìn)行編輯噢!原因也很簡(jiǎn)單,編寫(xiě)后的 Markdown 文件,可能會(huì )導致無(wú)法逆向被 RunApi 使用,格式被破壞了!
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的下邊的【Mock】按鈕,我們可以看到一個(gè) Mock 的界面。
Mock 界面
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
RunApi 還提供了 3 個(gè)高級特性,胖友后面可以自己體驗下。
強烈推薦 ?。?!
環(huán)境變量
例如說(shuō),設置“本地環(huán)境”、“測試環(huán)境”等多套環(huán)境變量,方便模擬請求不通過(guò)環(huán)境下的 API 噢。
前執行腳本
例如說(shuō),可以模擬登陸,獲得用戶(hù)的訪(fǎng)問(wèn) token 令牌。
后執行腳本
例如說(shuō),斷言響應的結果,是否為期望的 200 。
RunApi 提供的自動(dòng) 生成 API 接口文檔的方式,確實(shí)能夠避免一部分煩瑣 的手寫(xiě) Markdown 的過(guò)程。同時(shí),它能夠結合我們日常開(kāi)發(fā),模擬調用 API 接口的時(shí),復用了請求參數與響應結果。
但是我們如果仔細去思考,這是不是意味著(zhù)可能此時(shí)此刻,我們已經(jīng)開(kāi)發(fā)完 API 接口了?!那么,假如團隊采用的是前后端分離的架構,并且前端和后端是兩撥人,那么前端會(huì )希望后端提前就定義好 API 接口的文檔,而不是在后端具體完成好 API 接口的開(kāi)發(fā)后,再提供接口文檔。
所以我們在使用 RunApi 的時(shí)候,有可能是先使用它來(lái)**“手動(dòng)”** 定義好 API 接口文檔,然后復用它來(lái)模擬測試 API 接口。
嘿嘿~胖友也可以思考下,結合 RunApi 的這種模式,怎么結合到我們的日常開(kāi)發(fā)流程中,歡迎留言討論。
ShowDoc 支持通過(guò)掃描代碼注釋的方式,自動(dòng)生成 API 接口文檔,目前自持 Java、C++、PHP、Node 等等主流的編程語(yǔ)言。
艿艿看了下官方文檔 對這塊功能的介紹,感受上使用體驗會(huì )非常不好。一起來(lái)看下官方提供的示例:
????/**<br />????*?showdoc<br />????*?@catalog?測試文檔/用戶(hù)相關(guān)<br />????*?@title?用戶(hù)登錄<br />????*?@description?用戶(hù)登錄的接口<br />????*?@method?get<br />????*?@url?https://www.showdoc.cc/home/user/login<br />????*?@header?token?可選?string?設備token?<br />????*?@param?username?必選?string?用戶(hù)名?<br />????*?@param?password?必選?string?密碼??<br />????*?@param?name?可選?string?用戶(hù)昵稱(chēng)??<br />????*?@return?{"error_code":0,"data":{"uid":"1","username":"12154545","name":"吳系掛","groupid":2,"reg_time":"1436864169","last_login_time":"0"}}<br />????*?@return_param?groupid?int?用戶(hù)組id<br />????*?@return_param?name?string?用戶(hù)昵稱(chēng)<br />????*?@remark?這里是備注信息<br />????*?@number?99<br />????*/<br />????public?Object?login(String?username,?String?password,?String?name)?{<br />????????//?...?省略具體代碼<br />????}<br />
需要使用到 @catalog、@title 等等自定義的注釋標簽,且原有的 @param 需要安裝一定的格式來(lái)保證 API 接口的參數的說(shuō)明,@return 的示例會(huì )導致注釋非常長(cháng)。
自定義注釋
這樣就導致,雖然只使用代碼注釋的方式,實(shí)際對代碼還是有一定的入侵,影響代碼的可讀性。
還是老樣子,我們使用 項目,lab-24/lab-24-apidoc-showdoc 示例,編寫(xiě)一個(gè) users/login2 接口,并使用 ShowDoc 掃碼 Java代碼注釋?zhuān)?API 接口文檔。
?、?下載 腳本,到項目的根目錄。
下載 showdoc_api 腳本
?、?在項目的設置頁(yè),獲得 ShowDoc 的開(kāi)放 API 的 api_key 和 api_token 秘鑰對。
進(jìn)入項目的設置頁(yè)獲得 api_key 和 api_token 秘鑰對
?、?修改 showdoc_api.sh 腳本,設置剛獲得的 api_key 和 api_token 秘鑰對。
設置 api_key 和 api_token 秘鑰對
?、?編寫(xiě) users/login2 接口,添加 ShowDoc 所需的注釋。
編寫(xiě) users/login2 接口
是不是看著(zhù)就蠻亂的,IDEA 還報錯 @param 找不到 username 和 password 參數。
?、?執行 showdoc_api.sh 腳本,掃描 Java代碼注釋?zhuān)?API 接口文檔。
生成 API 接口文檔
?、?查看生成 API 接口文檔。
查看 API 接口文檔
如果胖友希望基于 Java 注釋生成 API 接口文檔,艿艿還是相對 JApiDocs 工具。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 JApiDocs 入門(mén)》 文章。
JApiDocs 效果
ShowDoc 提供給了開(kāi)放 API 的方式,導入 Markdown 文檔。所以,我們可以編寫(xiě)程序,調用它的 API 接口,創(chuàng )建或更新 API 接口文檔。
開(kāi)放 API 的官方文檔文檔地址是, 。
接口地址 :
接口參數 :
接口參數
我們來(lái)導入一個(gè)簡(jiǎn)單的文檔,效果如下圖所示:
{<br />??"api_key":?"60fc53cea6af4758c1686cb22ba20566472255580",<br />??"api_token":?"0bbb5f564a9ee66333115b1abb8f8d541979489118",<br />??"page_title":?"公眾號",<br />??"page_content":?"芋道源碼,求一波關(guān)注呀~"<br />}<br />
友情提示:api_key 和 api_token 參數,記得改成自己的秘鑰對,不然就導入到艿艿的項目里啦~~~
調用開(kāi)放 API文檔效果
在新建項目時(shí),ShowDoc 支持導入 Swagger 或者 Postman 的 JSON 文檔,方便我們快速遷移到 ShowDoc 作為 API 接口的平臺。
我們來(lái)體驗下 ShowDoc 提供的導入 Swagger 文檔的功能,使用 項目,lab-24/lab-24-apidoc-swagger-starter 示例,提供的 Swagger JSON 文件。
?、?啟動(dòng) Spring Boot 項目,獲得其 Swagger JSON 文件。
下載 Swagger JSON 文件
友情提示:胖友也可以訪(fǎng)問(wèn) 地址,直接進(jìn)行下載!
?、?新建 ShowDoc 項目,點(diǎn)擊【導入文件】,選擇 Swagger JSON 文件。
導入 Swagger JSON 文件
?、?導入完成后,點(diǎn)擊自動(dòng)新建的項目,查看下導入的 API 文檔的效果。
導入 Swagger JSON 文件
接口都成功導入了,可惜 Swagger 中的 example 都缺失了,這就導致我們需要手動(dòng)補全下接口的示例。
ShowDoc 目前只支持新建項目時(shí),導入 Swagger 接口文檔。但是如果 Swagger 接口文檔變更時(shí),無(wú)法進(jìn)行更新 ShowDoc 中的文檔。
如果我們僅僅是把 Swagger 遷移到 ShowDoc 中,肯定是基本能夠滿(mǎn)足。但是,如果我們希望使用 Swagger 編寫(xiě)接口文檔,手動(dòng)或者自動(dòng)導入 ShowDoc 進(jìn)行展示,這樣就無(wú)法滿(mǎn)足了。
這里艿艿推薦下 YApi 工具,支持定時(shí)采集 Swagger 接口,智能 合并 API 接口文檔。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 YApi 入門(mén)》 文章。
YApi + Swagger
在上家公司,艿艿就采用 Swagger + YApi 的組合,Swagger 方便后端編寫(xiě) API 接口文檔,YApi 提供接口的展示 、編輯 、Mock 、調試 、自動(dòng)化測試 。
ShowDoc 支持通過(guò)掃描數據庫,自動(dòng)生成表結構的數據庫文檔。
對應的官方文檔地址是, 。
下面, 我們來(lái)把艿艿的一個(gè)開(kāi)源項目 的數據庫,導入 ShowDoc 生成數據庫文檔。
?、?下載 腳本,并設置數據庫相關(guān)的參數。
下載 show_db 腳本
?、?執行 show_db 腳本,看到“成功”說(shuō)明成功。查看數據庫文檔的效果,效果還是還不錯。
查看數據庫文檔
國內還有一款不錯的數據庫文檔的生成工具 Screw,具體可以看看艿艿寫(xiě)的《芋道 Spring Boot 數據表結構文檔》,地址是 。
演示效果
至此,我們已經(jīng)完成 ShowDoc 的入門(mén),還是蠻不錯的一個(gè)工具。做個(gè)簡(jiǎn)單的小總結:
Talk is Cheap,胖友可以選擇動(dòng)手玩玩 ShowDoc 工具。
- END -
歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長(cháng)按下方二維碼噢:
已在知識星球更新源碼解析如下:
最近更新《芋道 SpringBoot 2.X 入門(mén)》系列,已經(jīng) 101 余篇,覆蓋了MyBatis、Redis、MongoDB、ES、分庫分表、讀寫(xiě)分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。
提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務(wù)項目。 查看全部
干掉 Swagger + Postman?測試接口直接生成API文檔
?、?點(diǎn)擊右上角的【+】按鈕,我們來(lái)新建一個(gè)頁(yè)面,編寫(xiě)一個(gè)用戶(hù)注冊的 API 接口文檔。
新建頁(yè)面
?、?點(diǎn)擊【API 接口模板】按鈕,ShowDoc 會(huì )幫我們生成 API 接口文檔的示例,采用的是 Markdown 的格式。
API 接口模板
?、?簡(jiǎn)單修改 Markdown 的內容,然后點(diǎn)擊右上角的【保存】按鈕,生成文檔。
保存接口
?、?點(diǎn)擊右上角的【返回】按鈕,可以看到剛創(chuàng )建的 API 接口文檔。
接口預覽
在右邊,艿艿圈了【分享】【目錄】【歷史版本】三個(gè)按鈕,胖友可以自己去體驗下。
ShowDoc 提供 API 接口的 Mock 功能,方便后端在定義 API 接口后,提供模擬數據。
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的右邊的【編輯頁(yè)面】按鈕,然后點(diǎn)擊【Mock】按鈕,我們可以看到一個(gè) Mock 的彈窗。
Mock 彈窗
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
友情提示:ShowDoc 提供的 Mock 能力還是比較基礎的,實(shí)際項目中,我們可能希望根據不同的請求參數,返回不同的 Mock 結果。
如果胖友有這塊需求,可以看看 YApi: 。
通過(guò)手寫(xiě) Markdown 的方式,生成 API 文檔的方式,是非常非常非常繁瑣 的?。?!所以,ShowDoc 自己也不推薦采用這種方式,而是主推 RunApi 工具,一邊調試接口,一邊自動(dòng)生成 。
咱先看看 RunApi 的自我介紹,也是賊長(cháng)一大串:
RunApi 是一個(gè)以接口為核心的開(kāi)發(fā)測試工具(功能上類(lèi)似 Postman)。
目前有客戶(hù)端版(推薦,支持 Win/Mac/Linux全平臺)和在線(xiàn)精簡(jiǎn)版 ,包含接口測試 / 自動(dòng)流程測試 / Mock 數據 / 項目協(xié)作等功能。
它和 ShowDoc 相輔相成:
相信使用 ShowDoc + RunApi 這兩個(gè)工具組合,能夠極大地提高IT團隊的效率。
管你看沒(méi)看懂,跟著(zhù)艿艿一起,體驗一下就完事了!
?、?在 地址下,提供了不同操作系統的 RunApi 客戶(hù)端的下載。
客戶(hù)端
?、?下載并安裝完成后,使用 ShowDoc 注冊的賬號,進(jìn)行登陸。
Runapi 登陸
雖然我們在 ShowDoc 中,已經(jīng)新建了項目,但是我們在 RunApi 中是無(wú)法看到的。因此,我們需要重新新建屬于 RunApi 的項目。
項目對比
?、?點(diǎn)擊 RunApi 客戶(hù)端的【新建項目】按鈕,填寫(xiě)項目名和描述,然后點(diǎn)擊【確認】按鈕進(jìn)行保存。
新建項目
?、?瀏覽器刷新 ShowDoc 頁(yè)面,可以看到剛創(chuàng )建的項目。
查看項目
?、?點(diǎn)擊【+】按鈕,選擇要新增的類(lèi)型為“帶調試功能的API接口”。
新建 API 接口
?、?啟動(dòng)一個(gè) Spring Boot 項目,提供一個(gè)需要調試的 API 接口。
友情提示:胖友可以克隆 項目,使用 lab-24/lab-24-apidoc-showdoc 示例。
嘿嘿,順手求個(gè) Star 關(guān)注,艿艿寫(xiě)了 40000+ Spring Boot 和 Spring Cloud 的使用示例代碼。
啟動(dòng) Spring Boot 項目
?、?使用 RunApi 調試下 /users/login 接口。
調試 API 接口
?、?點(diǎn)擊【返回示例和參數說(shuō)明】,補全返回結果的接口文檔。
補全響應結果
?、?點(diǎn)擊【保存】按鈕,生成 API 接口文檔。
?、?點(diǎn)擊【文檔鏈接】按鈕,獲得 API 接口文檔的地址。
文檔鏈接
?、?點(diǎn)擊 API 文檔的訪(fǎng)問(wèn)鏈接,查看 API 文檔。
RunAPI 文檔預覽
當然,我們也可以在 ShowDoc 中,進(jìn)行訪(fǎng)問(wèn)。
ShowDoc 文檔預覽
有一點(diǎn)要注意,使用 RunApi 生成的 API 接口文檔,無(wú)法在使用 Markdown 進(jìn)行編輯噢!原因也很簡(jiǎn)單,編寫(xiě)后的 Markdown 文件,可能會(huì )導致無(wú)法逆向被 RunApi 使用,格式被破壞了!
?、?點(diǎn)擊需要 Mock 的 API 接口文檔的下邊的【Mock】按鈕,我們可以看到一個(gè) Mock 的界面。
Mock 界面
?、?填寫(xiě) Mock 的返回結果,設置 Mock Url 的路徑,然后點(diǎn)擊【保存】按鈕。
設置 Mock
?、?點(diǎn)擊【復制】按鈕,復制 Mock Url 的路徑,然后使用瀏覽器訪(fǎng)問(wèn),可以看到 Mock 的返回結果。
請求 Mock 接口
RunApi 還提供了 3 個(gè)高級特性,胖友后面可以自己體驗下。
強烈推薦 ?。?!
環(huán)境變量
例如說(shuō),設置“本地環(huán)境”、“測試環(huán)境”等多套環(huán)境變量,方便模擬請求不通過(guò)環(huán)境下的 API 噢。
前執行腳本
例如說(shuō),可以模擬登陸,獲得用戶(hù)的訪(fǎng)問(wèn) token 令牌。
后執行腳本
例如說(shuō),斷言響應的結果,是否為期望的 200 。
RunApi 提供的自動(dòng) 生成 API 接口文檔的方式,確實(shí)能夠避免一部分煩瑣 的手寫(xiě) Markdown 的過(guò)程。同時(shí),它能夠結合我們日常開(kāi)發(fā),模擬調用 API 接口的時(shí),復用了請求參數與響應結果。
但是我們如果仔細去思考,這是不是意味著(zhù)可能此時(shí)此刻,我們已經(jīng)開(kāi)發(fā)完 API 接口了?!那么,假如團隊采用的是前后端分離的架構,并且前端和后端是兩撥人,那么前端會(huì )希望后端提前就定義好 API 接口的文檔,而不是在后端具體完成好 API 接口的開(kāi)發(fā)后,再提供接口文檔。
所以我們在使用 RunApi 的時(shí)候,有可能是先使用它來(lái)**“手動(dòng)”** 定義好 API 接口文檔,然后復用它來(lái)模擬測試 API 接口。
嘿嘿~胖友也可以思考下,結合 RunApi 的這種模式,怎么結合到我們的日常開(kāi)發(fā)流程中,歡迎留言討論。
ShowDoc 支持通過(guò)掃描代碼注釋的方式,自動(dòng)生成 API 接口文檔,目前自持 Java、C++、PHP、Node 等等主流的編程語(yǔ)言。
艿艿看了下官方文檔 對這塊功能的介紹,感受上使用體驗會(huì )非常不好。一起來(lái)看下官方提供的示例:
????/**<br />????*?showdoc<br />????*?@catalog?測試文檔/用戶(hù)相關(guān)<br />????*?@title?用戶(hù)登錄<br />????*?@description?用戶(hù)登錄的接口<br />????*?@method?get<br />????*?@url?https://www.showdoc.cc/home/user/login<br />????*?@header?token?可選?string?設備token?<br />????*?@param?username?必選?string?用戶(hù)名?<br />????*?@param?password?必選?string?密碼??<br />????*?@param?name?可選?string?用戶(hù)昵稱(chēng)??<br />????*?@return?{"error_code":0,"data":{"uid":"1","username":"12154545","name":"吳系掛","groupid":2,"reg_time":"1436864169","last_login_time":"0"}}<br />????*?@return_param?groupid?int?用戶(hù)組id<br />????*?@return_param?name?string?用戶(hù)昵稱(chēng)<br />????*?@remark?這里是備注信息<br />????*?@number?99<br />????*/<br />????public?Object?login(String?username,?String?password,?String?name)?{<br />????????//?...?省略具體代碼<br />????}<br />
需要使用到 @catalog、@title 等等自定義的注釋標簽,且原有的 @param 需要安裝一定的格式來(lái)保證 API 接口的參數的說(shuō)明,@return 的示例會(huì )導致注釋非常長(cháng)。
自定義注釋
這樣就導致,雖然只使用代碼注釋的方式,實(shí)際對代碼還是有一定的入侵,影響代碼的可讀性。
還是老樣子,我們使用 項目,lab-24/lab-24-apidoc-showdoc 示例,編寫(xiě)一個(gè) users/login2 接口,并使用 ShowDoc 掃碼 Java代碼注釋?zhuān)?API 接口文檔。
?、?下載 腳本,到項目的根目錄。
下載 showdoc_api 腳本
?、?在項目的設置頁(yè),獲得 ShowDoc 的開(kāi)放 API 的 api_key 和 api_token 秘鑰對。
進(jìn)入項目的設置頁(yè)獲得 api_key 和 api_token 秘鑰對
?、?修改 showdoc_api.sh 腳本,設置剛獲得的 api_key 和 api_token 秘鑰對。
設置 api_key 和 api_token 秘鑰對
?、?編寫(xiě) users/login2 接口,添加 ShowDoc 所需的注釋。
編寫(xiě) users/login2 接口
是不是看著(zhù)就蠻亂的,IDEA 還報錯 @param 找不到 username 和 password 參數。
?、?執行 showdoc_api.sh 腳本,掃描 Java代碼注釋?zhuān)?API 接口文檔。
生成 API 接口文檔
?、?查看生成 API 接口文檔。
查看 API 接口文檔
如果胖友希望基于 Java 注釋生成 API 接口文檔,艿艿還是相對 JApiDocs 工具。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 JApiDocs 入門(mén)》 文章。
JApiDocs 效果
ShowDoc 提供給了開(kāi)放 API 的方式,導入 Markdown 文檔。所以,我們可以編寫(xiě)程序,調用它的 API 接口,創(chuàng )建或更新 API 接口文檔。
開(kāi)放 API 的官方文檔文檔地址是, 。
接口地址 :
接口參數 :
接口參數
我們來(lái)導入一個(gè)簡(jiǎn)單的文檔,效果如下圖所示:
{<br />??"api_key":?"60fc53cea6af4758c1686cb22ba20566472255580",<br />??"api_token":?"0bbb5f564a9ee66333115b1abb8f8d541979489118",<br />??"page_title":?"公眾號",<br />??"page_content":?"芋道源碼,求一波關(guān)注呀~"<br />}<br />
友情提示:api_key 和 api_token 參數,記得改成自己的秘鑰對,不然就導入到艿艿的項目里啦~~~
調用開(kāi)放 API文檔效果
在新建項目時(shí),ShowDoc 支持導入 Swagger 或者 Postman 的 JSON 文檔,方便我們快速遷移到 ShowDoc 作為 API 接口的平臺。
我們來(lái)體驗下 ShowDoc 提供的導入 Swagger 文檔的功能,使用 項目,lab-24/lab-24-apidoc-swagger-starter 示例,提供的 Swagger JSON 文件。
?、?啟動(dòng) Spring Boot 項目,獲得其 Swagger JSON 文件。
下載 Swagger JSON 文件
友情提示:胖友也可以訪(fǎng)問(wèn) 地址,直接進(jìn)行下載!
?、?新建 ShowDoc 項目,點(diǎn)擊【導入文件】,選擇 Swagger JSON 文件。
導入 Swagger JSON 文件
?、?導入完成后,點(diǎn)擊自動(dòng)新建的項目,查看下導入的 API 文檔的效果。
導入 Swagger JSON 文件
接口都成功導入了,可惜 Swagger 中的 example 都缺失了,這就導致我們需要手動(dòng)補全下接口的示例。
ShowDoc 目前只支持新建項目時(shí),導入 Swagger 接口文檔。但是如果 Swagger 接口文檔變更時(shí),無(wú)法進(jìn)行更新 ShowDoc 中的文檔。
如果我們僅僅是把 Swagger 遷移到 ShowDoc 中,肯定是基本能夠滿(mǎn)足。但是,如果我們希望使用 Swagger 編寫(xiě)接口文檔,手動(dòng)或者自動(dòng)導入 ShowDoc 進(jìn)行展示,這樣就無(wú)法滿(mǎn)足了。
這里艿艿推薦下 YApi 工具,支持定時(shí)采集 Swagger 接口,智能 合并 API 接口文檔。具體的,可以看看艿艿寫(xiě)的 《芋道 Spring Boot API 接口文檔 YApi 入門(mén)》 文章。
YApi + Swagger
在上家公司,艿艿就采用 Swagger + YApi 的組合,Swagger 方便后端編寫(xiě) API 接口文檔,YApi 提供接口的展示 、編輯 、Mock 、調試 、自動(dòng)化測試 。
ShowDoc 支持通過(guò)掃描數據庫,自動(dòng)生成表結構的數據庫文檔。
對應的官方文檔地址是, 。
下面, 我們來(lái)把艿艿的一個(gè)開(kāi)源項目 的數據庫,導入 ShowDoc 生成數據庫文檔。
?、?下載 腳本,并設置數據庫相關(guān)的參數。
下載 show_db 腳本
?、?執行 show_db 腳本,看到“成功”說(shuō)明成功。查看數據庫文檔的效果,效果還是還不錯。
查看數據庫文檔
國內還有一款不錯的數據庫文檔的生成工具 Screw,具體可以看看艿艿寫(xiě)的《芋道 Spring Boot 數據表結構文檔》,地址是 。
演示效果
至此,我們已經(jīng)完成 ShowDoc 的入門(mén),還是蠻不錯的一個(gè)工具。做個(gè)簡(jiǎn)單的小總結:
Talk is Cheap,胖友可以選擇動(dòng)手玩玩 ShowDoc 工具。
- END -
歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長(cháng)按下方二維碼噢:
已在知識星球更新源碼解析如下:
最近更新《芋道 SpringBoot 2.X 入門(mén)》系列,已經(jīng) 101 余篇,覆蓋了MyBatis、Redis、MongoDB、ES、分庫分表、讀寫(xiě)分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。
提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務(wù)項目。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 146 次瀏覽 ? 2022-05-09 04:23
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
如何使用新一代輕量級分布式日志管理神器 Graylog 來(lái)收集日志
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 97 次瀏覽 ? 2022-05-04 14:05
公眾號關(guān)注「奇妙的 Linux 世界」
設為「星標」,每天帶你玩轉 Linux !
當我們公司內部部署很多服務(wù)以及測試、正式環(huán)境的時(shí)候,查看日志就變成了一個(gè)非常剛需的需求了。是多個(gè)環(huán)境的日志統一收集,然后使用 Nginx 對外提供服務(wù),還是使用專(zhuān)用的日志收集服務(wù) ELK 呢?
這就變成了一個(gè)問(wèn)題!而 Graylog 作為整合方案,使用 Elasticsearch 來(lái)存儲,使用 MongoDB 來(lái)緩存,并且還有帶流量控制的(throttling),同時(shí)其界面查詢(xún)簡(jiǎn)單易用且易于擴展。所以,使用 Graylog 成為了不二之選,為我們省了不少心。
1Filebeat 工具介紹
Filebeat 日志文件托運服務(wù)
Filebeat 是一個(gè)日志文件托運工具,在你的服務(wù)器上安裝客戶(hù)端后,Filebeat 會(huì )自動(dòng)監控給定的日志目錄或者指定的日志文件,追蹤讀取這些文件,不停的讀取,并且轉發(fā)這些信息到 Elasticsearch 或者 Logstarsh 或者 Graylog 中存放。
Filebeat 工作流程介紹
當你安裝并啟用 Filebeat 程序的時(shí)候,它會(huì )啟動(dòng)一個(gè)或多個(gè)探測器(prospectors)去檢測你指定的日志目錄或文件,對于探測器找出的每一個(gè)日志文件,Filebeat 都會(huì )啟動(dòng)一個(gè)收割進(jìn)程(harvester),每一個(gè)收割進(jìn)程讀取一個(gè)日志文件的最新內容,并發(fā)送這些新的日志數據到處理程序(spooler),處理程序會(huì )集合這些事件,最后 Filebeat 會(huì )發(fā)送集合的數據到你指定的地址上去(我們這里就是發(fā)送給 Graylog 服務(wù)了)。
Filebeat 圖示理解記憶
我們這里不適用 Logstash 服務(wù),主要是因為 Filebeat 相比于 Logstash 更加輕量級。當我們需要收集信息的機器配置或資源并不是特別多時(shí),且并沒(méi)有那么復雜的時(shí)候,還是建議使用 Filebeat 來(lái)收集日志。日常使用中,Filebeat 的安裝部署方式多樣且運行十分穩定。
圖示服務(wù)架構理解記憶2Filebeat 配置文件
配置 Filebeat 工具的核心就是如何編寫(xiě)其對應的配置文件!
對應 Filebeat 工具的配置主要是通過(guò)編寫(xiě)其配置文件來(lái)控制的,對于通過(guò) rpm 或者 deb 包來(lái)安裝的情況,配置文件默認會(huì )存儲在,/etc/filebeat/filebeat.yml 這個(gè)路徑下面。而對于,對于 MAC 或者 Win 系統來(lái)說(shuō),請查看解壓文件中相關(guān)文件,其中都有涉及。
下面展示了 Filebeat 工具的主配置文件,注釋信息中都對其各個(gè)字段含義進(jìn)行了詳細的解釋?zhuān)疫@里就不再贅述了。需要注意的是,我們將日志的輸入來(lái)源統統定義去讀取 inputs.d 目錄下的所有 yml 配置。所以,我們可以更加不用的服務(wù)(測試、正式服務(wù))來(lái)定義不同的配置文件,根據物理機部署的實(shí)際情況具體配置。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br /><br />
下面展示一個(gè)簡(jiǎn)單的 inputs.d 目錄下面的 yml 配置文件的具體內容,其主要作用就是配置單獨服務(wù)的獨立日志數據,以及追加不同的數據 tag 類(lèi)型。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br />
需要注意的是,針對于不同的日志類(lèi)型,filebeat 還提供了不同了模塊來(lái)配置不同的服務(wù)日志以及其不同的模塊特性,比如我們常見(jiàn)的 PostgreSQl、Redis、Iptables 等。
#?iptables<br />-?module:?iptables<br />??log:<br />????enabled:?true<br />????var.paths:?["/var/log/iptables.log"]<br />????var.input:?"file"<br /><br />#?postgres<br />-?module:?postgresql<br />??log:<br />????enabled:?true<br />????var.paths:?["/path/to/log/postgres/*.log*"]<br /><br />#?nginx<br />-?module:?nginx<br />??access:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/access.log*"]<br />??error:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/error.log*"]<br />
3Graylog 服務(wù)介紹
服務(wù)日志收集方案:Filebeat + Graylog!
Graylog 日志監控系統
Graylog 是一個(gè)開(kāi)源的日志聚合、分析、審計、展現和預警工具。在功能上來(lái)說(shuō),和 ELK 類(lèi)似,但又比 ELK 要簡(jiǎn)單很多。依靠著(zhù)更加簡(jiǎn)潔,高效,部署使用簡(jiǎn)單的優(yōu)勢很快受到許多人的青睞。當然,在擴展性上面確實(shí)沒(méi)有比 ELK 好,但是其有商業(yè)版本可以選擇。
Graylog 工作流程介紹
部署 Graylog 最簡(jiǎn)單的架構就是單機部署,復雜的也是部署集群模式,架構圖示如下所示。我們可以看到其中包含了三個(gè)組件,分別是 Elasticsearch、MongoDb 和 Graylog。其中,Elasticsearch 用來(lái)持久化存儲和檢索日志文件數據(IO 密集),MongoDb 用來(lái)存儲關(guān)于 Graylog 的相關(guān)配置,而 Graylog 來(lái)提供 Web 界面和對外接口的(CPU 密集)。
最小化單機部署
最優(yōu)化集群部署4Graylog 組件功能
配置 Graylog 服務(wù)的核心就是理解對應組件的功能以及其運作方式!
簡(jiǎn)單來(lái)講,Input 表示日志數據的來(lái)源,對不同來(lái)源的日志可以通過(guò) Extractors 來(lái)進(jìn)行日志的字段轉換,比如將 Nginx 的狀態(tài)碼變成對應的英文表述等。然后,通過(guò)不同的標簽類(lèi)型分組成不用的 Stream,并將這些日志數據存儲到指定的 Index 庫中進(jìn)行持久化保存。
Graylog中的核心服務(wù)組件
Graylog 通過(guò) Input 搜集日志,每個(gè) Input 單獨配置 Extractors 用來(lái)做字段轉換。Graylog 中日志搜索的基本單位是 Stream,每個(gè) Stream 可以有自己?jiǎn)为毜?Elastic Index Set,也可以共享一個(gè) Index Set。
Extractor 在 System/Input 中配置。Graylog 中很方便的一點(diǎn)就是可以加載一條日志,然后基于這個(gè)實(shí)際的例子進(jìn)行配置并能直接看到結果。內置的 Extractor 基本可以完成各種字段提取和轉換的任務(wù),但是也有些限制,在應用里寫(xiě)日志的時(shí)候就需要考慮到這些限制。Input 可以配置多個(gè) Extractors,按照順序依次執行。
系統會(huì )有一個(gè)默認的 Stream,所有日志默認都會(huì )保存到這個(gè) Stream 中,除非匹配了某個(gè) Stream,并且這個(gè) Stream 里配置了不保存日志到默認 Stream??梢酝ㄟ^(guò)菜單 Streams 創(chuàng )建更多的 Stream,新創(chuàng )建的 Stream 是暫停狀態(tài),需要在配置完成后手動(dòng)啟動(dòng)。Stream 通過(guò)配置條件匹配日志,滿(mǎn)足條件的日志添加 stream ID 標識字段并保存到對應的 Elastic Index Set 中。
Index Set 通過(guò)菜單 System/Indices 創(chuàng )建。日志存儲的性能,可靠性和過(guò)期策略都通過(guò) Index Set 來(lái)配置。性能和可靠性就是配置 Elastic Index 的一些參數,主要參數包括,Shards 和 Replicas。
除了上面提到的日志處理流程,Graylog 還提供了 Pipeline 腳本實(shí)現更靈活的日志處理方案。這里不詳細闡述,只介紹如果使用 Pipelines 來(lái)過(guò)濾不需要的日志。下面是丟棄 level > 6 的所有日志的 Pipeline Rule 的例子。從數據采集(input),字段解析(extractor),分流到 stream,再到 Pipeline 的清洗,一氣呵成,無(wú)需在通過(guò)其他方式進(jìn)行二次加工。
Sidecar 是一個(gè)輕量級的日志采集器,通過(guò)訪(fǎng)問(wèn) Graylog 進(jìn)行集中式管理,支持 Linux 和 windows 系統。Sidecar 守護進(jìn)程會(huì )定期訪(fǎng)問(wèn) Graylog 的 REST API 接口獲取 Sidecar 配置文件中定義的標簽(tag),Sidecar 在首次運行時(shí)會(huì )從 Graylog 服務(wù)器拉取配置文件中指定標簽(tag)的配置信息同步到本地。目前 Sidecar 支持 NXLog,Filebeat 和 Winlogbeat。他們都通過(guò) Graylog 中的 web 界面進(jìn)行統一配置,支持 Beats、CEF、Gelf、Json API、NetFlow 等輸出類(lèi)型。Graylog 最厲害的在于可以在配置文件中指定 Sidecar 把日志發(fā)送到哪個(gè) Graylog 群集,并對 Graylog 群集中的多個(gè) input 進(jìn)行負載均衡,這樣在遇到日志量非常龐大的時(shí)候,Graylog 也能應付自如。
rule?"discard?debug?messages"<br />when<br />??to_long($message.level)?>?6<br />then<br />??drop_message();<br />end<br />
日志集中保存到 Graylog 后就可以方便的使用搜索了。不過(guò)有時(shí)候還是需要對數據進(jìn)行近一步的處理。主要有兩個(gè)途徑,分別是直接訪(fǎng)問(wèn) Elastic 中保存的數據,或者通過(guò) Graylog 的 Output 轉發(fā)到其它服務(wù)。
5服務(wù)安裝和部署
主要介紹部署 Filebeat + Graylog 的安裝步驟和注意事項!
使用 Graylog 來(lái)收集日志
部署 Filebeat 工具
官方提供了多種的部署方式,包括通過(guò) rpm 和 deb 包安裝服務(wù),以及源代碼編譯的方式安裝服務(wù),同時(shí)包括了使用 Docker 或者 kubernetes 的方式安裝服務(wù)。我們根據自己的實(shí)際需要,進(jìn)行安裝即可。
#?Ubuntu(deb)<br />$?curl?-L?-O?https://artifacts.elastic.co/d ... %3Bbr />$?sudo?dpkg?-i?filebeat-7.8.1-amd64.deb<br />$?sudo?systemctl?enable?filebeat<br />$?sudo?service?filebeat?start<br /><br />#?使用docker啟動(dòng)<br />docker?run?-d?--name=filebeat?--user=root?\<br />??--volume="./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro"?\<br />??--volume="/var/lib/docker/containers:/var/lib/docker/containers:ro"?\<br />??--volume="/var/run/docker.sock:/var/run/docker.sock:ro"?\<br />??docker.elastic.co/beats/filebeat:7.8.1?filebeat?-e?-strict.perms=false?\<br />??-E?output.elasticsearch.hosts=["elasticsearch:9200"]<br />
使用 Graylog 來(lái)收集日志
部署 Graylog 服務(wù)
我們這里主要介紹使用 Docker 容器來(lái)部署服務(wù),如果你需要使用其他方式來(lái)部署的話(huà),請自行查看官方文檔對應章節的安裝部署步驟。在服務(wù)部署之前,我們需要給 Graylog 服務(wù)生成等相關(guān)信息,生成部署如下所示:
<p>#?生成password_secret密碼(最少16位)<br />$?sudo?apt?install?-y?pwgen<br />$?pwgen?-N?1?-s?16<br />zscMb65...FxR9ag<br /><br />#?生成后續Web登錄時(shí)所需要使用的密碼<br />$?echo?-n?"Enter?Password:?"?&&?head?-1? 查看全部
如何使用新一代輕量級分布式日志管理神器 Graylog 來(lái)收集日志
公眾號關(guān)注「奇妙的 Linux 世界」
設為「星標」,每天帶你玩轉 Linux !
當我們公司內部部署很多服務(wù)以及測試、正式環(huán)境的時(shí)候,查看日志就變成了一個(gè)非常剛需的需求了。是多個(gè)環(huán)境的日志統一收集,然后使用 Nginx 對外提供服務(wù),還是使用專(zhuān)用的日志收集服務(wù) ELK 呢?
這就變成了一個(gè)問(wèn)題!而 Graylog 作為整合方案,使用 Elasticsearch 來(lái)存儲,使用 MongoDB 來(lái)緩存,并且還有帶流量控制的(throttling),同時(shí)其界面查詢(xún)簡(jiǎn)單易用且易于擴展。所以,使用 Graylog 成為了不二之選,為我們省了不少心。
1Filebeat 工具介紹
Filebeat 日志文件托運服務(wù)
Filebeat 是一個(gè)日志文件托運工具,在你的服務(wù)器上安裝客戶(hù)端后,Filebeat 會(huì )自動(dòng)監控給定的日志目錄或者指定的日志文件,追蹤讀取這些文件,不停的讀取,并且轉發(fā)這些信息到 Elasticsearch 或者 Logstarsh 或者 Graylog 中存放。
Filebeat 工作流程介紹
當你安裝并啟用 Filebeat 程序的時(shí)候,它會(huì )啟動(dòng)一個(gè)或多個(gè)探測器(prospectors)去檢測你指定的日志目錄或文件,對于探測器找出的每一個(gè)日志文件,Filebeat 都會(huì )啟動(dòng)一個(gè)收割進(jìn)程(harvester),每一個(gè)收割進(jìn)程讀取一個(gè)日志文件的最新內容,并發(fā)送這些新的日志數據到處理程序(spooler),處理程序會(huì )集合這些事件,最后 Filebeat 會(huì )發(fā)送集合的數據到你指定的地址上去(我們這里就是發(fā)送給 Graylog 服務(wù)了)。
Filebeat 圖示理解記憶
我們這里不適用 Logstash 服務(wù),主要是因為 Filebeat 相比于 Logstash 更加輕量級。當我們需要收集信息的機器配置或資源并不是特別多時(shí),且并沒(méi)有那么復雜的時(shí)候,還是建議使用 Filebeat 來(lái)收集日志。日常使用中,Filebeat 的安裝部署方式多樣且運行十分穩定。
圖示服務(wù)架構理解記憶2Filebeat 配置文件
配置 Filebeat 工具的核心就是如何編寫(xiě)其對應的配置文件!
對應 Filebeat 工具的配置主要是通過(guò)編寫(xiě)其配置文件來(lái)控制的,對于通過(guò) rpm 或者 deb 包來(lái)安裝的情況,配置文件默認會(huì )存儲在,/etc/filebeat/filebeat.yml 這個(gè)路徑下面。而對于,對于 MAC 或者 Win 系統來(lái)說(shuō),請查看解壓文件中相關(guān)文件,其中都有涉及。
下面展示了 Filebeat 工具的主配置文件,注釋信息中都對其各個(gè)字段含義進(jìn)行了詳細的解釋?zhuān)疫@里就不再贅述了。需要注意的是,我們將日志的輸入來(lái)源統統定義去讀取 inputs.d 目錄下的所有 yml 配置。所以,我們可以更加不用的服務(wù)(測試、正式服務(wù))來(lái)定義不同的配置文件,根據物理機部署的實(shí)際情況具體配置。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br /><br />
下面展示一個(gè)簡(jiǎn)單的 inputs.d 目錄下面的 yml 配置文件的具體內容,其主要作用就是配置單獨服務(wù)的獨立日志數據,以及追加不同的數據 tag 類(lèi)型。
#?配置輸入來(lái)源的日志信息<br />#?我們合理將其配置到了inputs.d目錄下的所有yml文件<br />filebeat.config.inputs:<br />??enabled:?true<br />??path:?${path.config}/inputs.d/*.yml<br />??#?若收取日志格式為json的log請開(kāi)啟此配置<br />??#?json.keys_under_root:?true<br /><br />#?配置filebeat需要加載的模塊<br />filebeat.config.modules:<br />??path:?${path.config}/modules.d/*.yml<br />??reload.enabled:?false<br /><br />setup.template.settings:<br />??index.number_of_shards:?1<br /><br />#?配置將日志信息發(fā)送那個(gè)地址上面<br />output.logstash:<br />??hosts:?["11.22.33.44:5500"]<br /><br />#?output.file:<br />#???enable:?true<br /><br />processors:<br />??-?add_host_metadata:?~<br />??-?rename:<br />??????fields:<br />????????-?from:?"log"<br />??????????to:?"message"<br />??-?add_fields:<br />??????target:?""<br />??????fields:<br />????????#?加token是為了防止無(wú)認證的服務(wù)上Graylog服務(wù)發(fā)送數據<br />????????token:?"0uxxxxaM-1111-2222-3333-VQZJxxxxxwgX?"<br />
需要注意的是,針對于不同的日志類(lèi)型,filebeat 還提供了不同了模塊來(lái)配置不同的服務(wù)日志以及其不同的模塊特性,比如我們常見(jiàn)的 PostgreSQl、Redis、Iptables 等。
#?iptables<br />-?module:?iptables<br />??log:<br />????enabled:?true<br />????var.paths:?["/var/log/iptables.log"]<br />????var.input:?"file"<br /><br />#?postgres<br />-?module:?postgresql<br />??log:<br />????enabled:?true<br />????var.paths:?["/path/to/log/postgres/*.log*"]<br /><br />#?nginx<br />-?module:?nginx<br />??access:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/access.log*"]<br />??error:<br />????enabled:?true<br />????var.paths:?["/path/to/log/nginx/error.log*"]<br />
3Graylog 服務(wù)介紹
服務(wù)日志收集方案:Filebeat + Graylog!
Graylog 日志監控系統
Graylog 是一個(gè)開(kāi)源的日志聚合、分析、審計、展現和預警工具。在功能上來(lái)說(shuō),和 ELK 類(lèi)似,但又比 ELK 要簡(jiǎn)單很多。依靠著(zhù)更加簡(jiǎn)潔,高效,部署使用簡(jiǎn)單的優(yōu)勢很快受到許多人的青睞。當然,在擴展性上面確實(shí)沒(méi)有比 ELK 好,但是其有商業(yè)版本可以選擇。
Graylog 工作流程介紹
部署 Graylog 最簡(jiǎn)單的架構就是單機部署,復雜的也是部署集群模式,架構圖示如下所示。我們可以看到其中包含了三個(gè)組件,分別是 Elasticsearch、MongoDb 和 Graylog。其中,Elasticsearch 用來(lái)持久化存儲和檢索日志文件數據(IO 密集),MongoDb 用來(lái)存儲關(guān)于 Graylog 的相關(guān)配置,而 Graylog 來(lái)提供 Web 界面和對外接口的(CPU 密集)。
最小化單機部署
最優(yōu)化集群部署4Graylog 組件功能
配置 Graylog 服務(wù)的核心就是理解對應組件的功能以及其運作方式!
簡(jiǎn)單來(lái)講,Input 表示日志數據的來(lái)源,對不同來(lái)源的日志可以通過(guò) Extractors 來(lái)進(jìn)行日志的字段轉換,比如將 Nginx 的狀態(tài)碼變成對應的英文表述等。然后,通過(guò)不同的標簽類(lèi)型分組成不用的 Stream,并將這些日志數據存儲到指定的 Index 庫中進(jìn)行持久化保存。
Graylog中的核心服務(wù)組件
Graylog 通過(guò) Input 搜集日志,每個(gè) Input 單獨配置 Extractors 用來(lái)做字段轉換。Graylog 中日志搜索的基本單位是 Stream,每個(gè) Stream 可以有自己?jiǎn)为毜?Elastic Index Set,也可以共享一個(gè) Index Set。
Extractor 在 System/Input 中配置。Graylog 中很方便的一點(diǎn)就是可以加載一條日志,然后基于這個(gè)實(shí)際的例子進(jìn)行配置并能直接看到結果。內置的 Extractor 基本可以完成各種字段提取和轉換的任務(wù),但是也有些限制,在應用里寫(xiě)日志的時(shí)候就需要考慮到這些限制。Input 可以配置多個(gè) Extractors,按照順序依次執行。
系統會(huì )有一個(gè)默認的 Stream,所有日志默認都會(huì )保存到這個(gè) Stream 中,除非匹配了某個(gè) Stream,并且這個(gè) Stream 里配置了不保存日志到默認 Stream??梢酝ㄟ^(guò)菜單 Streams 創(chuàng )建更多的 Stream,新創(chuàng )建的 Stream 是暫停狀態(tài),需要在配置完成后手動(dòng)啟動(dòng)。Stream 通過(guò)配置條件匹配日志,滿(mǎn)足條件的日志添加 stream ID 標識字段并保存到對應的 Elastic Index Set 中。
Index Set 通過(guò)菜單 System/Indices 創(chuàng )建。日志存儲的性能,可靠性和過(guò)期策略都通過(guò) Index Set 來(lái)配置。性能和可靠性就是配置 Elastic Index 的一些參數,主要參數包括,Shards 和 Replicas。
除了上面提到的日志處理流程,Graylog 還提供了 Pipeline 腳本實(shí)現更靈活的日志處理方案。這里不詳細闡述,只介紹如果使用 Pipelines 來(lái)過(guò)濾不需要的日志。下面是丟棄 level > 6 的所有日志的 Pipeline Rule 的例子。從數據采集(input),字段解析(extractor),分流到 stream,再到 Pipeline 的清洗,一氣呵成,無(wú)需在通過(guò)其他方式進(jìn)行二次加工。
Sidecar 是一個(gè)輕量級的日志采集器,通過(guò)訪(fǎng)問(wèn) Graylog 進(jìn)行集中式管理,支持 Linux 和 windows 系統。Sidecar 守護進(jìn)程會(huì )定期訪(fǎng)問(wèn) Graylog 的 REST API 接口獲取 Sidecar 配置文件中定義的標簽(tag),Sidecar 在首次運行時(shí)會(huì )從 Graylog 服務(wù)器拉取配置文件中指定標簽(tag)的配置信息同步到本地。目前 Sidecar 支持 NXLog,Filebeat 和 Winlogbeat。他們都通過(guò) Graylog 中的 web 界面進(jìn)行統一配置,支持 Beats、CEF、Gelf、Json API、NetFlow 等輸出類(lèi)型。Graylog 最厲害的在于可以在配置文件中指定 Sidecar 把日志發(fā)送到哪個(gè) Graylog 群集,并對 Graylog 群集中的多個(gè) input 進(jìn)行負載均衡,這樣在遇到日志量非常龐大的時(shí)候,Graylog 也能應付自如。
rule?"discard?debug?messages"<br />when<br />??to_long($message.level)?>?6<br />then<br />??drop_message();<br />end<br />
日志集中保存到 Graylog 后就可以方便的使用搜索了。不過(guò)有時(shí)候還是需要對數據進(jìn)行近一步的處理。主要有兩個(gè)途徑,分別是直接訪(fǎng)問(wèn) Elastic 中保存的數據,或者通過(guò) Graylog 的 Output 轉發(fā)到其它服務(wù)。
5服務(wù)安裝和部署
主要介紹部署 Filebeat + Graylog 的安裝步驟和注意事項!
使用 Graylog 來(lái)收集日志
部署 Filebeat 工具
官方提供了多種的部署方式,包括通過(guò) rpm 和 deb 包安裝服務(wù),以及源代碼編譯的方式安裝服務(wù),同時(shí)包括了使用 Docker 或者 kubernetes 的方式安裝服務(wù)。我們根據自己的實(shí)際需要,進(jìn)行安裝即可。
#?Ubuntu(deb)<br />$?curl?-L?-O?https://artifacts.elastic.co/d ... %3Bbr />$?sudo?dpkg?-i?filebeat-7.8.1-amd64.deb<br />$?sudo?systemctl?enable?filebeat<br />$?sudo?service?filebeat?start<br /><br />#?使用docker啟動(dòng)<br />docker?run?-d?--name=filebeat?--user=root?\<br />??--volume="./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro"?\<br />??--volume="/var/lib/docker/containers:/var/lib/docker/containers:ro"?\<br />??--volume="/var/run/docker.sock:/var/run/docker.sock:ro"?\<br />??docker.elastic.co/beats/filebeat:7.8.1?filebeat?-e?-strict.perms=false?\<br />??-E?output.elasticsearch.hosts=["elasticsearch:9200"]<br />
使用 Graylog 來(lái)收集日志
部署 Graylog 服務(wù)
我們這里主要介紹使用 Docker 容器來(lái)部署服務(wù),如果你需要使用其他方式來(lái)部署的話(huà),請自行查看官方文檔對應章節的安裝部署步驟。在服務(wù)部署之前,我們需要給 Graylog 服務(wù)生成等相關(guān)信息,生成部署如下所示:
<p>#?生成password_secret密碼(最少16位)<br />$?sudo?apt?install?-y?pwgen<br />$?pwgen?-N?1?-s?16<br />zscMb65...FxR9ag<br /><br />#?生成后續Web登錄時(shí)所需要使用的密碼<br />$?echo?-n?"Enter?Password:?"?&&?head?-1?
超好用的收集信息工具
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 145 次瀏覽 ? 2022-05-04 14:00
什么是 OSINT?
如果您聽(tīng)說(shuō)過(guò)這個(gè)名字,OSINT代表開(kāi)源情報,它指的是可以從免費公共來(lái)源合法收集的有關(guān)個(gè)人或組織的任何信息。在實(shí)踐中,這往往意味著(zhù)在互聯(lián)網(wǎng)上找到的信息,但從技術(shù)上講,任何公共信息都屬于OSINT類(lèi)別,無(wú)論是公共圖書(shū)館的書(shū)籍或報告,報紙上的文章還是新聞稿中的聲明。
OSINT 還包括可在不同類(lèi)型的介質(zhì)中找到的信息。雖然我們通常認為它是基于文本的,但圖像,視頻,網(wǎng)絡(luò )研討會(huì ),公開(kāi)演講和會(huì )議中的信息都屬于該術(shù)語(yǔ)。
OSINT的用途是什么?
通過(guò)收集有關(guān)特定目標的公開(kāi)可用信息源,以更好地了解其特征并縮小搜索區域以查找可能的漏洞。數據信息可以生成的情報來(lái)構建威脅模型?;蛘哂嗅槍π缘木W(wǎng)絡(luò )攻擊,如軍事攻擊,從偵察開(kāi)始,數字偵察的第一階段是被動(dòng)地獲取情報,而不向目標發(fā)出警報。一旦可以從公共來(lái)源收集有關(guān)您的情報類(lèi)型,就可以使用它來(lái)幫助您或您的安全團隊制定更好的防御策略。
OSINT工具
用于情報收集的最明顯的工具之一是Google,Bing等網(wǎng)絡(luò )搜索引擎。事實(shí)上,有幾十個(gè)搜索引擎,對于特定類(lèi)型的查詢(xún),有些搜索引擎可能會(huì )返回比其他搜索引擎更好的結果。那么,問(wèn)題是,如何以有效的方式查詢(xún)這許多引擎呢?
Searx是解決此問(wèn)題并使Web查詢(xún)更有效的一個(gè)很好的工具。Searx是元搜索引擎,允許您匿名并同時(shí)收集來(lái)自70多個(gè)搜索服務(wù)的結果。Searx是免費的,您甚至可以托管自己的實(shí)例,以獲得最終的隱私。用戶(hù)既不會(huì )被跟蹤,也不會(huì )被分析,并且默認情況下禁用cookie。Searx也可以通過(guò)Tor用于在線(xiàn)匿名。
有很多人一直在為OSINT開(kāi)發(fā)新工具,當然,跟上他們以及網(wǎng)絡(luò )安全世界中其他任何事情的好地方就是在Twitter上關(guān)注人們。然而,在Twitter上跟蹤事情可能很困難。幸運的是,還有一個(gè)名為T(mén)wint的OSINT工具。
Twint是一個(gè)用Python編寫(xiě)的Twitter報廢工具,可以很容易地在Twitter上匿名收集和搜索信息,而無(wú)需注冊Twitter服務(wù)本身或使用API密鑰,就像使用Recon-ng這樣的工具一樣。使用 Twint,根本不需要身份驗證或 API。只需安裝工具并開(kāi)始搜索即可。您可以按用戶(hù),地理位置和時(shí)間范圍以及其他可能性進(jìn)行搜索。這只是Twint的一些選擇,但也有許多其他選擇。
那么,如何使用 Twint 來(lái)幫助您跟上 OSINT 的發(fā)展呢?嗯,這很容易,是Twint在行動(dòng)中的一個(gè)很好的例子。由于 Twint 允許你指定一個(gè)--因為選項,以便僅從某個(gè)日期開(kāi)始拉取推文,因此你可以將其與 Twint 的搜索動(dòng)詞相結合,每天抓取標記有#OSINT的新推文。您可以使用 Twint 的--database選項(保存為 SQLite 格式)自動(dòng)執行該腳本并將結果饋送到數據庫中,以便在方便時(shí)查看。
另一個(gè)可以用來(lái)收集公共信息的好工具是Metagaofil。此工具使用Google搜索引擎從給定域中檢索公共PDF,Word文檔,Powerpoint和Excel文件。然后,它可以自主地從這些文檔中提取元數據,以生成列出用戶(hù)名、軟件版本、服務(wù)器和計算機名稱(chēng)等信息的報告。
查看全部
超好用的收集信息工具
什么是 OSINT?
如果您聽(tīng)說(shuō)過(guò)這個(gè)名字,OSINT代表開(kāi)源情報,它指的是可以從免費公共來(lái)源合法收集的有關(guān)個(gè)人或組織的任何信息。在實(shí)踐中,這往往意味著(zhù)在互聯(lián)網(wǎng)上找到的信息,但從技術(shù)上講,任何公共信息都屬于OSINT類(lèi)別,無(wú)論是公共圖書(shū)館的書(shū)籍或報告,報紙上的文章還是新聞稿中的聲明。
OSINT 還包括可在不同類(lèi)型的介質(zhì)中找到的信息。雖然我們通常認為它是基于文本的,但圖像,視頻,網(wǎng)絡(luò )研討會(huì ),公開(kāi)演講和會(huì )議中的信息都屬于該術(shù)語(yǔ)。
OSINT的用途是什么?
通過(guò)收集有關(guān)特定目標的公開(kāi)可用信息源,以更好地了解其特征并縮小搜索區域以查找可能的漏洞。數據信息可以生成的情報來(lái)構建威脅模型?;蛘哂嗅槍π缘木W(wǎng)絡(luò )攻擊,如軍事攻擊,從偵察開(kāi)始,數字偵察的第一階段是被動(dòng)地獲取情報,而不向目標發(fā)出警報。一旦可以從公共來(lái)源收集有關(guān)您的情報類(lèi)型,就可以使用它來(lái)幫助您或您的安全團隊制定更好的防御策略。
OSINT工具
用于情報收集的最明顯的工具之一是Google,Bing等網(wǎng)絡(luò )搜索引擎。事實(shí)上,有幾十個(gè)搜索引擎,對于特定類(lèi)型的查詢(xún),有些搜索引擎可能會(huì )返回比其他搜索引擎更好的結果。那么,問(wèn)題是,如何以有效的方式查詢(xún)這許多引擎呢?
Searx是解決此問(wèn)題并使Web查詢(xún)更有效的一個(gè)很好的工具。Searx是元搜索引擎,允許您匿名并同時(shí)收集來(lái)自70多個(gè)搜索服務(wù)的結果。Searx是免費的,您甚至可以托管自己的實(shí)例,以獲得最終的隱私。用戶(hù)既不會(huì )被跟蹤,也不會(huì )被分析,并且默認情況下禁用cookie。Searx也可以通過(guò)Tor用于在線(xiàn)匿名。
有很多人一直在為OSINT開(kāi)發(fā)新工具,當然,跟上他們以及網(wǎng)絡(luò )安全世界中其他任何事情的好地方就是在Twitter上關(guān)注人們。然而,在Twitter上跟蹤事情可能很困難。幸運的是,還有一個(gè)名為T(mén)wint的OSINT工具。
Twint是一個(gè)用Python編寫(xiě)的Twitter報廢工具,可以很容易地在Twitter上匿名收集和搜索信息,而無(wú)需注冊Twitter服務(wù)本身或使用API密鑰,就像使用Recon-ng這樣的工具一樣。使用 Twint,根本不需要身份驗證或 API。只需安裝工具并開(kāi)始搜索即可。您可以按用戶(hù),地理位置和時(shí)間范圍以及其他可能性進(jìn)行搜索。這只是Twint的一些選擇,但也有許多其他選擇。
那么,如何使用 Twint 來(lái)幫助您跟上 OSINT 的發(fā)展呢?嗯,這很容易,是Twint在行動(dòng)中的一個(gè)很好的例子。由于 Twint 允許你指定一個(gè)--因為選項,以便僅從某個(gè)日期開(kāi)始拉取推文,因此你可以將其與 Twint 的搜索動(dòng)詞相結合,每天抓取標記有#OSINT的新推文。您可以使用 Twint 的--database選項(保存為 SQLite 格式)自動(dòng)執行該腳本并將結果饋送到數據庫中,以便在方便時(shí)查看。
另一個(gè)可以用來(lái)收集公共信息的好工具是Metagaofil。此工具使用Google搜索引擎從給定域中檢索公共PDF,Word文檔,Powerpoint和Excel文件。然后,它可以自主地從這些文檔中提取元數據,以生成列出用戶(hù)名、軟件版本、服務(wù)器和計算機名稱(chēng)等信息的報告。
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 128 次瀏覽 ? 2022-05-04 13:08
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
深入淺出前端監控
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 130 次瀏覽 ? 2022-05-02 22:02
重寫(xiě) fetch 方法
當然了,重寫(xiě)上述方法后除了異常請求可以被監控到之外,正常響應的請求狀態(tài)自然也能被采集到,比如 APM 會(huì )將對所有上報請求的持續時(shí)間進(jìn)行分析從而得出慢請求的占比:
PS:如果通過(guò) XHR 或 fetch 來(lái)上報監控數據的話(huà),上報請求也會(huì )被被攔截,可以有選擇地做一層過(guò)濾處理。
卡頓異常
卡頓指的是顯示器刷新時(shí)下一幀的畫(huà)面還沒(méi)有準備好,導致連續多次展示同樣的畫(huà)面,從而讓用戶(hù)感覺(jué)到頁(yè)面不流暢,也就是所謂的掉幀,衡量一個(gè)頁(yè)面是否卡頓的指標就是我們熟知的 FPS。
如何獲取 FPS
Chrome DevTool 中有一欄 Rendering 中包含 FPS 指標,但目前瀏覽器標準中暫時(shí)沒(méi)有提供相應 API ,只能手動(dòng)實(shí)現。這里需要借助 requestAnimationFrame 方法模擬實(shí)現,瀏覽器會(huì )在下一次重繪之前執行 rAF 的回調,因此可以通過(guò)計算每秒內 rAF 的執行次數來(lái)計算當前頁(yè)面的 FPS。
通過(guò) rAF 計算 FPS
如何上報“真實(shí)卡頓”
從技術(shù)角度看 FPS 低于 60 即視為卡頓,但在真實(shí)環(huán)境中用戶(hù)很多行為都可能造成 FPS 的波動(dòng),并不能無(wú)腦地把 FPS 低于 60 以下的 case 全部上報,會(huì )造成非常多無(wú)效數據,因此需要結合實(shí)際的用戶(hù)體驗重新定義“真正的卡頓”,這里貼一下司內 APM 平臺的上報策略:
頁(yè)面 FPS 持續低于預期:當前頁(yè)面連續 3s FPS 低于 20。用戶(hù)操作帶來(lái)的卡頓:當用戶(hù)進(jìn)行交互行為后,渲染新的一幀的時(shí)間超過(guò) 16ms + 100ms。崩潰異常
Web 頁(yè)面崩潰指在網(wǎng)頁(yè)運行過(guò)程頁(yè)面完全無(wú)響應的現象,通常有兩種情況會(huì )造成頁(yè)面崩潰:
JS 主線(xiàn)程出現無(wú)限循環(huán),觸發(fā)瀏覽器的保護策略,結束當前頁(yè)面的進(jìn)程。內存不足
發(fā)生崩潰時(shí)主線(xiàn)程被阻塞,因此對崩潰的監控只能在獨立于 JS 主線(xiàn)程的 Worker 線(xiàn)程中進(jìn)行,我們可以采用 Web Worker 心跳檢測的方式來(lái)對主線(xiàn)程進(jìn)行不斷的探測,如果主線(xiàn)程崩潰,就不會(huì )有任何響應,那就可以在 Worker 線(xiàn)程中進(jìn)行崩潰異常的上報。這里繼續貼一下 APM 的檢測策略:
Web Worker:
崩潰檢測
性能監控
性能監控并不只是簡(jiǎn)單的監控“頁(yè)面速度有多快”,需要從用戶(hù)體驗的角度全面衡量性能指標。(就是所謂的 RUM 指標)目前業(yè)界主流標準是 Google 最新定義的 Core Web Vitals:
可以看到最新標準中,以往熟知的 FP、FCP、FMP、TTI 等指標都被移除了,個(gè)人認為這些指標還是具備一定的參考價(jià)值,因此下文還是會(huì )將這些指標進(jìn)行相關(guān)介紹。(谷歌的話(huà)不聽(tīng)不聽(tīng))
Loading 加載
和 Loading 相關(guān)的指標有 FP 、FCP 、FMP 和 LCP,首先來(lái)看一下我們相對熟悉的幾個(gè)指標:
FP/FCP/FMP
一張流傳已久的圖
這兩個(gè)指標都通過(guò) PerformancePaintTiming API 獲?。?br />
通過(guò) PerformancePaintTiming 獲取 FP 和 FCP
下面再來(lái)看 FMP 的定義和獲取方式:
FMP 的計算相對復雜,因為瀏覽器并未提供相應的 API,在此之前我們先看一組圖:
從圖中可以發(fā)現頁(yè)面渲染過(guò)程中的一些規律:
在 1.577 秒,頁(yè)面渲染了一個(gè)搜索框,此時(shí)已經(jīng)有 60 個(gè)布局對象被添加到了布局樹(shù)中。在 1.760 秒,頁(yè)面頭部整體渲染完成,此時(shí)布局對象總數是 103 個(gè)。在 1.907 秒,頁(yè)面主體內容已經(jīng)繪制完成,此時(shí)有 261 個(gè)布局對象被添加到布局樹(shù)中從用戶(hù)體驗的角度看,此時(shí)的時(shí)間點(diǎn)就是是 FMP。
可以看到布局對象的數量與頁(yè)面完成度高度相關(guān)。業(yè)界目前比較認可的一個(gè)計算 FMP 的方式就是——「頁(yè)面在加載和渲染過(guò)程中最大布局變動(dòng)之后的那個(gè)繪制時(shí)間即為當前頁(yè)面的 FMP 」
實(shí)現原理則需要通過(guò) MutationObserver 監聽(tīng) document 整體的 DOM 變化,在回調計算出當前 DOM 樹(shù)的分數,分數變化最劇烈的時(shí)刻,即為 FMP 的時(shí)間點(diǎn)。
至于如何計算當前頁(yè)面 DOM 的分數,LightHouse 的源碼中會(huì )根據當前節點(diǎn)深度作為變量做一個(gè)權重的計算,具體實(shí)現可以參考 LightHouse 源碼。
const?curNodeScore?=?1?+?0.5?*?depth;<br />const?domScore?=?所有子節點(diǎn)分數求和<br />
上述計算方式性能開(kāi)銷(xiāo)大且未必準確,LightHouse 6.0 已明確廢棄了 FMP 打分項,建議在具體業(yè)務(wù)場(chǎng)景中根據實(shí)際情況手動(dòng)埋點(diǎn)來(lái)確定 FMP 具體的值,更準確也更高效。
LCP
沒(méi)錯,LCP (Largest Contentful Paint) 是就是用來(lái)代替 FMP 的一個(gè)性能指標 ,用于度量視口中最大的內容元素何時(shí)可見(jiàn),可以用來(lái)確定頁(yè)面的主要內容何時(shí)在屏幕上完成渲染。
使用 Largest Contentful Paint API 和 PerformanceObserver 即可獲取 LCP 指標的值:
獲取 LCP
Interactivity 交互TTI
TTI(Time To Interactive) 表示從頁(yè)面加載開(kāi)始到頁(yè)面處于完全可交互狀態(tài)所花費的時(shí)間, TTI 值越小,代表用戶(hù)可以更早地操作頁(yè)面,用戶(hù)體驗就更好。
這里定義一下什么是完全可交互狀態(tài)的頁(yè)面:
頁(yè)面已經(jīng)顯示有用內容。頁(yè)面上的可見(jiàn)元素關(guān)聯(lián)的事件響應函數已經(jīng)完成注冊。事件響應函數可以在事件發(fā)生后的 50ms 內開(kāi)始執行(主線(xiàn)程無(wú) Long Task)。
TTI 的算法略有些復雜,結合下圖看一下具體步驟:
TTI 示意圖
Long Task: 阻塞主線(xiàn)程達 50 毫秒或以上的任務(wù)。
從 FCP 時(shí)間開(kāi)始,向前搜索一個(gè)不小于 5s 的靜默窗口期。(靜默窗口期定義:窗口所對應的時(shí)間內沒(méi)有 Long Task,且進(jìn)行中的網(wǎng)絡(luò )請求數不超過(guò) 2 個(gè))找到靜默窗口期后,從靜默窗口期向后搜索到最近的一個(gè) Long Task,Long Task 的結束時(shí)間即為 TTI。如果一直找到 FCP 時(shí)刻仍然沒(méi)有找到 Long Task,以 FCP 時(shí)間作為 TTI。
其實(shí)現需要支持 Long Tasks API 和 Resource Timing API,具體實(shí)現感興趣的同學(xué)可以按照上述流程嘗試手動(dòng)實(shí)現。
FID
FID(First Input Delay) 用于度量用戶(hù)第一次與頁(yè)面交互的延遲時(shí)間,是用戶(hù)第一次與頁(yè)面交互到瀏覽器真正能夠開(kāi)始處理事件處理程序以響應該交互的時(shí)間。
其實(shí)現使用簡(jiǎn)潔的 PerformanceEventTiming API 即可,回調的觸發(fā)時(shí)機是用戶(hù)首次與頁(yè)面發(fā)生交互并得到瀏覽器響應(點(diǎn)擊鏈接、輸入文字等)。
獲取 FID
至于為何新的標準中采用 FID 而非 TTI,可能存在以下幾個(gè)因素:
Visual Stability 視覺(jué)穩定CLS
CLS(Cumulative Layout Shift) 是對在頁(yè)面的整個(gè)生命周期中發(fā)生的每一次意外布局變化的最大布局變化得分的度量,布局變化得分越小證明你的頁(yè)面越穩定。
聽(tīng)起來(lái)有點(diǎn)復雜,這里做一個(gè)簡(jiǎn)單的解釋?zhuān)?br /> 舉個(gè)例子,一個(gè)占據頁(yè)面高度 50% 的元素,向下偏移了 25%,那么其得分為 0.75 * 0.25,大于標準定義的 0.1 分,該頁(yè)面就視為視覺(jué)上沒(méi)那么穩定的頁(yè)面。
使用 Layout Instability API 和 PerformanceObserver 來(lái)獲取 CLS:
獲取 CLS
一點(diǎn)感受:在翻閱諸多參考資料后,私以為性能監控是一件長(cháng)期實(shí)踐、以實(shí)際業(yè)務(wù)為導向的事情,業(yè)內主流標準日新月異,到底監控什么指標是最貼合用戶(hù)體驗的我們不得而知,對于 FMP、FPS 這類(lèi)瀏覽器未提供 API 獲取方式的指標花費大量力氣去探索實(shí)現是否有足夠的收益也存在一定的疑問(wèn),但毋容置疑的是從自身頁(yè)面的業(yè)務(wù)屬性出發(fā),結合一些用戶(hù)反饋再進(jìn)行相關(guān)手段的優(yōu)化可能是更好的選擇。(更推薦深入了解瀏覽器渲染原理,寫(xiě)出性能極佳的頁(yè)面,讓 APM 同學(xué)失業(yè)
數據上報
得到所有錯誤、性能、用戶(hù)行為以及相應的環(huán)境信息后就要考慮如何進(jìn)行數據上報,理論上正常使用ajax 即可,但有一些數據上報可能出現在頁(yè)面關(guān)閉 (unload) 的時(shí)刻,這些請求會(huì )被瀏覽器的策略 cancel 掉,因此出現了以下幾種解決方案:
優(yōu)先使用 Navigator.sendBeacon,這個(gè) API 就是為了解決上述問(wèn)題而誕生,它通過(guò) HTTP POST 將數據異步傳輸到服務(wù)器且不會(huì )影響頁(yè)面卸載。如果不支持上述 API,動(dòng)態(tài)創(chuàng )建一個(gè)
/ > 標簽將數據通過(guò) url 拼接的方式傳遞。使用同步 XHR 進(jìn)行上報以延遲頁(yè)面卸載,不過(guò)現在很多瀏覽器禁止了該行為。
APM 采取了第一種方式,不支持 sendBeacon 則使用 XHR,偶爾丟日志的原因找到了。
由于監控數據通常量級都十分龐大,因此不能簡(jiǎn)單地采集一個(gè)就上報一個(gè),需要一些優(yōu)化手段:
總結
本文旨在提供一個(gè)相對體系的前端監控視圖,幫助各位了解前端監控領(lǐng)域我們能做什么、需要做什么。此外,如果能對頁(yè)面性能和異常處理有著(zhù)更深入的認知,無(wú)論是在開(kāi)發(fā)應用時(shí)的自我管理(減少 bug、有意識地書(shū)寫(xiě)高性能代碼),還是自研監控 SDK 都有所裨益。
如何設計監控 SDK 不是本文的重點(diǎn),部分監控指標的定義和實(shí)現細節也可能存在其他解法,實(shí)現一個(gè)完善且健壯的前端監控 SDK 還有很多技術(shù)細節,例如每個(gè)指標可以提供哪些配置項、如何設計上報的維度、如何做好兼容性等等,這些都需要在真實(shí)的業(yè)務(wù)場(chǎng)景中不斷打磨和優(yōu)化才能趨于成熟。
參考
Google Developer
?? 謝謝支持
以上便是本次分享的全部?jì)热?,希望對你有所幫助^_^ 查看全部
深入淺出前端監控
重寫(xiě) fetch 方法
當然了,重寫(xiě)上述方法后除了異常請求可以被監控到之外,正常響應的請求狀態(tài)自然也能被采集到,比如 APM 會(huì )將對所有上報請求的持續時(shí)間進(jìn)行分析從而得出慢請求的占比:
PS:如果通過(guò) XHR 或 fetch 來(lái)上報監控數據的話(huà),上報請求也會(huì )被被攔截,可以有選擇地做一層過(guò)濾處理。
卡頓異常
卡頓指的是顯示器刷新時(shí)下一幀的畫(huà)面還沒(méi)有準備好,導致連續多次展示同樣的畫(huà)面,從而讓用戶(hù)感覺(jué)到頁(yè)面不流暢,也就是所謂的掉幀,衡量一個(gè)頁(yè)面是否卡頓的指標就是我們熟知的 FPS。
如何獲取 FPS
Chrome DevTool 中有一欄 Rendering 中包含 FPS 指標,但目前瀏覽器標準中暫時(shí)沒(méi)有提供相應 API ,只能手動(dòng)實(shí)現。這里需要借助 requestAnimationFrame 方法模擬實(shí)現,瀏覽器會(huì )在下一次重繪之前執行 rAF 的回調,因此可以通過(guò)計算每秒內 rAF 的執行次數來(lái)計算當前頁(yè)面的 FPS。
通過(guò) rAF 計算 FPS
如何上報“真實(shí)卡頓”
從技術(shù)角度看 FPS 低于 60 即視為卡頓,但在真實(shí)環(huán)境中用戶(hù)很多行為都可能造成 FPS 的波動(dòng),并不能無(wú)腦地把 FPS 低于 60 以下的 case 全部上報,會(huì )造成非常多無(wú)效數據,因此需要結合實(shí)際的用戶(hù)體驗重新定義“真正的卡頓”,這里貼一下司內 APM 平臺的上報策略:
頁(yè)面 FPS 持續低于預期:當前頁(yè)面連續 3s FPS 低于 20。用戶(hù)操作帶來(lái)的卡頓:當用戶(hù)進(jìn)行交互行為后,渲染新的一幀的時(shí)間超過(guò) 16ms + 100ms。崩潰異常
Web 頁(yè)面崩潰指在網(wǎng)頁(yè)運行過(guò)程頁(yè)面完全無(wú)響應的現象,通常有兩種情況會(huì )造成頁(yè)面崩潰:
JS 主線(xiàn)程出現無(wú)限循環(huán),觸發(fā)瀏覽器的保護策略,結束當前頁(yè)面的進(jìn)程。內存不足
發(fā)生崩潰時(shí)主線(xiàn)程被阻塞,因此對崩潰的監控只能在獨立于 JS 主線(xiàn)程的 Worker 線(xiàn)程中進(jìn)行,我們可以采用 Web Worker 心跳檢測的方式來(lái)對主線(xiàn)程進(jìn)行不斷的探測,如果主線(xiàn)程崩潰,就不會(huì )有任何響應,那就可以在 Worker 線(xiàn)程中進(jìn)行崩潰異常的上報。這里繼續貼一下 APM 的檢測策略:
Web Worker:
崩潰檢測
性能監控
性能監控并不只是簡(jiǎn)單的監控“頁(yè)面速度有多快”,需要從用戶(hù)體驗的角度全面衡量性能指標。(就是所謂的 RUM 指標)目前業(yè)界主流標準是 Google 最新定義的 Core Web Vitals:
可以看到最新標準中,以往熟知的 FP、FCP、FMP、TTI 等指標都被移除了,個(gè)人認為這些指標還是具備一定的參考價(jià)值,因此下文還是會(huì )將這些指標進(jìn)行相關(guān)介紹。(谷歌的話(huà)不聽(tīng)不聽(tīng))
Loading 加載
和 Loading 相關(guān)的指標有 FP 、FCP 、FMP 和 LCP,首先來(lái)看一下我們相對熟悉的幾個(gè)指標:
FP/FCP/FMP
一張流傳已久的圖
這兩個(gè)指標都通過(guò) PerformancePaintTiming API 獲?。?br />
通過(guò) PerformancePaintTiming 獲取 FP 和 FCP
下面再來(lái)看 FMP 的定義和獲取方式:
FMP 的計算相對復雜,因為瀏覽器并未提供相應的 API,在此之前我們先看一組圖:
從圖中可以發(fā)現頁(yè)面渲染過(guò)程中的一些規律:
在 1.577 秒,頁(yè)面渲染了一個(gè)搜索框,此時(shí)已經(jīng)有 60 個(gè)布局對象被添加到了布局樹(shù)中。在 1.760 秒,頁(yè)面頭部整體渲染完成,此時(shí)布局對象總數是 103 個(gè)。在 1.907 秒,頁(yè)面主體內容已經(jīng)繪制完成,此時(shí)有 261 個(gè)布局對象被添加到布局樹(shù)中從用戶(hù)體驗的角度看,此時(shí)的時(shí)間點(diǎn)就是是 FMP。
可以看到布局對象的數量與頁(yè)面完成度高度相關(guān)。業(yè)界目前比較認可的一個(gè)計算 FMP 的方式就是——「頁(yè)面在加載和渲染過(guò)程中最大布局變動(dòng)之后的那個(gè)繪制時(shí)間即為當前頁(yè)面的 FMP 」
實(shí)現原理則需要通過(guò) MutationObserver 監聽(tīng) document 整體的 DOM 變化,在回調計算出當前 DOM 樹(shù)的分數,分數變化最劇烈的時(shí)刻,即為 FMP 的時(shí)間點(diǎn)。
至于如何計算當前頁(yè)面 DOM 的分數,LightHouse 的源碼中會(huì )根據當前節點(diǎn)深度作為變量做一個(gè)權重的計算,具體實(shí)現可以參考 LightHouse 源碼。
const?curNodeScore?=?1?+?0.5?*?depth;<br />const?domScore?=?所有子節點(diǎn)分數求和<br />
上述計算方式性能開(kāi)銷(xiāo)大且未必準確,LightHouse 6.0 已明確廢棄了 FMP 打分項,建議在具體業(yè)務(wù)場(chǎng)景中根據實(shí)際情況手動(dòng)埋點(diǎn)來(lái)確定 FMP 具體的值,更準確也更高效。
LCP
沒(méi)錯,LCP (Largest Contentful Paint) 是就是用來(lái)代替 FMP 的一個(gè)性能指標 ,用于度量視口中最大的內容元素何時(shí)可見(jiàn),可以用來(lái)確定頁(yè)面的主要內容何時(shí)在屏幕上完成渲染。
使用 Largest Contentful Paint API 和 PerformanceObserver 即可獲取 LCP 指標的值:
獲取 LCP
Interactivity 交互TTI
TTI(Time To Interactive) 表示從頁(yè)面加載開(kāi)始到頁(yè)面處于完全可交互狀態(tài)所花費的時(shí)間, TTI 值越小,代表用戶(hù)可以更早地操作頁(yè)面,用戶(hù)體驗就更好。
這里定義一下什么是完全可交互狀態(tài)的頁(yè)面:
頁(yè)面已經(jīng)顯示有用內容。頁(yè)面上的可見(jiàn)元素關(guān)聯(lián)的事件響應函數已經(jīng)完成注冊。事件響應函數可以在事件發(fā)生后的 50ms 內開(kāi)始執行(主線(xiàn)程無(wú) Long Task)。
TTI 的算法略有些復雜,結合下圖看一下具體步驟:
TTI 示意圖
Long Task: 阻塞主線(xiàn)程達 50 毫秒或以上的任務(wù)。
從 FCP 時(shí)間開(kāi)始,向前搜索一個(gè)不小于 5s 的靜默窗口期。(靜默窗口期定義:窗口所對應的時(shí)間內沒(méi)有 Long Task,且進(jìn)行中的網(wǎng)絡(luò )請求數不超過(guò) 2 個(gè))找到靜默窗口期后,從靜默窗口期向后搜索到最近的一個(gè) Long Task,Long Task 的結束時(shí)間即為 TTI。如果一直找到 FCP 時(shí)刻仍然沒(méi)有找到 Long Task,以 FCP 時(shí)間作為 TTI。
其實(shí)現需要支持 Long Tasks API 和 Resource Timing API,具體實(shí)現感興趣的同學(xué)可以按照上述流程嘗試手動(dòng)實(shí)現。
FID
FID(First Input Delay) 用于度量用戶(hù)第一次與頁(yè)面交互的延遲時(shí)間,是用戶(hù)第一次與頁(yè)面交互到瀏覽器真正能夠開(kāi)始處理事件處理程序以響應該交互的時(shí)間。
其實(shí)現使用簡(jiǎn)潔的 PerformanceEventTiming API 即可,回調的觸發(fā)時(shí)機是用戶(hù)首次與頁(yè)面發(fā)生交互并得到瀏覽器響應(點(diǎn)擊鏈接、輸入文字等)。
獲取 FID
至于為何新的標準中采用 FID 而非 TTI,可能存在以下幾個(gè)因素:
Visual Stability 視覺(jué)穩定CLS
CLS(Cumulative Layout Shift) 是對在頁(yè)面的整個(gè)生命周期中發(fā)生的每一次意外布局變化的最大布局變化得分的度量,布局變化得分越小證明你的頁(yè)面越穩定。
聽(tīng)起來(lái)有點(diǎn)復雜,這里做一個(gè)簡(jiǎn)單的解釋?zhuān)?br /> 舉個(gè)例子,一個(gè)占據頁(yè)面高度 50% 的元素,向下偏移了 25%,那么其得分為 0.75 * 0.25,大于標準定義的 0.1 分,該頁(yè)面就視為視覺(jué)上沒(méi)那么穩定的頁(yè)面。
使用 Layout Instability API 和 PerformanceObserver 來(lái)獲取 CLS:
獲取 CLS
一點(diǎn)感受:在翻閱諸多參考資料后,私以為性能監控是一件長(cháng)期實(shí)踐、以實(shí)際業(yè)務(wù)為導向的事情,業(yè)內主流標準日新月異,到底監控什么指標是最貼合用戶(hù)體驗的我們不得而知,對于 FMP、FPS 這類(lèi)瀏覽器未提供 API 獲取方式的指標花費大量力氣去探索實(shí)現是否有足夠的收益也存在一定的疑問(wèn),但毋容置疑的是從自身頁(yè)面的業(yè)務(wù)屬性出發(fā),結合一些用戶(hù)反饋再進(jìn)行相關(guān)手段的優(yōu)化可能是更好的選擇。(更推薦深入了解瀏覽器渲染原理,寫(xiě)出性能極佳的頁(yè)面,讓 APM 同學(xué)失業(yè)
數據上報
得到所有錯誤、性能、用戶(hù)行為以及相應的環(huán)境信息后就要考慮如何進(jìn)行數據上報,理論上正常使用ajax 即可,但有一些數據上報可能出現在頁(yè)面關(guān)閉 (unload) 的時(shí)刻,這些請求會(huì )被瀏覽器的策略 cancel 掉,因此出現了以下幾種解決方案:
優(yōu)先使用 Navigator.sendBeacon,這個(gè) API 就是為了解決上述問(wèn)題而誕生,它通過(guò) HTTP POST 將數據異步傳輸到服務(wù)器且不會(huì )影響頁(yè)面卸載。如果不支持上述 API,動(dòng)態(tài)創(chuàng )建一個(gè)
/ > 標簽將數據通過(guò) url 拼接的方式傳遞。使用同步 XHR 進(jìn)行上報以延遲頁(yè)面卸載,不過(guò)現在很多瀏覽器禁止了該行為。
APM 采取了第一種方式,不支持 sendBeacon 則使用 XHR,偶爾丟日志的原因找到了。
由于監控數據通常量級都十分龐大,因此不能簡(jiǎn)單地采集一個(gè)就上報一個(gè),需要一些優(yōu)化手段:
總結
本文旨在提供一個(gè)相對體系的前端監控視圖,幫助各位了解前端監控領(lǐng)域我們能做什么、需要做什么。此外,如果能對頁(yè)面性能和異常處理有著(zhù)更深入的認知,無(wú)論是在開(kāi)發(fā)應用時(shí)的自我管理(減少 bug、有意識地書(shū)寫(xiě)高性能代碼),還是自研監控 SDK 都有所裨益。
如何設計監控 SDK 不是本文的重點(diǎn),部分監控指標的定義和實(shí)現細節也可能存在其他解法,實(shí)現一個(gè)完善且健壯的前端監控 SDK 還有很多技術(shù)細節,例如每個(gè)指標可以提供哪些配置項、如何設計上報的維度、如何做好兼容性等等,這些都需要在真實(shí)的業(yè)務(wù)場(chǎng)景中不斷打磨和優(yōu)化才能趨于成熟。
參考
Google Developer
?? 謝謝支持
以上便是本次分享的全部?jì)热?,希望對你有所幫助^_^
文章采集api Python 爬取人人視頻
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 163 次瀏覽 ? 2022-05-02 21:59
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
查看全部
文章采集api Python 爬取人人視頻
hello,小伙伴們,又見(jiàn)面了,距離上一次發(fā)布文章的時(shí)間,也算是久別重逢了。期間也發(fā)生了很多的事情,導致博文斷更,也是筆者不愿意的,但是確實(shí)是比較忙,不再過(guò)多贅述,希望大家能夠體諒。
平時(shí)不斷的在后臺收到小伙伴的私信,問(wèn)是不是不更了,答案當然是否定的,有著(zhù)這么多人的支持,小編還是要繼續努力下去的,再次謝謝大家的支持。
這次給大家帶來(lái)的文章是爬取人人視頻,之前多是分享一些爬取數據,圖片,音樂(lè ),還沒(méi)怎么分享過(guò)爬取過(guò)視頻的,那么想要爬取視頻的話(huà)該怎么爬取呢?
其實(shí)不管是圖片,還是音樂(lè ),或者是其他的文檔,大部分都是一個(gè)文件讀寫(xiě)的過(guò)程,當然視頻也不例外,只是文件的格式不同而已。所以我們也可以試著(zhù)以常規的手段去嘗試下爬取視頻,沒(méi)錯還是熟悉的套路與配方,即python常用函數 open()和 write()。
不過(guò)這次略微不同的是我們會(huì )使用到iter_content來(lái)獲取請求的原始響應數據,普通情況可以用r.raw,在初始請求中設置stream=True,來(lái)獲取服務(wù)器的原始套接字響應,在這里我們使用iter_content更加方便一些,因為requests.get(url) 默認是下載在內存中的,下載完成才存到硬盤(pán)上,但Response.iter_content可以邊下載邊存硬盤(pán)中,所以在這視頻下載方面更具有優(yōu)勢。
當然說(shuō)到 iter_content 的話(huà),不得不提下chunk_size,因為流式請求就是像流水一樣,不是一次過(guò)來(lái)而是一點(diǎn)一點(diǎn)“流”過(guò)來(lái)。處理流式數據也是一點(diǎn)一點(diǎn)處理。
而chunk_size會(huì )直接返回從當前位置往后讀取 chunk_size 大小的文件內容,且迭代響應數據。這避免了立即將內容讀入內存以獲得較大的響應。chunk_size是它應該讀入內存的字節數。chunk_size的類(lèi)型必須是int或None。None的值將根據流的值發(fā)揮不同的作用。
做了引薦與講解后,那么就開(kāi)始上我們的主菜了,即目標網(wǎng)站:
https://m.rr.tv/
介于代碼偏基礎化,且主要知識點(diǎn)做過(guò)分析就直接上代碼了,具體請看代碼:
單線(xiàn)程:
import requestsimport jsonimport reimport osheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}ep_list =[]vod_list = []def get_vod(url): response = requests.get(url = url,headers = headers)#請求url ep= re.compile(r'sid:"(.*?)",')#提取ep鏈接 ep_list = re.findall(ep,response.text) vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod鏈接 vod_list = re.findall(vod,response.text) vod= re.compile(r',title:"(.*?)",desc:"')#提取視頻標題 vod_name = re.findall(vod,response.text) ep = 1 os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 for i in ep_list: print("開(kāi)始下載"+vod_name[0]+"第"+str(ep)+"集") url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers)#下載請求 r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下載鏈接并發(fā)起下載請求 f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk) ep = ep+1if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目標視頻鏈接 get_vod(url)
多線(xiàn)程:
import requestsimport jsonimport reimport osfrom concurrent.futures import ThreadPoolExecutorheaders = {'Referer':'https://m.rr.tv/',#全局設置'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'}vod_list = []#存儲視頻鏈接vod_name = []#存儲視頻標題get_down_url =[]#存儲下載直鏈def get_vod(url): response = requests.get(url = url,headers = headers)#請求url vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找視頻鏈接 vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找視頻標題 for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text): url ="https://web-api.rr.tv/web/dram ... _list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址 response = requests.get(url = url,headers = headers) get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下載直鏈進(jìn)listdef down_begin(url,i): print("開(kāi)始多線(xiàn)程下載"+vod_name[0]+"第"+str(i)+"集") r = requests.get(url = url,headers = headers)#下載請求 f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存視頻 for chunk in r.iter_content(chunk_size=512): if chunk: f.write(chunk)if __name__ == '__main__': url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#進(jìn)入rr.tv自行獲取 get_vod(url) os.mkdir('./'+vod_name[0])#創(chuàng )建視頻保存目錄 with ThreadPoolExecutor(10) as f:#這里寫(xiě)多線(xiàn)程參數,適合幾十集的電視劇使用 for i,url in enumerate(get_down_url): i=int(i)+1 f.submit(down_begin,url = url,i=i)
把案例里面的鏈接改成你想要下載的鏈接,然后右擊運行代碼,即可成功的下載你想要的視頻了。代碼獲取后臺回復:”人人視頻“。
在文章的最后給大家來(lái)一波福利,因為前一段時(shí)間小編在爬取百度相關(guān)關(guān)鍵詞以及文章采集時(shí),經(jīng)常觸發(fā)百度的驗證機制,這種情況很明顯要使用到代理IP,后來(lái)群里一個(gè)小伙伴推薦了品贊代理IP,小編測試了下,完美解決了爬取中存在的問(wèn)題。
如果大家后續有需要使用到代理方面的業(yè)務(wù)的話(huà),可以?huà)叽a添加下方的二維碼。國內外的IP都有,新用戶(hù)可以免費測試。
文章采集api 性能指標的信仰危機
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 101 次瀏覽 ? 2022-05-02 19:45
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。 查看全部
文章采集api 性能指標的信仰危機
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。
文章采集api 性能指標的信仰危機
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 142 次瀏覽 ? 2022-05-02 02:40
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。 查看全部
文章采集api 性能指標的信仰危機
正在閱讀這篇文章的你,或多或者接觸過(guò)前端性能優(yōu)化,這樣的接觸可能是來(lái)自你的閱讀體驗也可能是來(lái)自工作經(jīng)驗。那我們不妨從一個(gè)非常簡(jiǎn)單的思想實(shí)驗開(kāi)始,請你借助你對這個(gè)領(lǐng)域的理解,來(lái)回答下面的幾個(gè)問(wèn)題:
不要有壓力,你可以慢慢思考并回答這幾個(gè)問(wèn)題,你關(guān)于第一個(gè)問(wèn)題的答案可能會(huì )隨著(zhù)二三問(wèn)題的出現而不斷的調整。
這篇文章的目的就是對上面三個(gè)問(wèn)題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。
一次復盤(pán)
目前我所在的項目上長(cháng)時(shí)間都依賴(lài)都 GA (Google Analytic) 作為衡量頁(yè)面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡(jiǎn)稱(chēng)為 APLT),通過(guò)它來(lái)斷定我們站點(diǎn)當前的性能狀態(tài)如何。
但是在定期收集該指標數據的過(guò)程中,我們發(fā)現用戶(hù)的感受和數據的展示可能并不一致,具體來(lái)說(shuō)數據看上去波瀾不驚,但用戶(hù)體驗卻直線(xiàn)下降。
所以我們不得不要回答一個(gè)至關(guān)重要的問(wèn)題,APLT 衡量的究竟是什么?
什么這個(gè)問(wèn)題之所以至關(guān)重要,是因為它的答案決定我們接下來(lái)要解決的問(wèn)題和需要采取的行動(dòng):
然而官方文檔對于這個(gè)指標的解釋是很曖昧的:
Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.
Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.
對于它的解釋?zhuān)覀儺a(chǎn)生了幾點(diǎn)疑問(wèn):
GA 的實(shí)現
GA 底層是通過(guò) Navigation Timing API 在采集性能數據
GA 不會(huì )統計每一個(gè)階段的數據,它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實(shí)是某些階段的統計之和:
GA 統計的僅僅是與 DOM 文檔有關(guān)的數據。APLT 定義里所說(shuō)的 load completion 時(shí)刻指的就是 loadEventEnd 事件的發(fā)生時(shí)機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時(shí)意味著(zhù)所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時(shí)間范圍最廣的。
腳本對 Avg Page Load Time 的影響是什么
如上圖所示,當瀏覽器自上而下解析 DOM 樹(shù)時(shí),它會(huì )遇見(jiàn)很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡(luò )中請求這些資源。
頁(yè)面的解析是同步的,所以腳本的加載會(huì )導致頁(yè)面解析的暫停。瀏覽器需要在腳本加載、編譯、執行完畢之后才會(huì )繼續之后的解析工作,這么做是有道理的,因為 JavaScript 可能會(huì )使用諸如 document.write() 方法來(lái)改變 DOM 的結構。你可能聽(tīng)說(shuō)過(guò)在 script 標簽上添加 async 或者 defer 屬性來(lái)異步的加載和執行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無(wú)法保證腳本執行的順序。但這則方案不一定適用于所有頁(yè)面,因為 async 無(wú)法保證腳本的執行順序,如果你的應用對腳本的執行順序有嚴格要求,那么它對你愛(ài)莫能助。
目前瀏覽器都配備preloader機制來(lái)提前掃面頁(yè)面中的外聯(lián)元素提前加載,但這個(gè)機制并無(wú)統一的標準也無(wú)法衡量效果,所以暫時(shí)不考慮它對我們的影響。
腳本下載之后需要經(jīng)過(guò)解析(parse / compile)和執行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語(yǔ)言,執行階段才會(huì )真正的運行我們編寫(xiě)的代碼。腳本的解析和執行也會(huì )阻塞頁(yè)面的解析
所以綜上,我們可以得出腳本確實(shí)能夠影響 APLT 。
但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說(shuō)如果 APLT 是 2 秒的話(huà),其中多少時(shí)間耗費在了腳本上?
這里沒(méi)有一個(gè)具體的數字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時(shí)間上
雖然此后 Chrome 對編譯過(guò)程進(jìn)行了優(yōu)化,但執行腳本過(guò)長(cháng)的困惱依然存在。同時(shí)這只是 Chrome 下的情況,我們無(wú)法確認其他瀏覽器在編譯腳本時(shí)也可以保證同樣的效率
如果說(shuō) APLT 是由不同的階段組成,那么我們有沒(méi)有可能計算出每一個(gè)階段的具體時(shí)間?
回顧上面關(guān)于 GA 指標的定義,至少我們現在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說(shuō)腳本的下載時(shí)間和執行時(shí)間,這些我們就無(wú)從得知了。這些是需要額外計算和采集的。
綜上,我們完全依賴(lài) APLT 來(lái)對站點(diǎn)的性能問(wèn)題進(jìn)行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。
一場(chǎng)關(guān)于指標的信仰危機
我想你大概明白了為什么我在上一節中花了這么大段的篇幅來(lái)解釋僅僅一個(gè)指標的含義。因為一個(gè)指標能透露的信息可能會(huì )比你想象的要復雜,引導和誤導并存。
首先要聲明我并不反對使用常見(jiàn)指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問(wèn)題方面給了非常大的幫助。在這里我想探討的是,如果常規指標是性能監控的底線(xiàn)的話(huà),它的上限在哪?
從上面的描述中我們不難看出 APLT 的涉獵的維度過(guò)于寬泛,它更偏向于一個(gè)技術(shù)向的綜合性指標,它展示給我們是趨勢而非細節。這樣帶來(lái)的問(wèn)題有兩個(gè):
接下來(lái)我們深入的聊聊這兩個(gè)問(wèn)題。
以用戶(hù)為中心
你或許有留意到,目前前端性能監測的趨勢逐漸在向以用戶(hù)為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會(huì )出現這樣的情況?因為隨著(zhù)單頁(yè)面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來(lái)越不能準確地反饋真實(shí)用戶(hù)的體驗與產(chǎn)品性能。在傳統后端渲染的多頁(yè)面應用模式下,資源加載完畢即意味著(zhù)頁(yè)面對用戶(hù)可用;而在單頁(yè)面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時(shí)應用才能真正地請求用戶(hù)個(gè)性化的數據,渲染定制化的頁(yè)面。
總的來(lái)說(shuō),越來(lái)越多重要且耗時(shí)的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監控起來(lái)。
好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數據。顧名思義的這些指標嘗試站在用戶(hù)體驗的視角展現應用在瀏覽器中被呈現時(shí)的性能;壞消息是,這些指標依然在測量真實(shí)的用戶(hù)體驗方面依然存在誤差。
就以上面提到的 FP、FCP、TTI 這三個(gè)指標為例,我用一個(gè)簡(jiǎn)單的例子說(shuō)明這三個(gè)指標是如何不夠準確的:在單頁(yè)面的初始化過(guò)程中,我們通常會(huì )提供類(lèi)似于「加載中」視圖,通常是一個(gè) placeholder 或者 skeleton 樣式,在數據請求完畢之后才會(huì )將實(shí)際的視圖渲染出來(lái):
如果加載時(shí)間過(guò)長(cháng),瀏覽器會(huì )以為「加載中」視圖就是對用戶(hù)可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個(gè)指標
下面這段代碼模擬的就是包含上面所說(shuō)情況的日常情況:在組件加載時(shí)模擬發(fā)出兩個(gè)請求,其中一個(gè)需要5秒較長(cháng)的等待時(shí)間,只有當兩個(gè)請求都返回時(shí)才能開(kāi)始渲染數據,否則一直提示用戶(hù)加載中。
function App() {<br /> const [data, setState] = useState([]);<br /> useEffect(() => {<br /> const longRequest = new Promise((resolve, reject) => {<br /> setTimeout(() => {<br /> resolve([]);<br /> }, 1000 * 5)<br /> });<br /> const shortRequest = Promise.resolve([]);<br /> <br /> Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {<br /> setState([<br /> ['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],<br /> ['2019', 10, 11, 12, 13],<br /> ['2020', 20, 11, 14, 13],<br /> ['2021', 30, 15, 12, 13]<br /> ])<br /> })<br /> }, []);<br /> return (<br /> <br /> {data && data.length<br /> ? <br /> : }<br /> <br /> )<br />}
如果你嘗試在瀏覽器中運行上述 App, 通過(guò) Devtools 觀(guān)測到的各個(gè)指標如下:
你能通過(guò)開(kāi)發(fā)者工具夠觀(guān)測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁(yè)面加載后一秒左右以?xún)?。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩?hù)才能看到真實(shí)內容。所以上述指標并不能真的反饋用戶(hù)感受到的性能問(wèn)題
我已經(jīng)把這個(gè)應用部署到了 站點(diǎn)上,可以在線(xiàn)訪(fǎng)問(wèn)。并且可以使用 對它做更詳細的性能檢測,也會(huì )得出和 devtools 相同的結果。webpagetest 是一個(gè)開(kāi)源免費對網(wǎng)站性能進(jìn)行檢測的工具。早在 2012 年還沒(méi)有諸如 FP 一類(lèi)的指標時(shí),它獨創(chuàng )的 Speed Index 指標就能夠衡量用戶(hù)體驗。
總的來(lái)說(shuō)如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛(ài)莫能助。
這只是其中一個(gè)說(shuō)明原生指標不夠準確的例子,可以歸納為后端接口延遲過(guò)長(cháng)。然而還有一種情況是前端渲染時(shí)間過(guò)長(cháng)。例如我們在使用 Handsontable 組件渲染上千行數據表格的時(shí)候,甚至導致了瀏覽器的假死,這種場(chǎng)景對 Paint Timing API 也是免疫的。
那 tti 這個(gè)指標怎么樣?它不是聽(tīng)上去能夠檢測頁(yè)面是否可以交互嗎?它是不是能夠檢測頁(yè)面的假死?
很遺憾依然不行。
如果你有心去查看 tti 這個(gè)指標的定義的話(huà), 你會(huì )發(fā)現 tti 本質(zhì)上是一種算法:
并且目前的原生 API 并不支持 tti 指標,需要通過(guò) polyfill 實(shí)現,按照官方的說(shuō)明,目前并不能適配所有的 web app。
雙向指標
這是知乎創(chuàng )作者中心頁(yè)面的一個(gè)截圖
在這個(gè)頁(yè)面中,知乎每天都會(huì )為你更新過(guò)去七天內文章閱讀數、贊同數、評論數等數據的匯總。上圖中的折線(xiàn)就是閱讀數。
我知道它的用意是想給予創(chuàng )作者數據上的反饋幫助他們更好的輸出內容,但至少對我來(lái)說(shuō)一點(diǎn)用也沒(méi)有。因為我更想知道的是究竟增長(cháng)來(lái)自于哪里,這樣我才能有針對性的輸出帶來(lái)點(diǎn)擊量的內容。但它帶給我的總是匯總數據。
這個(gè)需求對于性能監控也是同樣的成立的,監控的目的主要是為了及時(shí)發(fā)現問(wèn)題,解決問(wèn)題。所以在審視數據的過(guò)程中,我們更關(guān)心的是異常波動(dòng)值發(fā)生在何時(shí)何地,我們也希望數據能給予我這方面的幫助。
當然我們不可能無(wú)中生有的將一組匯總數據還原成細節數據,但在這個(gè)問(wèn)題上我們可以往兩個(gè)方向努力:
在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關(guān)于他理想性能工具應該滿(mǎn)足的四則功能,分別是:
其中的第二三則對于我們選擇指標來(lái)說(shuō)也是成立的,與我在上面的強調的不謀而合
最后再一次強調這里不是對傳統指標的否定。數據帶來(lái)的效果一定是聊勝于無(wú),指標越多越是能精確的描繪出性能畫(huà)像。這里探討的是如何在這些基礎上繼續事半功倍提升我們洞察問(wèn)題的效率。
在選擇衡量指標上的一些建議
上下文驅動(dòng) (Context Driven)
之所以我無(wú)法在這里給你一個(gè)大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴(lài)你的上下文而定。
你也許更熟悉的是上下文驅動(dòng)測試(Context Driven Testing),但在我看來(lái),上下文驅動(dòng)在你選擇性能指標或者工具時(shí)也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:
想象一下如果你把兩句話(huà)中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒(méi)有任何違和感呢?
“上下文驅動(dòng)”初看上去不過(guò)是正反話(huà),但實(shí)際上它是我們提升監測效率的有效出路。指標本身不會(huì )有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務(wù)分析師希望得到的是能直接彰顯業(yè)務(wù)價(jià)值的數據,例如點(diǎn)擊率,彈出率,用戶(hù)轉化;DevOps 同學(xué)他們可能關(guān)心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長(cháng)的狀態(tài)。這種割裂還可以從技術(shù)角度上劃分,有的指標更側重于資源,有的指標更側重于用戶(hù)感受。
指標只是發(fā)現問(wèn)題的一種手段,現在我們有無(wú)數種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問(wèn)題的起點(diǎn):我究竟想衡量什么?我想衡量的物體是否可以通過(guò)已有的指標表達出來(lái)?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話(huà)是否還有其他的選擇?
“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅動(dòng)測試中的第六條原則如是說(shuō)。
追蹤元素
如果說(shuō)“資源加載完畢”這件事不靠譜,“瀏覽器開(kāi)始繪制”也不靠譜的話(huà),我想唯一靠譜的事情就是用戶(hù)的所見(jiàn)所得了。不需要用各種數據來(lái)展示你的頁(yè)面加載有多快,如果用戶(hù)每次都要等待十秒才能看到他想看到的信息,那么這些數字無(wú)非是自欺欺人而已。所以我們不妨可以追蹤用戶(hù)關(guān)注信息所對應元素的出現的時(shí)機。
這不是創(chuàng )新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續,指標的進(jìn)化過(guò)程像一個(gè)不斷收縮過(guò)程中圓圈,在不斷的像用戶(hù)本身靠攏。只不過(guò)出于技術(shù)手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會(huì )被上面例子中的 placeholder 所欺騙。
抱歉我要在這里再次強調一下上下文:我們不能只關(guān)注“元素出現的時(shí)機”,更要從時(shí)間的范疇和從代碼延展上看關(guān)注形成它的原因,這依然需要我們結合問(wèn)題所處的環(huán)境和它的運轉機制而定。舉兩個(gè)例子:
在上圖中,如果 Component D 是向客戶(hù)展示關(guān)鍵信息的關(guān)鍵元素,那么 request 到達 router 的時(shí)間,由 router 渲染出 Component C 的時(shí)間,都會(huì )對 D 元素產(chǎn)生影響;從另一個(gè)維度上看:
腳本以及請求加載的快慢和執行的效率,同樣也會(huì )對元素的出現產(chǎn)生影響。如果你需要對問(wèn)題進(jìn)行診斷,對這些背后工作機制的了解必不可少。
但追蹤元素也存在另一個(gè)問(wèn)題就是它難以大規模的應用。因為它是侵入式的,因為它需要你識別不同頁(yè)面上的不同關(guān)鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類(lèi)工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過(guò)分配統一的 id 或者 class name 的方式來(lái)減少我們的維護成本,但是相比統一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡(jiǎn)單的方法去監控最直接的元素,不要 case by case 的去編寫(xiě)你的監控代碼,不要讓你的實(shí)現代碼被監控代碼束縛住。
讓工具為你所用
你可以在市面上找到各類(lèi)數不勝數號稱(chēng)能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。
例如 site24x7 是一家專(zhuān)業(yè)提供用戶(hù)行為監控解決方案的公司。在它們有關(guān) APM 的幫助頁(yè)面上,開(kāi)宗明義的指出了監控捕獲 SAP(Single Page Application) 性能數據以目前的技術(shù)來(lái)說(shuō)其實(shí)是一項頗具挑戰的工作:
In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using
Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.
所以對于此種類(lèi)型的頁(yè)面,它們捕獲指標也只有:
For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.
但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無(wú)力了。
同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁(yè)面信息:
Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on
User information (for example, Location, network, IP)
Device information (for example, Browser, OS, version, language, model)
Session information
我不認為這些指標和其他平臺提供的相比能帶來(lái)額外的價(jià)值,它能真的給我帶來(lái)多少真正的 “insights”。
另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個(gè)我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。
在這里我首先必須贊頌 Chrome 內置 Performance 工具給我們調教性能帶來(lái)了極大的便利。但我們始終有一些額外的需求無(wú)法滿(mǎn)足。例如我希望能夠在結果呈現中做一些自定義的標記,又或者在 Performance Tab 下展示每一個(gè)請求從 connect 到 resposne 每個(gè)階段的狀態(tài)。
如下圖所示,于是我們跨界的使用了 Jaeger 開(kāi)源工具來(lái)用于自定義指標的收集和展示,可以說(shuō)是將不同緯度的指標以時(shí)間為線(xiàn)索將它們聯(lián)系起來(lái),這樣一來(lái)頁(yè)面加載階段的狀態(tài)并能一覽無(wú)余的盡收眼底。便于定位問(wèn)題的所在。
結束語(yǔ)
我觀(guān)察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監控時(shí)是一個(gè)被“喂”的過(guò)程,即會(huì )慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過(guò)程前置結果后置的關(guān)系,等到我們有需求發(fā)生時(shí)才會(huì )發(fā)現當下的結果并非是我們想要的。多一些思考才會(huì )讓我們的工作少一分浪費。
云原生愛(ài)好者周刊:尋找 Netlify 開(kāi)源替代品
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 71 次瀏覽 ? 2022-05-01 23:16
隨著(zhù)云原生技術(shù)的快速發(fā)展,技術(shù)的不斷迭代,對于日志的采集、處理及轉發(fā)提出了更高的要求。云原生架構下的日志方案相比基于物理機或者是虛擬機場(chǎng)景的日志架構設計存在很大差別。作為 CNCF 的畢業(yè)項目,Fluent Bit 無(wú)疑為解決云環(huán)境中的日志記錄問(wèn)題的首選解決方案之一。但是在 Kubernetes 中安裝部署以及配置 Fluent Bit 都具有一定的門(mén)檻,加大了用戶(hù)的使用成本。
本文從寫(xiě)作對個(gè)人的價(jià)值談到技術(shù)內容的創(chuàng )作選型,再到文章的排版和輔助工具,希望能幫助大家開(kāi)啟自己的技術(shù)內容創(chuàng )作之路。
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標[3]
對于 Prometheus 這種底層的時(shí)間序列數據庫來(lái)說(shuō),規模大了之后,免不了需要一定的手動(dòng)維護,這對于 Prometheus 的性能至關(guān)重要。這篇文章介紹了如何手動(dòng)刪除和丟棄無(wú)用的指標。
云原生動(dòng)態(tài)Harbor v2.5.0 引入 Cosign[4]
成品(Artifact)簽名和簽名驗證是關(guān)鍵的安全功能,允許你驗證成品的完整性。Harbor 通過(guò)與Notary 和 Cosign 的集成支持內容信任。
Harbor v2.5 集成了對 Cosign 的支持,這是一個(gè) OCI 成品簽名和驗證解決方案,是 Sigstore 項目的一部分。
將 Cosign 與 Harbor 結合使用的一個(gè)關(guān)鍵特性是能夠使用 Harbor 的復制功能來(lái)復制簽名及其相關(guān)的已簽名成品。這意味著(zhù),如果一個(gè)復制規則(replication rule)應用于一個(gè)已簽名成品,Harbo 將把復制規則應用于簽名,就像它應用于已簽名成品一樣。
Tanzu 應用平臺 1.1 版本發(fā)布[5]
Tanzu 應用平臺由 VMware 推出,旨在幫助用戶(hù)在任何公有云或本地 Kubernetes 集群上快速構建和部署軟件。Tanzu 應用平臺提供了一套豐富的開(kāi)發(fā)人員工具,并為支持生產(chǎn)的企業(yè)提供了一條預先鋪好的路徑,通過(guò)降低開(kāi)發(fā)人員工具的復雜性來(lái)更快地開(kāi)發(fā)創(chuàng )收應用程序。
1.1 版本提供了大量新功能,使企業(yè)能夠加快實(shí)現價(jià)值的時(shí)間、簡(jiǎn)化用戶(hù)體驗、建立更強大的安全態(tài)勢并保護他們已經(jīng)進(jìn)行的投資。這些領(lǐng)先的能力使企業(yè)能夠:
Kubernetes 1.24 發(fā)布推遲[6]
經(jīng)過(guò)一段時(shí)間的討論,發(fā)布團隊決定將預定的 Kubernetes 1.24 發(fā)布日推遲到 2022 年 5 月 3 日星期二。這比 2022 年 4 月 19 日星期二的原定發(fā)布日期延遲了兩周。
這是阻止發(fā)布 bug 的結果。該 bug 將在最新的 Golang 次要版本 Go 1.18.1 中修復,預計將于今天晚些時(shí)候發(fā)布。由于 Go 發(fā)布的延遲,發(fā)布團隊已采取措施將預定的 Kubernetes 發(fā)布日期延長(cháng)兩周,以便有足夠的時(shí)間進(jìn)行測試和穩定。
更新的時(shí)間表現在是:
4 月 19 日星期二的 1.24.0-rc.0。
4 月 26 日星期二的 1.24.0-rc.1。
1.24.0 于 5 月 3 日星期二正式發(fā)布。
WasmEdge 0.9.1 發(fā)布了!此版本集成了高性能 networking、JavaScript 流式 SSR 和 Fetch API 支持、新的 bindgen 框架、安卓和 OpenHarmony 操作系統支持、擴展的 Kubernetes 支持以及更好的內存管理。
Flagger 添加了網(wǎng)關(guān) API 支持[7]
Flagger 1.19.0 版本帶來(lái)了 Kubernetes Gateway API 的支持。
Flagger 是一個(gè)漸進(jìn)式的交付工具,它為運行在 Kubernetes 上的應用程序自動(dòng)化發(fā)布過(guò)程。它通過(guò)逐步將流量轉移到新版本,同時(shí)測量指標和運行一致性測試,降低了在生產(chǎn)中引入新軟件版本的風(fēng)險。
由于增加了對 Gateway API 的支持,Flagger 現在可以與所有的實(shí)現一起工作,這意味著(zhù)從今天起,這些都是原生支持:Contour, Emissary-Ingress, Google Kubernetes Engine, HAProxy Ingress, HashiCorp Consul, Istio, Kong and Traefik。
Flagger 團隊已經(jīng)使用 v1beta2 網(wǎng)關(guān) API 成功測試了 Contour 和 Istio。從 Flagger v1.19 開(kāi)始,網(wǎng)關(guān) API 是使用 Contour 實(shí)現的端到端測試套件的一部分。
引用鏈接[1]
Coolify:
[2]
Podman Desktop:
[3]
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標:
[4]
Harbor v2.5.0 引入 Cosign:
[5]
Tanzu 應用平臺 1.1 版本發(fā)布:
[6]
Kubernetes 1.24 發(fā)布推遲:
[7]
Flagger 添加了網(wǎng)關(guān) API 支持:
KubeSphere ()是在 Kubernetes 之上構建的開(kāi)源容器混合云,提供全棧的 IT 自動(dòng)化運維的能力,簡(jiǎn)化企業(yè)的 DevOps 工作流。
KubeSphere已被Aqara智能家居、愛(ài)立信、本來(lái)生活、東軟、華云、新浪、三一重工、華夏銀行、四川航空、國藥集團、微眾銀行、杭州數跑科技、紫金保險、去哪兒網(wǎng)、中通、中國人民銀行、中國銀行、中國人保壽險、中國太平保險、中國移動(dòng)、中國聯(lián)通、中國電信、天翼云、中移金科、Radore、ZaloPay等海內外數千家企業(yè)采用。KubeSphere 提供了開(kāi)發(fā)者友好的向導式操作界面和豐富的企業(yè)級功能,包括Kubernetes多云與多集群管理、DevOps(CI/CD)、應用生命周期管理、邊緣計算、微服務(wù)治理(ServiceMesh)、多租戶(hù)管理、可觀(guān)測性、存儲與網(wǎng)絡(luò )管理、GPUsupport等功能,幫助企業(yè)快速構建一個(gè)強大和功能豐富的容器云平臺。
?GitHub:官網(wǎng)(中國站):??微信群:請搜索添加群助手微信號kubesphere企業(yè)服務(wù):e.cloud
查看全部
云原生愛(ài)好者周刊:尋找 Netlify 開(kāi)源替代品
隨著(zhù)云原生技術(shù)的快速發(fā)展,技術(shù)的不斷迭代,對于日志的采集、處理及轉發(fā)提出了更高的要求。云原生架構下的日志方案相比基于物理機或者是虛擬機場(chǎng)景的日志架構設計存在很大差別。作為 CNCF 的畢業(yè)項目,Fluent Bit 無(wú)疑為解決云環(huán)境中的日志記錄問(wèn)題的首選解決方案之一。但是在 Kubernetes 中安裝部署以及配置 Fluent Bit 都具有一定的門(mén)檻,加大了用戶(hù)的使用成本。
本文從寫(xiě)作對個(gè)人的價(jià)值談到技術(shù)內容的創(chuàng )作選型,再到文章的排版和輔助工具,希望能幫助大家開(kāi)啟自己的技術(shù)內容創(chuàng )作之路。
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標[3]
對于 Prometheus 這種底層的時(shí)間序列數據庫來(lái)說(shuō),規模大了之后,免不了需要一定的手動(dòng)維護,這對于 Prometheus 的性能至關(guān)重要。這篇文章介紹了如何手動(dòng)刪除和丟棄無(wú)用的指標。
云原生動(dòng)態(tài)Harbor v2.5.0 引入 Cosign[4]
成品(Artifact)簽名和簽名驗證是關(guān)鍵的安全功能,允許你驗證成品的完整性。Harbor 通過(guò)與Notary 和 Cosign 的集成支持內容信任。
Harbor v2.5 集成了對 Cosign 的支持,這是一個(gè) OCI 成品簽名和驗證解決方案,是 Sigstore 項目的一部分。
將 Cosign 與 Harbor 結合使用的一個(gè)關(guān)鍵特性是能夠使用 Harbor 的復制功能來(lái)復制簽名及其相關(guān)的已簽名成品。這意味著(zhù),如果一個(gè)復制規則(replication rule)應用于一個(gè)已簽名成品,Harbo 將把復制規則應用于簽名,就像它應用于已簽名成品一樣。
Tanzu 應用平臺 1.1 版本發(fā)布[5]
Tanzu 應用平臺由 VMware 推出,旨在幫助用戶(hù)在任何公有云或本地 Kubernetes 集群上快速構建和部署軟件。Tanzu 應用平臺提供了一套豐富的開(kāi)發(fā)人員工具,并為支持生產(chǎn)的企業(yè)提供了一條預先鋪好的路徑,通過(guò)降低開(kāi)發(fā)人員工具的復雜性來(lái)更快地開(kāi)發(fā)創(chuàng )收應用程序。
1.1 版本提供了大量新功能,使企業(yè)能夠加快實(shí)現價(jià)值的時(shí)間、簡(jiǎn)化用戶(hù)體驗、建立更強大的安全態(tài)勢并保護他們已經(jīng)進(jìn)行的投資。這些領(lǐng)先的能力使企業(yè)能夠:
Kubernetes 1.24 發(fā)布推遲[6]
經(jīng)過(guò)一段時(shí)間的討論,發(fā)布團隊決定將預定的 Kubernetes 1.24 發(fā)布日推遲到 2022 年 5 月 3 日星期二。這比 2022 年 4 月 19 日星期二的原定發(fā)布日期延遲了兩周。
這是阻止發(fā)布 bug 的結果。該 bug 將在最新的 Golang 次要版本 Go 1.18.1 中修復,預計將于今天晚些時(shí)候發(fā)布。由于 Go 發(fā)布的延遲,發(fā)布團隊已采取措施將預定的 Kubernetes 發(fā)布日期延長(cháng)兩周,以便有足夠的時(shí)間進(jìn)行測試和穩定。
更新的時(shí)間表現在是:
4 月 19 日星期二的 1.24.0-rc.0。
4 月 26 日星期二的 1.24.0-rc.1。
1.24.0 于 5 月 3 日星期二正式發(fā)布。
WasmEdge 0.9.1 發(fā)布了!此版本集成了高性能 networking、JavaScript 流式 SSR 和 Fetch API 支持、新的 bindgen 框架、安卓和 OpenHarmony 操作系統支持、擴展的 Kubernetes 支持以及更好的內存管理。
Flagger 添加了網(wǎng)關(guān) API 支持[7]
Flagger 1.19.0 版本帶來(lái)了 Kubernetes Gateway API 的支持。
Flagger 是一個(gè)漸進(jìn)式的交付工具,它為運行在 Kubernetes 上的應用程序自動(dòng)化發(fā)布過(guò)程。它通過(guò)逐步將流量轉移到新版本,同時(shí)測量指標和運行一致性測試,降低了在生產(chǎn)中引入新軟件版本的風(fēng)險。
由于增加了對 Gateway API 的支持,Flagger 現在可以與所有的實(shí)現一起工作,這意味著(zhù)從今天起,這些都是原生支持:Contour, Emissary-Ingress, Google Kubernetes Engine, HAProxy Ingress, HashiCorp Consul, Istio, Kong and Traefik。
Flagger 團隊已經(jīng)使用 v1beta2 網(wǎng)關(guān) API 成功測試了 Contour 和 Istio。從 Flagger v1.19 開(kāi)始,網(wǎng)關(guān) API 是使用 Contour 實(shí)現的端到端測試套件的一部分。
引用鏈接[1]
Coolify:
[2]
Podman Desktop:
[3]
如何手動(dòng)丟棄 Prometheus 中的無(wú)用指標:
[4]
Harbor v2.5.0 引入 Cosign:
[5]
Tanzu 應用平臺 1.1 版本發(fā)布:
[6]
Kubernetes 1.24 發(fā)布推遲:
[7]
Flagger 添加了網(wǎng)關(guān) API 支持:
KubeSphere ()是在 Kubernetes 之上構建的開(kāi)源容器混合云,提供全棧的 IT 自動(dòng)化運維的能力,簡(jiǎn)化企業(yè)的 DevOps 工作流。
KubeSphere已被Aqara智能家居、愛(ài)立信、本來(lái)生活、東軟、華云、新浪、三一重工、華夏銀行、四川航空、國藥集團、微眾銀行、杭州數跑科技、紫金保險、去哪兒網(wǎng)、中通、中國人民銀行、中國銀行、中國人保壽險、中國太平保險、中國移動(dòng)、中國聯(lián)通、中國電信、天翼云、中移金科、Radore、ZaloPay等海內外數千家企業(yè)采用。KubeSphere 提供了開(kāi)發(fā)者友好的向導式操作界面和豐富的企業(yè)級功能,包括Kubernetes多云與多集群管理、DevOps(CI/CD)、應用生命周期管理、邊緣計算、微服務(wù)治理(ServiceMesh)、多租戶(hù)管理、可觀(guān)測性、存儲與網(wǎng)絡(luò )管理、GPUsupport等功能,幫助企業(yè)快速構建一個(gè)強大和功能豐富的容器云平臺。
?GitHub:官網(wǎng)(中國站):??微信群:請搜索添加群助手微信號kubesphere企業(yè)服務(wù):e.cloud
須臾現碼蟲(chóng),一鍵納乾坤——Hubble在微盟微前端中的應用
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 85 次瀏覽 ? 2022-04-29 20:30
通過(guò)Hubble的使用可以在一定程度上減少測試與研發(fā)在提bug、定位問(wèn)題上的溝通的成本,測試同學(xué)不用大段文字描述,研發(fā)同學(xué)能夠直觀(guān)地通過(guò)回放觀(guān)看bug出現的情況,以及根據接口或者報錯信息快速定位問(wèn)題以及復現bug。四、功能解析1.接入apm為了能記錄到接口請求的記錄,自行實(shí)現了一個(gè)rrweb插件,通過(guò)對瀏覽器原生的xhr 和 fetch api的覆寫(xiě),以實(shí)現請求信息的AOP。鑒于已存在A(yíng)PM系統,所以不對接口請求的請求體和響應體進(jìn)行記錄,只記錄下接口header中的apm trace id,在回放的時(shí)候可以通過(guò)這個(gè)trace id直接跳轉到APM系統中,來(lái)查看請求信息,協(xié)助排查和定位問(wèn)題。2.調試網(wǎng)頁(yè)免登錄Hubble的免登錄功能,是通過(guò)采集cookies中的saasAuth token來(lái)實(shí)現的。在管理頁(yè)面點(diǎn)擊免登錄查看時(shí),會(huì )跳轉到帶hubble特殊查詢(xún)參數的url,然后加載hubble時(shí)根據查詢(xún)參數判斷是免登錄查看模式的話(huà),將url中帶有的token寫(xiě)入到cookies中,然后跳轉到不帶特殊參數的頁(yè)面上,以實(shí)現跳過(guò)登錄環(huán)節完成鑒權。需要在頁(yè)面調用其他接口前完成Hubble的加載與判斷。token有時(shí)效性,可能會(huì )出現失效情況。為了避免非手動(dòng)退出來(lái)切換賬號所產(chǎn)生的混亂,建議打開(kāi)新的無(wú)痕窗口后粘貼免登錄鏈接查看。3.裁剪功能在解決錄制片段過(guò)長(cháng)的角度上,借助歸一化的概念,可以將裁剪到的所需時(shí)間段以外的事件,壓縮到一段比較短的時(shí)間內去播放,這樣就能實(shí)現近似裁剪功能了。
但是這屬于比較取巧的方案,后續會(huì )嘗試直接合并增量數據到全量snapshot數據上,這樣既能減少采集到的數據量,同時(shí)減輕剛開(kāi)始播放時(shí)的處理器計算壓力。4.未捕獲錯誤采集通過(guò)對window.onerror、unrejectionhandler和error事件的監聽(tīng),并將采集到的錯誤信息以自定義事件的形式插入到rrweb的record序列中,在回放時(shí)就可以通過(guò)面板查看到錯誤信息,輔助定位問(wèn)題。五、遇到的問(wèn)題1.樣式泄漏處理在開(kāi)發(fā)使用過(guò)程中,Hubble的瀏覽器端出現了樣式污染的問(wèn)題,除了對自己編寫(xiě)的組件內的過(guò)于普遍的樣式名進(jìn)行更改之外,還需要對整個(gè)Hubble進(jìn)行css的scope化。這里使用了部門(mén)內實(shí)現的postcss插件,在遍歷css rules的時(shí)候(使用postcss的walkRules API),對規則內的所有css選擇器前面,添加了一個(gè)當前包名 .${packageJson.name} 的一個(gè)類(lèi)作為父選擇器,同時(shí)在Hubble掛載的dom上也加上了這個(gè)className。同時(shí),在一些使用了css變量的UI組件庫,有些會(huì )將css變量定義在 :root 上,這是一個(gè)全局的偽類(lèi),如果不進(jìn)行處理的話(huà),css變量會(huì )泄漏并污染到全局。
于是在上述的postcss插件中也加入了:root 到 作用域類(lèi)名替換的規則。2.打包加載優(yōu)化為了優(yōu)化初始化速度(更快進(jìn)入錄制狀態(tài))和防止大體積bundle加載帶來(lái)的阻塞,且后續能支持插件化、sdk可拼裝,打包形式上從iife改為system。這樣在初始加載時(shí)能夠優(yōu)先加載主要功能并運行起來(lái),ui部分進(jìn)行延遲加載;同時(shí)拆解成system形式的包之后,后續可以根據配置來(lái)動(dòng)態(tài)加載功能,預留出擴展能力。六、未來(lái)預計添加的功能1.開(kāi)放接入能力基于systemjs的動(dòng)態(tài)加載腳本的能力,Hubble可以通過(guò)配置來(lái)動(dòng)態(tài)加載插件。后續考慮在這基礎上開(kāi)放出一些api以及自定義插件功能,比如可以使用hubble的addCustomEvent API來(lái)添加自定義事件,或者采集靜態(tài)數據直接上傳到hubble的后端。2.涂鴉評論功能在錄制的記錄上,有時(shí)候需要給錄制到的內容進(jìn)行標注評論以輔助傳遞信息,增強理解?,F計劃在后續添加涂鴉評論功能。涂鴉基于canvas,可以提交面板上編輯,記錄下打標注的地方以及持續時(shí)長(cháng),也考慮添加圖層功能來(lái)支持更復雜的標注能力。七、擴展閱讀Hubble主要是圍繞rrweb 這個(gè)dom錄制框架進(jìn)行開(kāi)發(fā)的。
rrweb是通過(guò)MutationObserver API來(lái)監聽(tīng)頁(yè)面上dom的變動(dòng),以及用戶(hù)輸入的各種操作事件進(jìn)行捕獲采集,然后通過(guò)rrweb的DOM序列化算法將DOM結構json化,以及事件行為的格式化,形成一個(gè)變動(dòng)更新列表,然后在回放的時(shí)候,通過(guò)將序列化的dom數據通過(guò)rebuild,和事件行為的重放,重現在一個(gè)iframe沙盒中,來(lái)實(shí)現頁(yè)面操作的回放。其中,rrweb主要有這些事件類(lèi)型:dom加載完成、加載、全量快照、增量快照、元數據、自定義事件、插件事件。而其中的增量快照則有這些數據來(lái)源:dom Mutation、鼠標鍵盤(pán)滾輪觸摸等操作、窗口resize、輸入框輸入、樣式變動(dòng)等。錄制開(kāi)始后,rrweb會(huì )將每次dom變動(dòng),監聽(tīng)到的事件,自定義觸發(fā)事件等錄制到的數據通過(guò)一個(gè)數組來(lái)保存,每個(gè)事件對應著(zhù)一個(gè)事件對象,其中含有觸發(fā)時(shí)的時(shí)間戳、事件類(lèi)型、內容載體payload等。在rrweb上生成一個(gè)dom的全量快照時(shí),會(huì )給當前的dom元素一個(gè)個(gè)分配一個(gè)id,用來(lái)記錄和追蹤其變化。當增量數據中dom的變動(dòng)要apply到snapshot對應的dom樹(shù)上時(shí),會(huì )根據id查找出目標dom節點(diǎn),將MutationObserver 監聽(tīng)到的dom變化應用到數據模型上。
?。╮rweb維護了一個(gè)node Map,以方便快速查找到節點(diǎn))當在播放器進(jìn)行操作時(shí),比如進(jìn)行時(shí)間跳轉(goto),會(huì )通過(guò)狀態(tài)機和事件管道,先暫停再調用播放。調用播放函數時(shí)傳入了跳轉的timeOffset,這時(shí)會(huì )進(jìn)行如下處理:暫停時(shí)會(huì )記錄播放的最后event,然后再開(kāi)始時(shí),首先會(huì )計算出跳轉后的時(shí)間偏移量,來(lái)定義一個(gè)基準時(shí)間戳(跳轉后的時(shí)間戳)。對于小于基準時(shí)間戳的事件,會(huì )以同步的方式全部apply起來(lái),而剩余的事件則是用定時(shí)器觸發(fā)。同時(shí),會(huì )把基準事件戳與上次播放的最后的event中含有的時(shí)間戳進(jìn)行比對,如果往前跳則清除節點(diǎn)Map數據,以同步方式重新計算;如果是往后跳則將同步計算的結果合并到已有的節點(diǎn)Map上。在定時(shí)器的使用上,由于setInterval會(huì )受到性能等各方面影響,這種事件定時(shí)器在精度上不能滿(mǎn)足需求。于是rrweb使用了requestAnimationFrame的API來(lái)作為定時(shí)器(機制上因為不受到eventloop的影響,精度能達到1ms級別),使用performance.now()來(lái)作為獲取每次觸發(fā)定時(shí)器callback的時(shí)間偏移量(減去初始值),從而準確地觸發(fā)rrweb待播放List中的事件。八、結語(yǔ)不通過(guò)口述或者截圖等方式、而是通過(guò)錄屏的方式進(jìn)行記錄,同時(shí)可以記錄接口等數據,這樣可以在復現前端場(chǎng)景上節省溝通成本、快速定位問(wèn)題,從而提高效率。我們也會(huì )在后續的迭代中,尋找合適的場(chǎng)景落地,嘗試更多方案,助力開(kāi)發(fā)提效。 查看全部
須臾現碼蟲(chóng),一鍵納乾坤——Hubble在微盟微前端中的應用
通過(guò)Hubble的使用可以在一定程度上減少測試與研發(fā)在提bug、定位問(wèn)題上的溝通的成本,測試同學(xué)不用大段文字描述,研發(fā)同學(xué)能夠直觀(guān)地通過(guò)回放觀(guān)看bug出現的情況,以及根據接口或者報錯信息快速定位問(wèn)題以及復現bug。四、功能解析1.接入apm為了能記錄到接口請求的記錄,自行實(shí)現了一個(gè)rrweb插件,通過(guò)對瀏覽器原生的xhr 和 fetch api的覆寫(xiě),以實(shí)現請求信息的AOP。鑒于已存在A(yíng)PM系統,所以不對接口請求的請求體和響應體進(jìn)行記錄,只記錄下接口header中的apm trace id,在回放的時(shí)候可以通過(guò)這個(gè)trace id直接跳轉到APM系統中,來(lái)查看請求信息,協(xié)助排查和定位問(wèn)題。2.調試網(wǎng)頁(yè)免登錄Hubble的免登錄功能,是通過(guò)采集cookies中的saasAuth token來(lái)實(shí)現的。在管理頁(yè)面點(diǎn)擊免登錄查看時(shí),會(huì )跳轉到帶hubble特殊查詢(xún)參數的url,然后加載hubble時(shí)根據查詢(xún)參數判斷是免登錄查看模式的話(huà),將url中帶有的token寫(xiě)入到cookies中,然后跳轉到不帶特殊參數的頁(yè)面上,以實(shí)現跳過(guò)登錄環(huán)節完成鑒權。需要在頁(yè)面調用其他接口前完成Hubble的加載與判斷。token有時(shí)效性,可能會(huì )出現失效情況。為了避免非手動(dòng)退出來(lái)切換賬號所產(chǎn)生的混亂,建議打開(kāi)新的無(wú)痕窗口后粘貼免登錄鏈接查看。3.裁剪功能在解決錄制片段過(guò)長(cháng)的角度上,借助歸一化的概念,可以將裁剪到的所需時(shí)間段以外的事件,壓縮到一段比較短的時(shí)間內去播放,這樣就能實(shí)現近似裁剪功能了。
但是這屬于比較取巧的方案,后續會(huì )嘗試直接合并增量數據到全量snapshot數據上,這樣既能減少采集到的數據量,同時(shí)減輕剛開(kāi)始播放時(shí)的處理器計算壓力。4.未捕獲錯誤采集通過(guò)對window.onerror、unrejectionhandler和error事件的監聽(tīng),并將采集到的錯誤信息以自定義事件的形式插入到rrweb的record序列中,在回放時(shí)就可以通過(guò)面板查看到錯誤信息,輔助定位問(wèn)題。五、遇到的問(wèn)題1.樣式泄漏處理在開(kāi)發(fā)使用過(guò)程中,Hubble的瀏覽器端出現了樣式污染的問(wèn)題,除了對自己編寫(xiě)的組件內的過(guò)于普遍的樣式名進(jìn)行更改之外,還需要對整個(gè)Hubble進(jìn)行css的scope化。這里使用了部門(mén)內實(shí)現的postcss插件,在遍歷css rules的時(shí)候(使用postcss的walkRules API),對規則內的所有css選擇器前面,添加了一個(gè)當前包名 .${packageJson.name} 的一個(gè)類(lèi)作為父選擇器,同時(shí)在Hubble掛載的dom上也加上了這個(gè)className。同時(shí),在一些使用了css變量的UI組件庫,有些會(huì )將css變量定義在 :root 上,這是一個(gè)全局的偽類(lèi),如果不進(jìn)行處理的話(huà),css變量會(huì )泄漏并污染到全局。
于是在上述的postcss插件中也加入了:root 到 作用域類(lèi)名替換的規則。2.打包加載優(yōu)化為了優(yōu)化初始化速度(更快進(jìn)入錄制狀態(tài))和防止大體積bundle加載帶來(lái)的阻塞,且后續能支持插件化、sdk可拼裝,打包形式上從iife改為system。這樣在初始加載時(shí)能夠優(yōu)先加載主要功能并運行起來(lái),ui部分進(jìn)行延遲加載;同時(shí)拆解成system形式的包之后,后續可以根據配置來(lái)動(dòng)態(tài)加載功能,預留出擴展能力。六、未來(lái)預計添加的功能1.開(kāi)放接入能力基于systemjs的動(dòng)態(tài)加載腳本的能力,Hubble可以通過(guò)配置來(lái)動(dòng)態(tài)加載插件。后續考慮在這基礎上開(kāi)放出一些api以及自定義插件功能,比如可以使用hubble的addCustomEvent API來(lái)添加自定義事件,或者采集靜態(tài)數據直接上傳到hubble的后端。2.涂鴉評論功能在錄制的記錄上,有時(shí)候需要給錄制到的內容進(jìn)行標注評論以輔助傳遞信息,增強理解?,F計劃在后續添加涂鴉評論功能。涂鴉基于canvas,可以提交面板上編輯,記錄下打標注的地方以及持續時(shí)長(cháng),也考慮添加圖層功能來(lái)支持更復雜的標注能力。七、擴展閱讀Hubble主要是圍繞rrweb 這個(gè)dom錄制框架進(jìn)行開(kāi)發(fā)的。
rrweb是通過(guò)MutationObserver API來(lái)監聽(tīng)頁(yè)面上dom的變動(dòng),以及用戶(hù)輸入的各種操作事件進(jìn)行捕獲采集,然后通過(guò)rrweb的DOM序列化算法將DOM結構json化,以及事件行為的格式化,形成一個(gè)變動(dòng)更新列表,然后在回放的時(shí)候,通過(guò)將序列化的dom數據通過(guò)rebuild,和事件行為的重放,重現在一個(gè)iframe沙盒中,來(lái)實(shí)現頁(yè)面操作的回放。其中,rrweb主要有這些事件類(lèi)型:dom加載完成、加載、全量快照、增量快照、元數據、自定義事件、插件事件。而其中的增量快照則有這些數據來(lái)源:dom Mutation、鼠標鍵盤(pán)滾輪觸摸等操作、窗口resize、輸入框輸入、樣式變動(dòng)等。錄制開(kāi)始后,rrweb會(huì )將每次dom變動(dòng),監聽(tīng)到的事件,自定義觸發(fā)事件等錄制到的數據通過(guò)一個(gè)數組來(lái)保存,每個(gè)事件對應著(zhù)一個(gè)事件對象,其中含有觸發(fā)時(shí)的時(shí)間戳、事件類(lèi)型、內容載體payload等。在rrweb上生成一個(gè)dom的全量快照時(shí),會(huì )給當前的dom元素一個(gè)個(gè)分配一個(gè)id,用來(lái)記錄和追蹤其變化。當增量數據中dom的變動(dòng)要apply到snapshot對應的dom樹(shù)上時(shí),會(huì )根據id查找出目標dom節點(diǎn),將MutationObserver 監聽(tīng)到的dom變化應用到數據模型上。
?。╮rweb維護了一個(gè)node Map,以方便快速查找到節點(diǎn))當在播放器進(jìn)行操作時(shí),比如進(jìn)行時(shí)間跳轉(goto),會(huì )通過(guò)狀態(tài)機和事件管道,先暫停再調用播放。調用播放函數時(shí)傳入了跳轉的timeOffset,這時(shí)會(huì )進(jìn)行如下處理:暫停時(shí)會(huì )記錄播放的最后event,然后再開(kāi)始時(shí),首先會(huì )計算出跳轉后的時(shí)間偏移量,來(lái)定義一個(gè)基準時(shí)間戳(跳轉后的時(shí)間戳)。對于小于基準時(shí)間戳的事件,會(huì )以同步的方式全部apply起來(lái),而剩余的事件則是用定時(shí)器觸發(fā)。同時(shí),會(huì )把基準事件戳與上次播放的最后的event中含有的時(shí)間戳進(jìn)行比對,如果往前跳則清除節點(diǎn)Map數據,以同步方式重新計算;如果是往后跳則將同步計算的結果合并到已有的節點(diǎn)Map上。在定時(shí)器的使用上,由于setInterval會(huì )受到性能等各方面影響,這種事件定時(shí)器在精度上不能滿(mǎn)足需求。于是rrweb使用了requestAnimationFrame的API來(lái)作為定時(shí)器(機制上因為不受到eventloop的影響,精度能達到1ms級別),使用performance.now()來(lái)作為獲取每次觸發(fā)定時(shí)器callback的時(shí)間偏移量(減去初始值),從而準確地觸發(fā)rrweb待播放List中的事件。八、結語(yǔ)不通過(guò)口述或者截圖等方式、而是通過(guò)錄屏的方式進(jìn)行記錄,同時(shí)可以記錄接口等數據,這樣可以在復現前端場(chǎng)景上節省溝通成本、快速定位問(wèn)題,從而提高效率。我們也會(huì )在后續的迭代中,尋找合適的場(chǎng)景落地,嘗試更多方案,助力開(kāi)發(fā)提效。
京東到家自動(dòng)化測試平臺的探索與實(shí)踐
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 75 次瀏覽 ? 2022-04-28 20:45
HTTP服務(wù)的流量復制可以通過(guò)一些代理工具來(lái)實(shí)現。Mitmproxy是一款免費、開(kāi)放的基于Python開(kāi)發(fā)的交互式HTTPS代理工具。它可以用來(lái)捕獲HTTP/HTTPS請求,支持抓包、斷點(diǎn)調試、請求替換、構造請求、模擬弱網(wǎng)等功能。
工作原理如下:
流量復制的實(shí)現具體可以分為以下幾個(gè)步驟:
1. 在電腦或手機端配置Mitmproxy代理服務(wù)器地址,此時(shí)電腦或手機的所有請求都通過(guò)代理服務(wù)器進(jìn)行請求發(fā)出,當請求響應結束后,代理服務(wù)器識別出我們需要攔截的請求,并將請求和響應結果轉發(fā)到我們的自動(dòng)化測試平臺;2. 測試平臺收到代理服務(wù)器轉發(fā)過(guò)來(lái)的請求和響應結果后,會(huì )將數據按照服務(wù)維度進(jìn)行分類(lèi),作為初步的種子用例,持久化到數據庫中;3. 測試人員依據種子用例,轉換成正式的測試用例;
下圖代碼片段是按域名截取數據后,整合平臺所需要的數據和數據格式:
效果展示
2.2 微服務(wù)流量復制
微服務(wù)的流量復制我們是通過(guò)自研客戶(hù)端+配置采集規則來(lái)實(shí)現的。規則配置
交互邏輯
具體實(shí)現步驟如下:
1. 管理端配置服務(wù)的采集規則;2. 客戶(hù)端定時(shí)拉取采集規則;3. 符合采集規則,則將請求入參和出參寫(xiě)入本地文件;4. 客戶(hù)端定期上報流量采集內容到精衛平臺;5. 按照服務(wù),時(shí)間段等維度圈出要回歸的流量用例,生成回歸任務(wù);6. 執行任務(wù),進(jìn)行流量回放;7. 生成流量回放的測試報告;如果之前沒(méi)有維護過(guò)測試用例,也可以通過(guò)開(kāi)啟流量復制功能來(lái)快速的實(shí)現回歸測試;總之,通過(guò)流量復制,將線(xiàn)上的真實(shí)流量引入到灰度測試環(huán)境中進(jìn)行回放,不僅能夠降低人工參與的成本,還可以更加真實(shí)的還原線(xiàn)上場(chǎng)景,使問(wèn)題更加高效客觀(guān)的呈現。
2.3 自動(dòng)生成種子用例
在用例維護過(guò)程當中,如何快速生成一個(gè)正確的樣本示例是我們經(jīng)常面臨的問(wèn)題。為了解決這個(gè)問(wèn)題我們搭建了API接口文檔管理平臺。這個(gè)平臺目的主要是將服務(wù)定義元數據進(jìn)行實(shí)時(shí)的線(xiàn)上化管理,可以隨時(shí)可查看各個(gè)部署版本的接口定義元數據(包括版本、入參、類(lèi)型、格式、示例等)?;诰€(xiàn)上化的接口定義智能生成最新的入參結構,支持微服務(wù)和HTTP等協(xié)議。
在創(chuàng )建用例時(shí),精衛平臺會(huì )拉取服務(wù)的方法和接口定義的相關(guān)信息(入參定義,出參定義,參數示例),解析參數結構,快速生成種子用例,提高新用例的創(chuàng )建效率。
一個(gè)完整的新用例的創(chuàng )建過(guò)程如下:
1.選擇所需的種子用例;
2.調整入參數據;3.補全用例名稱(chēng)、用途等信息;4.設置斷言檢查點(diǎn)等信息;
2.4收益評估
1. 測試人員不需要再進(jìn)行抓包,查日志來(lái)獲取自動(dòng)化測試數據,減少了30%左右用來(lái)創(chuàng )建測試用例的時(shí)間;2. 可以實(shí)時(shí)獲取最新的接口定義元數據,避免了接口定義的不準確性,同時(shí)降低了線(xiàn)下跟研發(fā)獲取接口定義的時(shí)間成本;3. 通過(guò)預設的斷言配置,用例執行結果的正確性檢查借助平臺實(shí)現了自動(dòng)化,大幅度提升了測試效率;三、自動(dòng)化回歸測試精衛平臺的自動(dòng)化回歸測試分為接口自動(dòng)化和流程自動(dòng)化兩個(gè)維度。下面將從這兩個(gè)部分來(lái)介紹。3.1接口自動(dòng)化接口測試是測試系統組件間接口的一種測試方式,主要用于檢測系統內部、系統間的交互點(diǎn),常作為功能測試的基本單元。接口自動(dòng)化就是將一批接口測試用例打包并自動(dòng)執行,以達到節省人力、時(shí)間、資源成本,快速驗證回歸測試服務(wù)正確性,提升測試效率的目的。
3.1.1 設計方案
自動(dòng)化回歸測試依托于持續集成部署平臺,當服務(wù)部署發(fā)布后,借助api接口文檔管理平臺,可以自動(dòng)識別出變更的服務(wù)方法,觸發(fā)自動(dòng)化回歸測試任務(wù),自動(dòng)回歸有代碼變更方法的用例。
3.1.2 執行過(guò)程
1. 用例錄制:接口自動(dòng)化回歸的前提條件是已經(jīng)擁有了測試用例;2. 圈定回歸范圍:同一接口的測試用例按照用途會(huì )分為多組,比如:?jiǎn)卧獪y試用例,回歸測試用例,壓測用例等,圈定出錄制的回歸測試用例;
3. 創(chuàng )建回歸測試任務(wù):支持全量/增量回歸,全量回歸可以進(jìn)行代碼覆蓋率的統計;4. 執行回歸測試任務(wù):當服務(wù)部署后,自動(dòng)觸發(fā)回歸任務(wù)的執行;5. 生成測試報告:任務(wù)用例執行完成后,會(huì )生成一份測試報告,報告中含用例通過(guò)率、代碼覆蓋率、問(wèn)題處理建議等信息;
3.1.3成果收益
接口自動(dòng)化測試減少了測試的執行時(shí)間,降低了回歸測試的實(shí)現門(mén)檻,有效的縮短了產(chǎn)品交付周期,測試人員有更多的時(shí)間和精力投入到產(chǎn)品業(yè)務(wù)本身上面去。3.2 流程自動(dòng)化速搭平臺是京東到家為研發(fā)和測試人員提供的一站式服務(wù)發(fā)布平臺,其核心是通過(guò)我們現有能力(微服務(wù)或http服務(wù))的再次加工(編排),形成新的能力,精衛平臺借助此能力實(shí)現流程自動(dòng)化測試。
3.2.1 設計方案
業(yè)務(wù)架構圖
3.2.2執行過(guò)程
1. 構建步驟:步驟是組成流程的最小執行單元,單個(gè)步驟可以理解為一個(gè)服務(wù);2. 構建流程:把各個(gè)步驟按照業(yè)務(wù)邏輯編排起來(lái)構成流程;
3. 設計流程用例:定義流程入參、設置斷言,創(chuàng )建流程用例;
4. 構建流程任務(wù):按照業(yè)務(wù)圈定要執行的流程用例,以任務(wù)的方式集中執行;
5. 執行流程任務(wù):支持手動(dòng)觸發(fā)和定時(shí)執行等方式,以達到回歸或巡檢的目的;
6. 任務(wù)執行報告:通過(guò)率、代碼覆蓋率、執行結果日志等報告信息,如有異常情況發(fā)送告警通知。
3.2.3 成果收益
1. 已經(jīng)初步完成核心場(chǎng)景的全覆蓋自動(dòng)回歸,在需求迭代效率上有了很大的提升;2. 流程測試與用戶(hù)真實(shí)操作更相近,可以更好的站著(zhù)用戶(hù)的角度驗證產(chǎn)品,利用黃金流程的實(shí)時(shí)巡檢機制,系統在穩定性方面也得到了更好的保障;3.3 回歸機制不同的場(chǎng)景下回歸的機制會(huì )有所不同。比如:3.3.1 一鍵回歸
研發(fā)發(fā)起提測后,針對圈定的服務(wù)和方法可以進(jìn)行一鍵全量/增量的回歸測試。
3.3.2 自動(dòng)回歸自動(dòng)回歸測試的觸發(fā)方式有部署后自動(dòng)回歸,線(xiàn)上的定時(shí)巡檢等場(chǎng)景。1. 日常巡檢平臺支持cron表達式,對多任務(wù)、多用例進(jìn)行定時(shí)執行,并在失敗或者異常后進(jìn)行預警。
2. 應用部署后自動(dòng)回歸支持全量和增量回歸。應用部署后,對API文檔變更的內容進(jìn)行自動(dòng)回歸、生成測試報告,在失敗或者異常時(shí)進(jìn)行預警。四、提升測試質(zhì)量測試質(zhì)量的把控可以從技術(shù)和流程兩個(gè)方面來(lái)考慮,技術(shù)層面主要依賴(lài)于度量指標的提升(用例通過(guò)率,代碼覆蓋率等),流程方面可以通過(guò)設置質(zhì)量門(mén)禁等方式來(lái)保證提測質(zhì)量。4.1 代碼覆蓋率代碼覆蓋率是軟件測試中的一種度量,描述程序中源代碼被測試的比例和程度,所得比例稱(chēng)為代碼覆蓋率。平臺實(shí)現原理:
實(shí)現方式可參照另一篇文章:《》
4.2 設置質(zhì)量門(mén)禁根據測試金字塔模型,我們知道問(wèn)題越早暴露,解決問(wèn)題的成本越低。單元測試的充分性是提高整個(gè)測試效率的關(guān)鍵,設置質(zhì)量門(mén)禁(單元測試通過(guò)率)是保證提測質(zhì)量的重要手段。如何設置質(zhì)量門(mén)禁的呢?我們具體來(lái)看一下整個(gè)提測流程:1. 維護單元測試用例:研發(fā)維護服務(wù)的單元測試用例;2. 圈定提測范圍:研發(fā)選擇要回歸的服務(wù)列表;
3. 生成單元測試任務(wù):根據圈定的服務(wù)列表,篩選出對應的單元你測試用例,生成單元測試任務(wù);4. 執行測試任務(wù):批量執行單元測試用例,達到設置的門(mén)禁標準(通過(guò)率,覆蓋率等)才可進(jìn)入測試環(huán)節;
5. 進(jìn)入測試流程:達到提測標準后,進(jìn)入正式測試環(huán)節,測試人員針對提測服務(wù)和測試重點(diǎn)進(jìn)行針對性的測試。
五、總結及其它5.1總結精衛平臺作為實(shí)現持續集成/發(fā)布(CI/CD)的基礎設施,其目標是保證代碼具備隨時(shí)可以發(fā)布到線(xiàn)上的良好狀態(tài),維持團隊的持續交付能力。另外,平臺在效率提升方面也取得了顯著(zhù)效果:
5.2展望軟件度量是對軟件開(kāi)發(fā)項目、過(guò)程、及其產(chǎn)品進(jìn)行數據定義、收集以及分析的持續性量化過(guò)程。通過(guò)軟件度量可以改進(jìn)軟件開(kāi)發(fā)過(guò)程,促進(jìn)項目成功,開(kāi)發(fā)高質(zhì)量的軟件產(chǎn)品。平臺將繼續對整個(gè)產(chǎn)品交付過(guò)程中的指標數據進(jìn)行整理、挖掘,發(fā)現過(guò)程中存在的問(wèn)題和短板,優(yōu)化和反哺產(chǎn)品交付流程,在效率和穩定性等方面獲得更大的突破。5.3附錄
平臺架構
核心流程
查看全部
京東到家自動(dòng)化測試平臺的探索與實(shí)踐
HTTP服務(wù)的流量復制可以通過(guò)一些代理工具來(lái)實(shí)現。Mitmproxy是一款免費、開(kāi)放的基于Python開(kāi)發(fā)的交互式HTTPS代理工具。它可以用來(lái)捕獲HTTP/HTTPS請求,支持抓包、斷點(diǎn)調試、請求替換、構造請求、模擬弱網(wǎng)等功能。
工作原理如下:
流量復制的實(shí)現具體可以分為以下幾個(gè)步驟:
1. 在電腦或手機端配置Mitmproxy代理服務(wù)器地址,此時(shí)電腦或手機的所有請求都通過(guò)代理服務(wù)器進(jìn)行請求發(fā)出,當請求響應結束后,代理服務(wù)器識別出我們需要攔截的請求,并將請求和響應結果轉發(fā)到我們的自動(dòng)化測試平臺;2. 測試平臺收到代理服務(wù)器轉發(fā)過(guò)來(lái)的請求和響應結果后,會(huì )將數據按照服務(wù)維度進(jìn)行分類(lèi),作為初步的種子用例,持久化到數據庫中;3. 測試人員依據種子用例,轉換成正式的測試用例;
下圖代碼片段是按域名截取數據后,整合平臺所需要的數據和數據格式:
效果展示
2.2 微服務(wù)流量復制
微服務(wù)的流量復制我們是通過(guò)自研客戶(hù)端+配置采集規則來(lái)實(shí)現的。規則配置
交互邏輯
具體實(shí)現步驟如下:
1. 管理端配置服務(wù)的采集規則;2. 客戶(hù)端定時(shí)拉取采集規則;3. 符合采集規則,則將請求入參和出參寫(xiě)入本地文件;4. 客戶(hù)端定期上報流量采集內容到精衛平臺;5. 按照服務(wù),時(shí)間段等維度圈出要回歸的流量用例,生成回歸任務(wù);6. 執行任務(wù),進(jìn)行流量回放;7. 生成流量回放的測試報告;如果之前沒(méi)有維護過(guò)測試用例,也可以通過(guò)開(kāi)啟流量復制功能來(lái)快速的實(shí)現回歸測試;總之,通過(guò)流量復制,將線(xiàn)上的真實(shí)流量引入到灰度測試環(huán)境中進(jìn)行回放,不僅能夠降低人工參與的成本,還可以更加真實(shí)的還原線(xiàn)上場(chǎng)景,使問(wèn)題更加高效客觀(guān)的呈現。
2.3 自動(dòng)生成種子用例
在用例維護過(guò)程當中,如何快速生成一個(gè)正確的樣本示例是我們經(jīng)常面臨的問(wèn)題。為了解決這個(gè)問(wèn)題我們搭建了API接口文檔管理平臺。這個(gè)平臺目的主要是將服務(wù)定義元數據進(jìn)行實(shí)時(shí)的線(xiàn)上化管理,可以隨時(shí)可查看各個(gè)部署版本的接口定義元數據(包括版本、入參、類(lèi)型、格式、示例等)?;诰€(xiàn)上化的接口定義智能生成最新的入參結構,支持微服務(wù)和HTTP等協(xié)議。
在創(chuàng )建用例時(shí),精衛平臺會(huì )拉取服務(wù)的方法和接口定義的相關(guān)信息(入參定義,出參定義,參數示例),解析參數結構,快速生成種子用例,提高新用例的創(chuàng )建效率。
一個(gè)完整的新用例的創(chuàng )建過(guò)程如下:
1.選擇所需的種子用例;
2.調整入參數據;3.補全用例名稱(chēng)、用途等信息;4.設置斷言檢查點(diǎn)等信息;
2.4收益評估
1. 測試人員不需要再進(jìn)行抓包,查日志來(lái)獲取自動(dòng)化測試數據,減少了30%左右用來(lái)創(chuàng )建測試用例的時(shí)間;2. 可以實(shí)時(shí)獲取最新的接口定義元數據,避免了接口定義的不準確性,同時(shí)降低了線(xiàn)下跟研發(fā)獲取接口定義的時(shí)間成本;3. 通過(guò)預設的斷言配置,用例執行結果的正確性檢查借助平臺實(shí)現了自動(dòng)化,大幅度提升了測試效率;三、自動(dòng)化回歸測試精衛平臺的自動(dòng)化回歸測試分為接口自動(dòng)化和流程自動(dòng)化兩個(gè)維度。下面將從這兩個(gè)部分來(lái)介紹。3.1接口自動(dòng)化接口測試是測試系統組件間接口的一種測試方式,主要用于檢測系統內部、系統間的交互點(diǎn),常作為功能測試的基本單元。接口自動(dòng)化就是將一批接口測試用例打包并自動(dòng)執行,以達到節省人力、時(shí)間、資源成本,快速驗證回歸測試服務(wù)正確性,提升測試效率的目的。
3.1.1 設計方案
自動(dòng)化回歸測試依托于持續集成部署平臺,當服務(wù)部署發(fā)布后,借助api接口文檔管理平臺,可以自動(dòng)識別出變更的服務(wù)方法,觸發(fā)自動(dòng)化回歸測試任務(wù),自動(dòng)回歸有代碼變更方法的用例。
3.1.2 執行過(guò)程
1. 用例錄制:接口自動(dòng)化回歸的前提條件是已經(jīng)擁有了測試用例;2. 圈定回歸范圍:同一接口的測試用例按照用途會(huì )分為多組,比如:?jiǎn)卧獪y試用例,回歸測試用例,壓測用例等,圈定出錄制的回歸測試用例;
3. 創(chuàng )建回歸測試任務(wù):支持全量/增量回歸,全量回歸可以進(jìn)行代碼覆蓋率的統計;4. 執行回歸測試任務(wù):當服務(wù)部署后,自動(dòng)觸發(fā)回歸任務(wù)的執行;5. 生成測試報告:任務(wù)用例執行完成后,會(huì )生成一份測試報告,報告中含用例通過(guò)率、代碼覆蓋率、問(wèn)題處理建議等信息;
3.1.3成果收益
接口自動(dòng)化測試減少了測試的執行時(shí)間,降低了回歸測試的實(shí)現門(mén)檻,有效的縮短了產(chǎn)品交付周期,測試人員有更多的時(shí)間和精力投入到產(chǎn)品業(yè)務(wù)本身上面去。3.2 流程自動(dòng)化速搭平臺是京東到家為研發(fā)和測試人員提供的一站式服務(wù)發(fā)布平臺,其核心是通過(guò)我們現有能力(微服務(wù)或http服務(wù))的再次加工(編排),形成新的能力,精衛平臺借助此能力實(shí)現流程自動(dòng)化測試。
3.2.1 設計方案
業(yè)務(wù)架構圖
3.2.2執行過(guò)程
1. 構建步驟:步驟是組成流程的最小執行單元,單個(gè)步驟可以理解為一個(gè)服務(wù);2. 構建流程:把各個(gè)步驟按照業(yè)務(wù)邏輯編排起來(lái)構成流程;
3. 設計流程用例:定義流程入參、設置斷言,創(chuàng )建流程用例;
4. 構建流程任務(wù):按照業(yè)務(wù)圈定要執行的流程用例,以任務(wù)的方式集中執行;
5. 執行流程任務(wù):支持手動(dòng)觸發(fā)和定時(shí)執行等方式,以達到回歸或巡檢的目的;
6. 任務(wù)執行報告:通過(guò)率、代碼覆蓋率、執行結果日志等報告信息,如有異常情況發(fā)送告警通知。
3.2.3 成果收益
1. 已經(jīng)初步完成核心場(chǎng)景的全覆蓋自動(dòng)回歸,在需求迭代效率上有了很大的提升;2. 流程測試與用戶(hù)真實(shí)操作更相近,可以更好的站著(zhù)用戶(hù)的角度驗證產(chǎn)品,利用黃金流程的實(shí)時(shí)巡檢機制,系統在穩定性方面也得到了更好的保障;3.3 回歸機制不同的場(chǎng)景下回歸的機制會(huì )有所不同。比如:3.3.1 一鍵回歸
研發(fā)發(fā)起提測后,針對圈定的服務(wù)和方法可以進(jìn)行一鍵全量/增量的回歸測試。
3.3.2 自動(dòng)回歸自動(dòng)回歸測試的觸發(fā)方式有部署后自動(dòng)回歸,線(xiàn)上的定時(shí)巡檢等場(chǎng)景。1. 日常巡檢平臺支持cron表達式,對多任務(wù)、多用例進(jìn)行定時(shí)執行,并在失敗或者異常后進(jìn)行預警。
2. 應用部署后自動(dòng)回歸支持全量和增量回歸。應用部署后,對API文檔變更的內容進(jìn)行自動(dòng)回歸、生成測試報告,在失敗或者異常時(shí)進(jìn)行預警。四、提升測試質(zhì)量測試質(zhì)量的把控可以從技術(shù)和流程兩個(gè)方面來(lái)考慮,技術(shù)層面主要依賴(lài)于度量指標的提升(用例通過(guò)率,代碼覆蓋率等),流程方面可以通過(guò)設置質(zhì)量門(mén)禁等方式來(lái)保證提測質(zhì)量。4.1 代碼覆蓋率代碼覆蓋率是軟件測試中的一種度量,描述程序中源代碼被測試的比例和程度,所得比例稱(chēng)為代碼覆蓋率。平臺實(shí)現原理:
實(shí)現方式可參照另一篇文章:《》
4.2 設置質(zhì)量門(mén)禁根據測試金字塔模型,我們知道問(wèn)題越早暴露,解決問(wèn)題的成本越低。單元測試的充分性是提高整個(gè)測試效率的關(guān)鍵,設置質(zhì)量門(mén)禁(單元測試通過(guò)率)是保證提測質(zhì)量的重要手段。如何設置質(zhì)量門(mén)禁的呢?我們具體來(lái)看一下整個(gè)提測流程:1. 維護單元測試用例:研發(fā)維護服務(wù)的單元測試用例;2. 圈定提測范圍:研發(fā)選擇要回歸的服務(wù)列表;
3. 生成單元測試任務(wù):根據圈定的服務(wù)列表,篩選出對應的單元你測試用例,生成單元測試任務(wù);4. 執行測試任務(wù):批量執行單元測試用例,達到設置的門(mén)禁標準(通過(guò)率,覆蓋率等)才可進(jìn)入測試環(huán)節;
5. 進(jìn)入測試流程:達到提測標準后,進(jìn)入正式測試環(huán)節,測試人員針對提測服務(wù)和測試重點(diǎn)進(jìn)行針對性的測試。
五、總結及其它5.1總結精衛平臺作為實(shí)現持續集成/發(fā)布(CI/CD)的基礎設施,其目標是保證代碼具備隨時(shí)可以發(fā)布到線(xiàn)上的良好狀態(tài),維持團隊的持續交付能力。另外,平臺在效率提升方面也取得了顯著(zhù)效果:
5.2展望軟件度量是對軟件開(kāi)發(fā)項目、過(guò)程、及其產(chǎn)品進(jìn)行數據定義、收集以及分析的持續性量化過(guò)程。通過(guò)軟件度量可以改進(jìn)軟件開(kāi)發(fā)過(guò)程,促進(jìn)項目成功,開(kāi)發(fā)高質(zhì)量的軟件產(chǎn)品。平臺將繼續對整個(gè)產(chǎn)品交付過(guò)程中的指標數據進(jìn)行整理、挖掘,發(fā)現過(guò)程中存在的問(wèn)題和短板,優(yōu)化和反哺產(chǎn)品交付流程,在效率和穩定性等方面獲得更大的突破。5.3附錄
平臺架構
核心流程
沒(méi)有數據治理思維,數字化轉型就是“白忙活”
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 93 次瀏覽 ? 2022-04-28 13:34
BUT,數據資產(chǎn)能怎么用?為什么無(wú)數據可用,或無(wú)可用數據?怎樣開(kāi)展數據治理?則是一頭霧水。這也導致很多企業(yè)的數字化轉型“白忙活一場(chǎng)”、“從頭再來(lái)”的重要原因。
《報告》依據數據治理及管理組織各層級所關(guān)注的側重點(diǎn),圖譜將工具劃分為三層——戰略層、管理層、操作層。
01/戰略層工具為提供數據質(zhì)量戰略規劃、評估、知道、監控的工具或功能,主要包括五大過(guò)程域:組織與職責、體系與制度、團隊與文化、計劃與監控、成本與評估。1. 組織與職責對數據治理組織及其職責進(jìn)行規劃、管理。
2. 體系與制度對數據治理相關(guān)體系、制度、流程進(jìn)行管理、發(fā)布。
3. 團隊與文化提供數據治理文化發(fā)布、查詢(xún)、學(xué)習培訓等。
4. 計劃與監控
提供數據治理項目管理及監控。
5.成效與評估
對治理成效提供評估依據及評估行為。
02/
管理層工具
為應落實(shí)數據治理戰略而進(jìn)行的數據管理活動(dòng)的工具或功能。主要包括八大過(guò)程域:
數據架構管理、元數據管理、數據標準管理、主數據管理、數據質(zhì)量管理、數據資產(chǎn)管理、數據安全管理、數據生存周期管理。
1.數據架構管理提供數據架構規劃、設計相關(guān)工具及功能,包括數據層次、數據模型和數據流向設計。
2.元數據管理提供統一的企業(yè)元數據存儲庫,支持相關(guān)血緣、影響分析及變更管理的監控。
3.數據標準管理提供統一的指標數據技術(shù)標準、 業(yè)務(wù)標準、管理標準的視圖,具備基本的增刪改查及廢止功能,可進(jìn)行標準符合性檢測。
4.主數據管理提供對企業(yè)主數據、參考數據統一管理, 支持主數據模型定義、數據約束及分發(fā)策略的管理。
5.數據質(zhì)量管理支持對數據質(zhì)量建立質(zhì)量規則,支持數據治理評估,并生成質(zhì)量報告,提供質(zhì)量整改機制。
6.數據資產(chǎn)管理提供企業(yè)以資產(chǎn)價(jià)值視角的數據管理功能,包括資產(chǎn)索引、資產(chǎn)開(kāi)發(fā)、資產(chǎn)服務(wù)等功能。
7.數據安全管理支持對數據進(jìn)行安全分級分類(lèi),定期監督和執行數據安全策略執行情況。
8.數據生存周期管理對數據進(jìn)行生存周期管理,定期監督和檢查數據歸檔和銷(xiāo)毀策略執行情況。
03/
操作層工具
數據操作層主要包括六大過(guò)程域:數據存儲工具、數據采集工具、數據處理工具、數據共享交換工具、AI計算支撐工具、數據分析應用工具。
1.數據存儲工具
基于數據治理戰略及數據架構、數據標準、元數據、質(zhì)量等管理要求,對數據進(jìn)行存儲。包括分布式存儲、傳統關(guān)系型存儲、文件存儲及圖數據庫存儲。
2.數據采集工具基于數據治理戰略要求,完成相關(guān)數據采集工作。支持不同采集方式及頻率,包括實(shí)時(shí)采集、離線(xiàn)采集、報表填報采集、API采集等。
3.數據處理工具基于數據質(zhì)量、標準、數據架構等要求,對數據進(jìn)行加工、轉換、清洗、集中等工作。
4.數據共享交換工具
基于業(yè)務(wù)與之間的數據共享需求,對不同異構數據執行交換或服務(wù)。包括文件、庫表、接口、實(shí)時(shí)流等。
5.Al計算支撐工具將人工智能技術(shù)運用到數據采集、處理、共享、評估、度量等活動(dòng)中。
6.數據分析應用工具通過(guò)數據可視化、報表等工具完成數據治理的報告、診斷分析、監控圖表等的開(kāi)發(fā)制作。
《數據治理工具圖譜研究報告》對上述工具能力圖譜進(jìn)行了詳細解釋?zhuān)皥D外,報告對每層工具能力要素進(jìn)行了更細一步的繪制,并收錄了部分行業(yè)案例采用的工具架構圖。
報告共研制、收錄了26個(gè)圖譜,其中研制了20個(gè)通用工具能力圖譜,收錄了6個(gè)數據治理案例工具能力圖譜。 查看全部
當前這個(gè)時(shí)代,人人都知道數據,或多或少也知道數據是資產(chǎn),治理好了很有用,畢竟企業(yè)數字化轉型的始終離不開(kāi)“數據”,始于數據,最終也是為了數據。
BUT,數據資產(chǎn)能怎么用?為什么無(wú)數據可用,或無(wú)可用數據?怎樣開(kāi)展數據治理?則是一頭霧水。這也導致很多企業(yè)的數字化轉型“白忙活一場(chǎng)”、“從頭再來(lái)”的重要原因。
《報告》依據數據治理及管理組織各層級所關(guān)注的側重點(diǎn),圖譜將工具劃分為三層——戰略層、管理層、操作層。
01/戰略層工具為提供數據質(zhì)量戰略規劃、評估、知道、監控的工具或功能,主要包括五大過(guò)程域:組織與職責、體系與制度、團隊與文化、計劃與監控、成本與評估。1. 組織與職責對數據治理組織及其職責進(jìn)行規劃、管理。
2. 體系與制度對數據治理相關(guān)體系、制度、流程進(jìn)行管理、發(fā)布。
3. 團隊與文化提供數據治理文化發(fā)布、查詢(xún)、學(xué)習培訓等。
4. 計劃與監控
提供數據治理項目管理及監控。
5.成效與評估
對治理成效提供評估依據及評估行為。
02/
管理層工具
為應落實(shí)數據治理戰略而進(jìn)行的數據管理活動(dòng)的工具或功能。主要包括八大過(guò)程域:
數據架構管理、元數據管理、數據標準管理、主數據管理、數據質(zhì)量管理、數據資產(chǎn)管理、數據安全管理、數據生存周期管理。
1.數據架構管理提供數據架構規劃、設計相關(guān)工具及功能,包括數據層次、數據模型和數據流向設計。
2.元數據管理提供統一的企業(yè)元數據存儲庫,支持相關(guān)血緣、影響分析及變更管理的監控。
3.數據標準管理提供統一的指標數據技術(shù)標準、 業(yè)務(wù)標準、管理標準的視圖,具備基本的增刪改查及廢止功能,可進(jìn)行標準符合性檢測。
4.主數據管理提供對企業(yè)主數據、參考數據統一管理, 支持主數據模型定義、數據約束及分發(fā)策略的管理。
5.數據質(zhì)量管理支持對數據質(zhì)量建立質(zhì)量規則,支持數據治理評估,并生成質(zhì)量報告,提供質(zhì)量整改機制。
6.數據資產(chǎn)管理提供企業(yè)以資產(chǎn)價(jià)值視角的數據管理功能,包括資產(chǎn)索引、資產(chǎn)開(kāi)發(fā)、資產(chǎn)服務(wù)等功能。
7.數據安全管理支持對數據進(jìn)行安全分級分類(lèi),定期監督和執行數據安全策略執行情況。
8.數據生存周期管理對數據進(jìn)行生存周期管理,定期監督和檢查數據歸檔和銷(xiāo)毀策略執行情況。
03/
操作層工具
數據操作層主要包括六大過(guò)程域:數據存儲工具、數據采集工具、數據處理工具、數據共享交換工具、AI計算支撐工具、數據分析應用工具。
1.數據存儲工具
基于數據治理戰略及數據架構、數據標準、元數據、質(zhì)量等管理要求,對數據進(jìn)行存儲。包括分布式存儲、傳統關(guān)系型存儲、文件存儲及圖數據庫存儲。
2.數據采集工具基于數據治理戰略要求,完成相關(guān)數據采集工作。支持不同采集方式及頻率,包括實(shí)時(shí)采集、離線(xiàn)采集、報表填報采集、API采集等。
3.數據處理工具基于數據質(zhì)量、標準、數據架構等要求,對數據進(jìn)行加工、轉換、清洗、集中等工作。
4.數據共享交換工具
基于業(yè)務(wù)與之間的數據共享需求,對不同異構數據執行交換或服務(wù)。包括文件、庫表、接口、實(shí)時(shí)流等。
5.Al計算支撐工具將人工智能技術(shù)運用到數據采集、處理、共享、評估、度量等活動(dòng)中。
6.數據分析應用工具通過(guò)數據可視化、報表等工具完成數據治理的報告、診斷分析、監控圖表等的開(kāi)發(fā)制作。
《數據治理工具圖譜研究報告》對上述工具能力圖譜進(jìn)行了詳細解釋?zhuān)皥D外,報告對每層工具能力要素進(jìn)行了更細一步的繪制,并收錄了部分行業(yè)案例采用的工具架構圖。
報告共研制、收錄了26個(gè)圖譜,其中研制了20個(gè)通用工具能力圖譜,收錄了6個(gè)數據治理案例工具能力圖譜。
文章采集api(優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口及解決方案 )
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 201 次瀏覽 ? 2022-04-19 09:28
)
優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口處理采集的數據標題和內容、關(guān)鍵詞、描述等??梢葬槍π缘呐浜蟽?yōu)采云采集的SEO功能和5118智能換詞API,處理原創(chuàng )度數更高的文章。@收錄 和 網(wǎng)站 權重起著(zhù)非常重要的作用。
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺;
詳細使用步驟優(yōu)采云API接口配置創(chuàng )建API處理規則API處理規則使用API??處理結果并發(fā)布優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方案
1. 優(yōu)采云API接口配置
一、API配置入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==點(diǎn)擊【第三方內容API接入】==點(diǎn)擊【第三方API配置管理】==最后點(diǎn)擊【+< @優(yōu)采云API] 創(chuàng )建接口配置;
二、配置API接口信息:
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺。
【API key】是從優(yōu)采云(Puppy AI)后臺獲取對應的API key,填寫(xiě)后記得保存;
2. 創(chuàng )建 API 處理規則
API處理規則,可以通過(guò)調用API接口設置處理哪些字段的內容;
一、API處理規則入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==,點(diǎn)擊【第三方內容API接入】==進(jìn)入【API處理規則管理】頁(yè)面,最后點(diǎn)擊【+添加API處理規則]創(chuàng )建API處理規則;
二、API處理規則配置:
3. API 處理規則使用
API處理規則有兩種使用方式:手動(dòng)執行和自動(dòng)執行:
一、手動(dòng)執行API處理規則:
在采集任務(wù)的【結果數據&發(fā)布】選項卡中,點(diǎn)擊【SEO&API&翻譯等工具】按鈕==>選擇【第三方API執行】欄==>選擇對應的API處理規則= => 執行;
二、自動(dòng)執行API處理規則:
啟用 API 處理的自動(dòng)執行。任務(wù)完成后采集會(huì )自動(dòng)執行API處理。一般配合定時(shí)采集和自動(dòng)發(fā)布功能使用非常方便;
在任務(wù)的【自動(dòng)化:發(fā)布&SEO&翻譯】選項卡【自動(dòng)執行第三方API配置】==勾選【采集,自動(dòng)執行API】選項==選擇要執行的API處理規則= ="選擇API接口處理的數據范圍(一般選擇'待發(fā)布',都將導致所有數據重復執行),最后點(diǎn)擊保存;
4. API 處理結果并發(fā)布
一、查看API接口處理結果:
API接口處理的內容會(huì )保存為一個(gè)新的字段,如:標題處理后的新字段:title_優(yōu)采云,內容處理后的新字段:content_優(yōu)采云,在[Result Data & Publish ]和數據預覽界面可以查看。
二、發(fā)布API接口處理后的內容:
發(fā)布文章前,修改發(fā)布目標的第二步映射字段,重新選擇標題和內容到API接口處理后添加的對應字段title_優(yōu)采云和content_優(yōu)采云;
提示:如果發(fā)布目標中無(wú)法選擇新字段,請在任務(wù)下復制或新建發(fā)布目標,然后在新發(fā)布目標中選擇新字段即可。詳細教程請參考發(fā)布目標中不能選擇的字段;
5. 優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方法
一、API處理規則和SEO規則如何協(xié)同工作?
系統默認對title和content字段進(jìn)行SEO功能,需要修改為SEO規則中的title_優(yōu)采云和content_優(yōu)采云字段;
查看全部
文章采集api(優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口及解決方案
)
優(yōu)采云采集支持調用優(yōu)采云(小狗AI)API接口處理采集的數據標題和內容、關(guān)鍵詞、描述等??梢葬槍π缘呐浜蟽?yōu)采云采集的SEO功能和5118智能換詞API,處理原創(chuàng )度數更高的文章。@收錄 和 網(wǎng)站 權重起著(zhù)非常重要的作用。
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺;
詳細使用步驟優(yōu)采云API接口配置創(chuàng )建API處理規則API處理規則使用API??處理結果并發(fā)布優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方案
1. 優(yōu)采云API接口配置
一、API配置入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==點(diǎn)擊【第三方內容API接入】==點(diǎn)擊【第三方API配置管理】==最后點(diǎn)擊【+< @優(yōu)采云API] 創(chuàng )建接口配置;

二、配置API接口信息:
購買(mǎi)優(yōu)采云(小狗AI)API,建議先咨詢(xún)優(yōu)采云(小狗AI)客服,并告知在優(yōu)采云采集上使用@> 平臺。
【API key】是從優(yōu)采云(Puppy AI)后臺獲取對應的API key,填寫(xiě)后記得保存;


2. 創(chuàng )建 API 處理規則
API處理規則,可以通過(guò)調用API接口設置處理哪些字段的內容;
一、API處理規則入口:
點(diǎn)擊控制臺左側列表中的【第三方服務(wù)配置】==,點(diǎn)擊【第三方內容API接入】==進(jìn)入【API處理規則管理】頁(yè)面,最后點(diǎn)擊【+添加API處理規則]創(chuàng )建API處理規則;
二、API處理規則配置:

3. API 處理規則使用
API處理規則有兩種使用方式:手動(dòng)執行和自動(dòng)執行:
一、手動(dòng)執行API處理規則:
在采集任務(wù)的【結果數據&發(fā)布】選項卡中,點(diǎn)擊【SEO&API&翻譯等工具】按鈕==>選擇【第三方API執行】欄==>選擇對應的API處理規則= => 執行;

二、自動(dòng)執行API處理規則:
啟用 API 處理的自動(dòng)執行。任務(wù)完成后采集會(huì )自動(dòng)執行API處理。一般配合定時(shí)采集和自動(dòng)發(fā)布功能使用非常方便;
在任務(wù)的【自動(dòng)化:發(fā)布&SEO&翻譯】選項卡【自動(dòng)執行第三方API配置】==勾選【采集,自動(dòng)執行API】選項==選擇要執行的API處理規則= ="選擇API接口處理的數據范圍(一般選擇'待發(fā)布',都將導致所有數據重復執行),最后點(diǎn)擊保存;

4. API 處理結果并發(fā)布
一、查看API接口處理結果:
API接口處理的內容會(huì )保存為一個(gè)新的字段,如:標題處理后的新字段:title_優(yōu)采云,內容處理后的新字段:content_優(yōu)采云,在[Result Data & Publish ]和數據預覽界面可以查看。


二、發(fā)布API接口處理后的內容:
發(fā)布文章前,修改發(fā)布目標的第二步映射字段,重新選擇標題和內容到API接口處理后添加的對應字段title_優(yōu)采云和content_優(yōu)采云;
提示:如果發(fā)布目標中無(wú)法選擇新字段,請在任務(wù)下復制或新建發(fā)布目標,然后在新發(fā)布目標中選擇新字段即可。詳細教程請參考發(fā)布目標中不能選擇的字段;

5. 優(yōu)采云-API接口常見(jiàn)問(wèn)題及解決方法
一、API處理規則和SEO規則如何協(xié)同工作?
系統默認對title和content字段進(jìn)行SEO功能,需要修改為SEO規則中的title_優(yōu)采云和content_優(yōu)采云字段;
文章采集api(就是錯誤博客(圖片或視頻亦包括在內)分享)
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 108 次瀏覽 ? 2022-04-19 07:01
此外,偽原創(chuàng )大部分都被同義詞和同義詞所取代?;旧?,市場(chǎng)上沒(méi)有 AI偽原創(chuàng )。如果確實(shí)存在,那么直接給關(guān)鍵詞,剩下的可以自己寫(xiě)。市面上大部分的偽原創(chuàng )提供者都替換了同義詞和同義詞,所以最好不要這樣做。
3、構建文章
使用大量的詞搭建文章,比如10萬(wàn)個(gè)相關(guān)詞做一個(gè)表格文章頁(yè)面,通過(guò)對詞和句子的布局,看起來(lái)沒(méi)有不協(xié)調的感覺(jué)。另請參閱此方法。很多網(wǎng)站都獲得了很大的流量,而bug博客本身也獲得了數萬(wàn)這樣的收錄流量。
二、優(yōu)采云構建文章
優(yōu)采云構建文章 很簡(jiǎn)單,bug 博客為您提供了一切。
1、優(yōu)采云導入模板
下載優(yōu)采云,即優(yōu)采云采集,創(chuàng )建人員列表組,右鍵組,導入準備好的“.ljobx”文件,這是 優(yōu)采云@ 的模板>采集。
2、內容采集規則
導入后,雙擊打開(kāi),直接跳過(guò)“URL采集規則”,直接進(jìn)入“內容采集規則”,那么,我們需要構建標題、頁(yè)面對于原創(chuàng ) 關(guān)鍵詞,頁(yè)面描述、作者、縮略圖、標簽等,都來(lái)自txt文檔,內存中有幾萬(wàn)行數據,所以構建< @原創(chuàng )文章 。當然,這只是一種模式。如果你想有更好的收錄效果,那么你需要考慮如何使用這種模式來(lái)創(chuàng )造更好的內容,或者改變模式來(lái)產(chǎn)生更像原創(chuàng )的內容。
以上是Error Blog()分享的內容為“優(yōu)采云采集三種構建方式原創(chuàng )文章”。謝謝閱讀。更多原創(chuàng )文章搜索“bug blog”。
特別聲明:以上內容(包括圖片或視頻)由自媒體平臺“網(wǎng)易”用戶(hù)上傳發(fā)布。本平臺僅提供信息存儲服務(wù)。 查看全部
文章采集api(就是錯誤博客(圖片或視頻亦包括在內)分享)
此外,偽原創(chuàng )大部分都被同義詞和同義詞所取代?;旧?,市場(chǎng)上沒(méi)有 AI偽原創(chuàng )。如果確實(shí)存在,那么直接給關(guān)鍵詞,剩下的可以自己寫(xiě)。市面上大部分的偽原創(chuàng )提供者都替換了同義詞和同義詞,所以最好不要這樣做。
3、構建文章
使用大量的詞搭建文章,比如10萬(wàn)個(gè)相關(guān)詞做一個(gè)表格文章頁(yè)面,通過(guò)對詞和句子的布局,看起來(lái)沒(méi)有不協(xié)調的感覺(jué)。另請參閱此方法。很多網(wǎng)站都獲得了很大的流量,而bug博客本身也獲得了數萬(wàn)這樣的收錄流量。
二、優(yōu)采云構建文章
優(yōu)采云構建文章 很簡(jiǎn)單,bug 博客為您提供了一切。
1、優(yōu)采云導入模板
下載優(yōu)采云,即優(yōu)采云采集,創(chuàng )建人員列表組,右鍵組,導入準備好的“.ljobx”文件,這是 優(yōu)采云@ 的模板>采集。
2、內容采集規則
導入后,雙擊打開(kāi),直接跳過(guò)“URL采集規則”,直接進(jìn)入“內容采集規則”,那么,我們需要構建標題、頁(yè)面對于原創(chuàng ) 關(guān)鍵詞,頁(yè)面描述、作者、縮略圖、標簽等,都來(lái)自txt文檔,內存中有幾萬(wàn)行數據,所以構建< @原創(chuàng )文章 。當然,這只是一種模式。如果你想有更好的收錄效果,那么你需要考慮如何使用這種模式來(lái)創(chuàng )造更好的內容,或者改變模式來(lái)產(chǎn)生更像原創(chuàng )的內容。
以上是Error Blog()分享的內容為“優(yōu)采云采集三種構建方式原創(chuàng )文章”。謝謝閱讀。更多原創(chuàng )文章搜索“bug blog”。
特別聲明:以上內容(包括圖片或視頻)由自媒體平臺“網(wǎng)易”用戶(hù)上傳發(fā)布。本平臺僅提供信息存儲服務(wù)。
文章采集api( 京東云API分組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲 )
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 136 次瀏覽 ? 2022-04-19 00:42
京東云API分組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲
)
日志服務(wù)
目前,您可以在京東云的API群組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲、日志檢索、智能分析等功能,通過(guò)日志解決業(yè)務(wù)運營(yíng)、業(yè)務(wù)監控、日志分析等問(wèn)題。
入口一:
互聯(lián)網(wǎng)中間件 > API網(wǎng)關(guān) > 開(kāi)放API > API組管理 > 日志服務(wù)
入口二:
管理 > 日志服務(wù)
操作步驟: 第一步:進(jìn)入API組管理頁(yè)面,點(diǎn)擊“Log”按鈕
第二步:在日志集管理模塊中,點(diǎn)擊“創(chuàng )建日志集”按鈕,打開(kāi)創(chuàng )建日志集頁(yè)面。
步驟 3:設置日志集名稱(chēng)、描述(可選)和保存時(shí)間。點(diǎn)擊“確定”按鈕后,彈出提示“日志集創(chuàng )建成功,現在去添加日志主題嗎?”
第四步:點(diǎn)擊“確定”按鈕后,跳轉到日志集詳情,創(chuàng )建日志主題。
第五步:添加日志主題名稱(chēng)后,點(diǎn)擊“確定”按鈕,彈出提示“日志主題創(chuàng )建成功,現在去添加采集配置嗎?”
第六步:點(diǎn)擊“確定”后,進(jìn)入采集配置頁(yè)面。點(diǎn)擊“添加采集配置”進(jìn)入添加采集配置頁(yè)面,在“產(chǎn)品”對應選項中選擇“API網(wǎng)關(guān)”,點(diǎn)擊“確定”按鈕完成配置。第七步:返回日志集管理中的日志主題列表頁(yè)面,點(diǎn)擊日志集ID/名稱(chēng),點(diǎn)擊“預覽”按鈕可以查看日志主題下的最新日志數據。如果需要查詢(xún)日志數據,可以到日志檢索查詢(xún)。
第八步:在日志主題列表中選擇要查看的日志主題,點(diǎn)擊“搜索”按鈕,或者切換到左側菜單的日志搜索模塊,可以進(jìn)行相應的全文搜索或鍵值搜索在日志上:
全文搜索
鍵值檢索
(1)快速搜索
(2)高級搜索
查看全部
文章采集api(
京東云API分組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲
)
日志服務(wù)
目前,您可以在京東云的API群組管理中實(shí)現日志實(shí)時(shí)采集、日志存儲、日志檢索、智能分析等功能,通過(guò)日志解決業(yè)務(wù)運營(yíng)、業(yè)務(wù)監控、日志分析等問(wèn)題。
入口一:
互聯(lián)網(wǎng)中間件 > API網(wǎng)關(guān) > 開(kāi)放API > API組管理 > 日志服務(wù)
入口二:
管理 > 日志服務(wù)
操作步驟: 第一步:進(jìn)入API組管理頁(yè)面,點(diǎn)擊“Log”按鈕

第二步:在日志集管理模塊中,點(diǎn)擊“創(chuàng )建日志集”按鈕,打開(kāi)創(chuàng )建日志集頁(yè)面。

步驟 3:設置日志集名稱(chēng)、描述(可選)和保存時(shí)間。點(diǎn)擊“確定”按鈕后,彈出提示“日志集創(chuàng )建成功,現在去添加日志主題嗎?”


第四步:點(diǎn)擊“確定”按鈕后,跳轉到日志集詳情,創(chuàng )建日志主題。


第五步:添加日志主題名稱(chēng)后,點(diǎn)擊“確定”按鈕,彈出提示“日志主題創(chuàng )建成功,現在去添加采集配置嗎?”

第六步:點(diǎn)擊“確定”后,進(jìn)入采集配置頁(yè)面。點(diǎn)擊“添加采集配置”進(jìn)入添加采集配置頁(yè)面,在“產(chǎn)品”對應選項中選擇“API網(wǎng)關(guān)”,點(diǎn)擊“確定”按鈕完成配置。第七步:返回日志集管理中的日志主題列表頁(yè)面,點(diǎn)擊日志集ID/名稱(chēng),點(diǎn)擊“預覽”按鈕可以查看日志主題下的最新日志數據。如果需要查詢(xún)日志數據,可以到日志檢索查詢(xún)。

第八步:在日志主題列表中選擇要查看的日志主題,點(diǎn)擊“搜索”按鈕,或者切換到左側菜單的日志搜索模塊,可以進(jìn)行相應的全文搜索或鍵值搜索在日志上:
全文搜索

鍵值檢索
(1)快速搜索

(2)高級搜索
文章采集api(搭建一套前端監控平臺需要考慮的幾個(gè)問(wèn)題?|本文)
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 95 次瀏覽 ? 2022-04-18 20:32
隨著(zhù)業(yè)務(wù)的快速發(fā)展,我們越來(lái)越重視對生產(chǎn)環(huán)境問(wèn)題的感知能力。作為離用戶(hù)最近的一層,前端性能是否可靠、穩定、好用在很大程度上決定了用戶(hù)對整個(gè)產(chǎn)品的體驗和感受。因此,前端的監控也不容忽視。
搭建前端監控平臺需要考慮很多方面,比如數據采集、埋藏模式、數據處理分析、告警、監控平臺在具體業(yè)務(wù)中的應用等等。在所有這些環(huán)節中、準確、完整、全面的數據采集是一切的前提,也為用戶(hù)后續的精細化運營(yíng)提供了依據。
前端技術(shù)的飛速發(fā)展給數據帶來(lái)了變化和挑戰采集,傳統的人工管理模式已經(jīng)不能滿(mǎn)足需求。如何讓前端數據采集在新的技術(shù)背景下工作更加完整高效是本文的重點(diǎn)。
前端監控數據采集
在采集數據之前,考慮一下采集什么樣的數據。我們關(guān)注兩類(lèi)數據,一類(lèi)與用戶(hù)體驗相關(guān),如首屏時(shí)間、文件加載時(shí)間、頁(yè)面性能等;另一個(gè)是幫助我們及時(shí)感知產(chǎn)品上線(xiàn)后是否出現異常,比如資源錯誤、API響應時(shí)間等。具體來(lái)說(shuō),我們的前端數據采集主要分為:
路由交換機
Vue、React、Angular等前端技術(shù)的快速發(fā)展,使得單頁(yè)應用流行起來(lái)。我們都知道,傳統的頁(yè)面應用使用一些超鏈接來(lái)實(shí)現頁(yè)面切換和跳轉,而單頁(yè)面應用使用自己的路由系統來(lái)管理各個(gè)前端頁(yè)面切換,比如vue-router、react-router等,只有跳轉時(shí)刷新本地資源,js、css等公共資源只需加載一次,使得傳統的網(wǎng)頁(yè)進(jìn)出方式只有在第一次打開(kāi)時(shí)才會(huì )被記錄。在單頁(yè)應用中切換所有后續路由有兩種方式,一種是Hash,另一種是HTML5推出的History API。
1. 鏈接
href是頁(yè)面初始化的第一個(gè)入口,這里只需要簡(jiǎn)單的報告“進(jìn)入頁(yè)面”事件。
2. 哈希變化
哈希路由的一個(gè)明顯標志是帶有“#”。Hash的優(yōu)點(diǎn)是兼容性更好,但問(wèn)題是URL中的“#”不美觀(guān)。我們主要通過(guò)監聽(tīng) URL 中的 hashchange 來(lái)捕獲具體的 hash 值進(jìn)行檢測。
window.addEventListener('hashchange', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
需要注意的是,如果瀏覽器在新版本的vue-router中支持history,即使模式選擇hash,也會(huì )先選擇history模式。雖然表達式暫時(shí)還是#,但實(shí)際上是模擬出來(lái)的,所以不要以為你在如果模式選擇hash,那肯定是hash。
3. 歷史 API
History利用HTML5 History接口中新增的pushState()和replaceState()方法進(jìn)行路由切換,是目前主流的非刷新切換路由方式。與 hashchange 只能更改 # 后面的代碼片段相比,History API(pushState、replaceState)給了前端完全的自由。
PopState 是瀏覽器返回事件的回調,但是更新路由的 pushState 和 replaceState 沒(méi)有回調事件。因此,URL 更改需要分別在 history.pushState() 和 history.replaceState() 方法中處理。在這里,我們使用類(lèi)似Java的AOP編程思想來(lái)改造pushState和replaceState。
AOP(Aspect-oriented programming)是面向方面的編程,它提倡對同一類(lèi)型的問(wèn)題進(jìn)行統一處理。AOP的核心思想是讓某個(gè)模塊能夠被復用。它采用橫向抽取機制,將功能代碼與業(yè)務(wù)邏輯代碼分離,在不修改源代碼的情況下擴展功能。與封裝相比,隔離更徹底。
下面介紹我們具體的改造方法:
// 第一階段:我們對原生方法進(jìn)行包裝,調用前執行 dispatchEvent 了一個(gè)同樣的事件
function aop (type) {
var source = window.history[type];
return function () {
var event = new Event(type);
event.arguments = arguments;
window.dispatchEvent(event);
var rewrite = source.apply(this, arguments);
return rewrite;
};
}
// 第二階段:將 pushState 和 replaceState 進(jìn)行基于 AOP 思想的代碼注入
window.history.pushState = aop('pushState');
window.history.replaceState = aop('replaceState'); // 更改路由,不會(huì )留下歷史記錄
// 第三階段:捕獲pushState 和 replaceState
window.addEventListener('pushState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.addEventListener('replaceState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.history.pushState的實(shí)際調用關(guān)系如圖:
至此,我們完成了pushState和replaceState的轉換,實(shí)現了路由切換的有效抓包??梢钥闯?,我們在不侵入業(yè)務(wù)代碼的情況下擴展了window.history.pushState,調用時(shí)會(huì )主動(dòng)dispatchEvent一個(gè)pushState。
但是這里我們也可以看到一個(gè)缺點(diǎn),就是如果AOP代理函數出現JS錯誤,會(huì )阻塞后續的調用關(guān)系,從而無(wú)法調用實(shí)際的window.history.pushState。因此,在使用該方法時(shí),需要對AOP代理功能的內容進(jìn)行一次完整的try catch,以防止出現業(yè)務(wù)異常。
*提示:如果要自動(dòng)捕捉頁(yè)面停留時(shí)間,只需在觸發(fā)下一頁(yè)進(jìn)入事件時(shí),將上一頁(yè)的時(shí)間與當前時(shí)間做個(gè)差值即可。這時(shí)候可以上報【離開(kāi)頁(yè)面】事件。
錯誤
在前端項目中,由于 JavaScript 本身是一種弱類(lèi)型語(yǔ)言,再加上瀏覽器環(huán)境的復雜性、網(wǎng)絡(luò )問(wèn)題等,很容易出現錯誤。因此,做好網(wǎng)頁(yè)錯誤監控,不斷優(yōu)化代碼,提高代碼的健壯性是非常重要的。
JsError的捕獲可以幫助我們分析和監控在線(xiàn)問(wèn)題,和我們在Chrome瀏覽器的調試工具Console中看到的一致。
1. 窗口.onerror
我們通常使用 window.onerror 來(lái)捕獲 JS 錯誤的異常信息。有兩種方法可以捕獲 JS 錯誤,window.onerror 和 window.addEventListener('error')。一般不建議使用 addEventListener('error') 來(lái)捕獲 JS 異常,主要是它沒(méi)有堆棧信息,而且還需要區分捕獲的信息,因為它會(huì )捕獲所有的異常信息,包括資源加載錯誤. 等待。
window.onerror = function (msg, url, lineno, colno, stack) {
// 上報 【js錯誤】事件
}
2. 未被抓?。ǔ兄Z)
當 Promise 發(fā)生 JS 錯誤或者業(yè)務(wù)沒(méi)有處理拒絕信息時(shí),會(huì )拋出 unhandledrejection,并且這個(gè)錯誤不會(huì )被 window.onerror 和 window.addEventListener('error') 這個(gè)特殊的窗口捕獲。addEventListener('unhandledrejection') 用于捕獲處理:
window.addEventListener('unhandledrejection', function (e) {
var reg_url = /\(([^)]*)\)/;
var fileMsg = e.reason.stack.split('\n')[1].match(reg_url)[1];
var fileArr = fileMsg.split(':');
var lineno = fileArr[fileArr.length - 2];
var colno = fileArr[fileArr.length - 1];
var url = fileMsg.slice(0, -lno.length - cno.length - 2);}, true);
var msg = e.reason.message;
// 上報 【js錯誤】事件
}
我們注意到unhandledrejection繼承自PromiseRejectionEvent,而PromiseRejectionEvent繼承自Event,所以msg、url、lineno、colno、stack以字符串的形式放在e.reason.stack中,我們需要將上面的參數解析出來(lái)與onerror參數對齊,為后續監測平臺各項指標的統一奠定了基礎。
3. 常見(jiàn)問(wèn)題
如果抓到的msg都是“Script error.”,問(wèn)題是你的JS地址和當前網(wǎng)頁(yè)不在同一個(gè)域下。因為我們經(jīng)常需要對網(wǎng)絡(luò )版的靜態(tài)資源進(jìn)行CDN,會(huì )導致經(jīng)常訪(fǎng)問(wèn)的頁(yè)面和腳本文件來(lái)自不同的域名。這時(shí)候如果不進(jìn)行額外配置,瀏覽器很容易出現“腳本錯誤”。出于安全考慮。我們可以利用當前流行的 Webpack bundler 來(lái)處理此類(lèi)問(wèn)題。
// webpack config 配置
// 處理 html 注入 js 添加跨域標識
plugins: [
new HtmlWebpackPlugin({
filename: 'html/index.html',
template: HTML_PATH,
attributes: {
crossorigin: 'anonymous'
}
}),
new HtmlWebpackPluginCrossorigin({
inject: true
})
]
// 處理按需加載的 js 添加跨域標識
output: {
crossOriginLoading: true
}
大多數場(chǎng)景下,生產(chǎn)環(huán)境中的代碼都是壓縮合并的,這使得我們抓到的錯誤很難映射到具體的源碼中,給我們解決問(wèn)題帶來(lái)了很大的麻煩。這里有兩個(gè)解決方案。想法。
在生產(chǎn)環(huán)境中,我們需要添加sourceMap的配置,這樣會(huì )帶來(lái)安全隱患,因為這樣外網(wǎng)可以通過(guò)sourceMap進(jìn)行source map的映射。為了降低風(fēng)險,我們可以做到以下幾點(diǎn):
此時(shí),我們已經(jīng)有了 .map 文件。接下來(lái)我們需要做的就是通過(guò)捕獲的lineno、colno、url調用mozilla/source-map庫進(jìn)行源碼映射,然后就可以得到真正的源碼錯誤信息了。
表現
性能指標的獲取比較簡(jiǎn)單,在onload之后讀取window.performance就可以了,里面收錄了性能、內存等信息。這部分內容在很多現有的文章中都有介紹。由于篇幅所限,本文不再過(guò)多展開(kāi)。稍后,我們將在相關(guān)主題文章中進(jìn)行相關(guān)討論。感興趣的朋友可以添加“馬蜂窩技術(shù)”公眾號繼續關(guān)注。
資源錯誤
首先,我們需要明確資源錯誤捕獲的使用場(chǎng)景,更多的是感知DNS劫持和CDN節點(diǎn)異常等,具體方法如下:
window.addEventListener('error', function (e) {
var target = e.target || e.srcElement;
if (target instanceof HTMLScriptElement) {
// 上報 【資源錯誤】事件
}
}, true)
這只是一個(gè)基本的演示。在實(shí)際環(huán)境中,我們會(huì )關(guān)心更多的Element錯誤,比如css、img、woff等,大家可以根據不同的場(chǎng)景添加。
*資源錯誤的使用場(chǎng)景更多地依賴(lài)于其他維度,例如:地區、運營(yíng)商等,我們將在后面的頁(yè)面中詳細解釋。
API
在市面上的主流框架(如axios、jQuery.ajax等)中,基本上所有的API請求都是基于xmlHttpRequest或者fetch,所以捕獲全局接口錯誤的方式就是封裝xmlHttpRequest或者fetch。在這里,我們的SDK還是使用了上面提到的AOP思想來(lái)攔截API。 查看全部
文章采集api(搭建一套前端監控平臺需要考慮的幾個(gè)問(wèn)題?|本文)
隨著(zhù)業(yè)務(wù)的快速發(fā)展,我們越來(lái)越重視對生產(chǎn)環(huán)境問(wèn)題的感知能力。作為離用戶(hù)最近的一層,前端性能是否可靠、穩定、好用在很大程度上決定了用戶(hù)對整個(gè)產(chǎn)品的體驗和感受。因此,前端的監控也不容忽視。
搭建前端監控平臺需要考慮很多方面,比如數據采集、埋藏模式、數據處理分析、告警、監控平臺在具體業(yè)務(wù)中的應用等等。在所有這些環(huán)節中、準確、完整、全面的數據采集是一切的前提,也為用戶(hù)后續的精細化運營(yíng)提供了依據。
前端技術(shù)的飛速發(fā)展給數據帶來(lái)了變化和挑戰采集,傳統的人工管理模式已經(jīng)不能滿(mǎn)足需求。如何讓前端數據采集在新的技術(shù)背景下工作更加完整高效是本文的重點(diǎn)。
前端監控數據采集
在采集數據之前,考慮一下采集什么樣的數據。我們關(guān)注兩類(lèi)數據,一類(lèi)與用戶(hù)體驗相關(guān),如首屏時(shí)間、文件加載時(shí)間、頁(yè)面性能等;另一個(gè)是幫助我們及時(shí)感知產(chǎn)品上線(xiàn)后是否出現異常,比如資源錯誤、API響應時(shí)間等。具體來(lái)說(shuō),我們的前端數據采集主要分為:
路由交換機
Vue、React、Angular等前端技術(shù)的快速發(fā)展,使得單頁(yè)應用流行起來(lái)。我們都知道,傳統的頁(yè)面應用使用一些超鏈接來(lái)實(shí)現頁(yè)面切換和跳轉,而單頁(yè)面應用使用自己的路由系統來(lái)管理各個(gè)前端頁(yè)面切換,比如vue-router、react-router等,只有跳轉時(shí)刷新本地資源,js、css等公共資源只需加載一次,使得傳統的網(wǎng)頁(yè)進(jìn)出方式只有在第一次打開(kāi)時(shí)才會(huì )被記錄。在單頁(yè)應用中切換所有后續路由有兩種方式,一種是Hash,另一種是HTML5推出的History API。
1. 鏈接
href是頁(yè)面初始化的第一個(gè)入口,這里只需要簡(jiǎn)單的報告“進(jìn)入頁(yè)面”事件。
2. 哈希變化
哈希路由的一個(gè)明顯標志是帶有“#”。Hash的優(yōu)點(diǎn)是兼容性更好,但問(wèn)題是URL中的“#”不美觀(guān)。我們主要通過(guò)監聽(tīng) URL 中的 hashchange 來(lái)捕獲具體的 hash 值進(jìn)行檢測。
window.addEventListener('hashchange', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
需要注意的是,如果瀏覽器在新版本的vue-router中支持history,即使模式選擇hash,也會(huì )先選擇history模式。雖然表達式暫時(shí)還是#,但實(shí)際上是模擬出來(lái)的,所以不要以為你在如果模式選擇hash,那肯定是hash。
3. 歷史 API
History利用HTML5 History接口中新增的pushState()和replaceState()方法進(jìn)行路由切換,是目前主流的非刷新切換路由方式。與 hashchange 只能更改 # 后面的代碼片段相比,History API(pushState、replaceState)給了前端完全的自由。
PopState 是瀏覽器返回事件的回調,但是更新路由的 pushState 和 replaceState 沒(méi)有回調事件。因此,URL 更改需要分別在 history.pushState() 和 history.replaceState() 方法中處理。在這里,我們使用類(lèi)似Java的AOP編程思想來(lái)改造pushState和replaceState。
AOP(Aspect-oriented programming)是面向方面的編程,它提倡對同一類(lèi)型的問(wèn)題進(jìn)行統一處理。AOP的核心思想是讓某個(gè)模塊能夠被復用。它采用橫向抽取機制,將功能代碼與業(yè)務(wù)邏輯代碼分離,在不修改源代碼的情況下擴展功能。與封裝相比,隔離更徹底。
下面介紹我們具體的改造方法:
// 第一階段:我們對原生方法進(jìn)行包裝,調用前執行 dispatchEvent 了一個(gè)同樣的事件
function aop (type) {
var source = window.history[type];
return function () {
var event = new Event(type);
event.arguments = arguments;
window.dispatchEvent(event);
var rewrite = source.apply(this, arguments);
return rewrite;
};
}
// 第二階段:將 pushState 和 replaceState 進(jìn)行基于 AOP 思想的代碼注入
window.history.pushState = aop('pushState');
window.history.replaceState = aop('replaceState'); // 更改路由,不會(huì )留下歷史記錄
// 第三階段:捕獲pushState 和 replaceState
window.addEventListener('pushState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.addEventListener('replaceState', function() {
// 上報【進(jìn)入頁(yè)面】事件
}, true)
window.history.pushState的實(shí)際調用關(guān)系如圖:
至此,我們完成了pushState和replaceState的轉換,實(shí)現了路由切換的有效抓包??梢钥闯?,我們在不侵入業(yè)務(wù)代碼的情況下擴展了window.history.pushState,調用時(shí)會(huì )主動(dòng)dispatchEvent一個(gè)pushState。
但是這里我們也可以看到一個(gè)缺點(diǎn),就是如果AOP代理函數出現JS錯誤,會(huì )阻塞后續的調用關(guān)系,從而無(wú)法調用實(shí)際的window.history.pushState。因此,在使用該方法時(shí),需要對AOP代理功能的內容進(jìn)行一次完整的try catch,以防止出現業(yè)務(wù)異常。
*提示:如果要自動(dòng)捕捉頁(yè)面停留時(shí)間,只需在觸發(fā)下一頁(yè)進(jìn)入事件時(shí),將上一頁(yè)的時(shí)間與當前時(shí)間做個(gè)差值即可。這時(shí)候可以上報【離開(kāi)頁(yè)面】事件。
錯誤
在前端項目中,由于 JavaScript 本身是一種弱類(lèi)型語(yǔ)言,再加上瀏覽器環(huán)境的復雜性、網(wǎng)絡(luò )問(wèn)題等,很容易出現錯誤。因此,做好網(wǎng)頁(yè)錯誤監控,不斷優(yōu)化代碼,提高代碼的健壯性是非常重要的。
JsError的捕獲可以幫助我們分析和監控在線(xiàn)問(wèn)題,和我們在Chrome瀏覽器的調試工具Console中看到的一致。
1. 窗口.onerror
我們通常使用 window.onerror 來(lái)捕獲 JS 錯誤的異常信息。有兩種方法可以捕獲 JS 錯誤,window.onerror 和 window.addEventListener('error')。一般不建議使用 addEventListener('error') 來(lái)捕獲 JS 異常,主要是它沒(méi)有堆棧信息,而且還需要區分捕獲的信息,因為它會(huì )捕獲所有的異常信息,包括資源加載錯誤. 等待。
window.onerror = function (msg, url, lineno, colno, stack) {
// 上報 【js錯誤】事件
}
2. 未被抓?。ǔ兄Z)
當 Promise 發(fā)生 JS 錯誤或者業(yè)務(wù)沒(méi)有處理拒絕信息時(shí),會(huì )拋出 unhandledrejection,并且這個(gè)錯誤不會(huì )被 window.onerror 和 window.addEventListener('error') 這個(gè)特殊的窗口捕獲。addEventListener('unhandledrejection') 用于捕獲處理:
window.addEventListener('unhandledrejection', function (e) {
var reg_url = /\(([^)]*)\)/;
var fileMsg = e.reason.stack.split('\n')[1].match(reg_url)[1];
var fileArr = fileMsg.split(':');
var lineno = fileArr[fileArr.length - 2];
var colno = fileArr[fileArr.length - 1];
var url = fileMsg.slice(0, -lno.length - cno.length - 2);}, true);
var msg = e.reason.message;
// 上報 【js錯誤】事件
}
我們注意到unhandledrejection繼承自PromiseRejectionEvent,而PromiseRejectionEvent繼承自Event,所以msg、url、lineno、colno、stack以字符串的形式放在e.reason.stack中,我們需要將上面的參數解析出來(lái)與onerror參數對齊,為后續監測平臺各項指標的統一奠定了基礎。
3. 常見(jiàn)問(wèn)題
如果抓到的msg都是“Script error.”,問(wèn)題是你的JS地址和當前網(wǎng)頁(yè)不在同一個(gè)域下。因為我們經(jīng)常需要對網(wǎng)絡(luò )版的靜態(tài)資源進(jìn)行CDN,會(huì )導致經(jīng)常訪(fǎng)問(wèn)的頁(yè)面和腳本文件來(lái)自不同的域名。這時(shí)候如果不進(jìn)行額外配置,瀏覽器很容易出現“腳本錯誤”。出于安全考慮。我們可以利用當前流行的 Webpack bundler 來(lái)處理此類(lèi)問(wèn)題。
// webpack config 配置
// 處理 html 注入 js 添加跨域標識
plugins: [
new HtmlWebpackPlugin({
filename: 'html/index.html',
template: HTML_PATH,
attributes: {
crossorigin: 'anonymous'
}
}),
new HtmlWebpackPluginCrossorigin({
inject: true
})
]
// 處理按需加載的 js 添加跨域標識
output: {
crossOriginLoading: true
}
大多數場(chǎng)景下,生產(chǎn)環(huán)境中的代碼都是壓縮合并的,這使得我們抓到的錯誤很難映射到具體的源碼中,給我們解決問(wèn)題帶來(lái)了很大的麻煩。這里有兩個(gè)解決方案。想法。
在生產(chǎn)環(huán)境中,我們需要添加sourceMap的配置,這樣會(huì )帶來(lái)安全隱患,因為這樣外網(wǎng)可以通過(guò)sourceMap進(jìn)行source map的映射。為了降低風(fēng)險,我們可以做到以下幾點(diǎn):
此時(shí),我們已經(jīng)有了 .map 文件。接下來(lái)我們需要做的就是通過(guò)捕獲的lineno、colno、url調用mozilla/source-map庫進(jìn)行源碼映射,然后就可以得到真正的源碼錯誤信息了。
表現
性能指標的獲取比較簡(jiǎn)單,在onload之后讀取window.performance就可以了,里面收錄了性能、內存等信息。這部分內容在很多現有的文章中都有介紹。由于篇幅所限,本文不再過(guò)多展開(kāi)。稍后,我們將在相關(guān)主題文章中進(jìn)行相關(guān)討論。感興趣的朋友可以添加“馬蜂窩技術(shù)”公眾號繼續關(guān)注。
資源錯誤
首先,我們需要明確資源錯誤捕獲的使用場(chǎng)景,更多的是感知DNS劫持和CDN節點(diǎn)異常等,具體方法如下:
window.addEventListener('error', function (e) {
var target = e.target || e.srcElement;
if (target instanceof HTMLScriptElement) {
// 上報 【資源錯誤】事件
}
}, true)
這只是一個(gè)基本的演示。在實(shí)際環(huán)境中,我們會(huì )關(guān)心更多的Element錯誤,比如css、img、woff等,大家可以根據不同的場(chǎng)景添加。
*資源錯誤的使用場(chǎng)景更多地依賴(lài)于其他維度,例如:地區、運營(yíng)商等,我們將在后面的頁(yè)面中詳細解釋。
API
在市面上的主流框架(如axios、jQuery.ajax等)中,基本上所有的API請求都是基于xmlHttpRequest或者fetch,所以捕獲全局接口錯誤的方式就是封裝xmlHttpRequest或者fetch。在這里,我們的SDK還是使用了上面提到的AOP思想來(lái)攔截API。


