證碼是爬蟲程序繞不過的坎,有各種各樣的驗證碼擋在前進的道路上,比如本文將要重點介紹的旋轉驗證碼,網上能找到不少關于這種驗證碼的逆向方法,整體思路都是一樣的,首先需要通過深度學習模型識別出圖片的旋轉角度,接下來逆向分析加密旋轉角度的一系列過程的js代碼,根據逆向出的過程構造出對應的參數,模擬驗證碼驗證接口調用實現旋轉驗證碼的識別。
不得不說,獨自搞定這一切相當耗時、耗力,而且還可能無功而返,怪不得逆向會經常伴隨著掉頭發的調侃,即使參照網上大佬們的技術文章,真正實踐起來才發現每走一步都可能有坑,有可能是平臺反爬策略更新導致和原文已不一致,也可能因為內容比較敏感導致關鍵細節被故意隱藏,還可能是技術實力欠缺等等。總之,這種逆向的方法讓很多人倍感無力,也許硬著頭皮研究下去最終可以搞定,但肯定需要花費不少的時間,而時間往往是不夠用的。
這里提出另外一種經過驗證可行的解決方案,那就是直接模擬用戶鼠標操作去拖動滑塊實現旋轉驗證碼識別(其他驗證碼也可以使用這個思路)。簡單分析下下面的旋轉碼操作就可以發現滑塊滑到頭,圖片就旋轉了一圈360°,它們之間是線性關系,可以計算出這個比例關系,一旦確定了圖片的旋轉角度就可以根據這個比例關系換算出滑塊滑動的距離,然后模擬拖動滑塊就完成了旋轉驗證碼的驗證。
這種處理驗證碼的方式完全不需要去逆向分析前端代碼,完全是站在用戶的視角在操作,當然它顯得不夠極客,可能性能也稍差點,但是真的不會掉太多頭發,關鍵是它可以解決問題,不管黑貓白貓,能抓老鼠就是好貓。按照這個思路的話,只需要重點解決下面幾個問題:
這一步的目的是提取旋轉驗證碼圖片數據,用于接下來使用深度學習模型識別旋轉角度。可以通過JavaScript代碼創建canvas畫布并繪制驗證碼圖像的方式來獲取圖片數據,如果你使用selenium、playwright這樣的自動化框架的話,它們都支持直接執行js代碼并獲取返回結果。這里需要注意的地方,一是圖像元素需要設置允許跨域,否則無法獲取到圖片數據,而且設置跨域屬性會觸發重新請求圖片,如果設置跨域后立刻繪制圖像是獲取不到數據的,需要等待響應圖片渲染完成。另外一個就是canvas.toDataURL需要指定圖片格式為png,因為jpeg是不支持透明背景的,使用jpeg格式會導致旋轉角度識別庫識別旋轉角度完全錯誤。
// img_selector表示驗證碼圖片選擇器
var imgelm=document.querySelector(img_selector);
// 設置允許跨域,否則無法獲取圖片數據
// TIP:設置跨域后會觸發重新請求圖片,
// 立刻獲取圖片尺寸結果為全0,需要等待一段時間重新獲取
imgelm.setAttribute("crossOrigin","anonymous");
var canvas=document.createElement('canvas');
var ctx=canvas.getContext('2d');
canvas.width=imgelm.naturalWidth;
canvas.height=imgelm.naturalHeight;
ctx.drawImage(imgelm, 0, 0);
// 注意:jpeg格式不支持透明背景,這里使用png格式
var dataURL=canvas.toDataURL('image/png');
return dataURL;
關于旋轉角度識別,可以使用https://github.com/Starry-OvO/rotate-captcha-crack這個模型,這里通過運行server.py開啟一個web服務,通過調用接口,傳入圖片數據會返回識別出的旋轉角度。
(使用指導參考:https://cloud.tencent.com/developer/article/2418786)
不過,由于百度旋轉驗證碼圖片已經升級,圖片全部使用AI生成,更不易識別,當前的模型識別成功率有點低,不過可以通過增加重試來規避這個問題,如果你對深度學習比較熟悉的話也可以使用它的模型重新訓練最新的驗證碼圖片。
另外,百度除了會出現旋轉驗證碼之外,有時候也會出現其他類型驗證,比如滑塊驗證碼,這種情況就需要同時處理滑塊驗證碼和旋轉驗證碼,思路也是一樣的,至于滑塊驗證碼的識別可以使用ddddocr這個庫(https://gitee.com/fkgeek/ddddocr),官網文檔給出了詳細的使用方法。
不管是滑塊驗證碼還是旋轉驗證碼,識別出了圖片滑塊的距離、旋轉角度之后都可以簡單地通過線性關系得出拖動滑塊的距離,接下來就是模擬滑塊拖動指定距離就可以了,下面的js代碼實現了模擬拖動滑塊的功能。代碼中滑動距離僅給出示例,實際運行時請改為換算后的動態值。
()=> {
// selector:滑塊選擇器 offsetX: 滑動距離
function slide(selector, offsetX) {
// 滑塊定位
let slider=document.querySelector(selector);
// 計算滑塊矩形區域對角坐標
let rect=slider.getBoundingClientRect(),
x0=rect.x || rect.left,
y0=rect.y || rect.top,
x1=x0 + offsetX,
y1=y0;
// 模擬鼠標按下動作
let mousedown=document.createEvent('MouseEvents');
mousedown.initMouseEvent('mousedown', true, true, window, 0, x0, y0, x0, y0, false, false, false, false, 0, null);
slider.dispatchEvent(mousedown);
//模擬鼠標拖動動作,將滑塊移動距離簡單拆分為4個相同距離的動作
let mousemove=document.createEvent('MouseEvents');
mousemove.initMouseEvent('mousemove', true, true, window, 0, x0+offsetX/4, y1, x0+offsetX/4, y1, false, false, false, false, 0, null);
slider.dispatchEvent(mousemove);
mousemove.initMouseEvent('mousemove', true, true, window, 0, x0+offsetX/2, y1, x0+offsetX/2, y1, false, false, false, false, 0, null);
slider.dispatchEvent(mousemove);
mousemove.initMouseEvent('mousemove', true, true, window, 0, x0+3*offsetX/4, y1, x0+3*offsetX/4, y1, false, false, false, false, 0, null);
slider.dispatchEvent(mousemove);
mousemove.initMouseEvent('mousemove', true, true, window, 0, x0+offsetX, y1, x0+offsetX, y1, false, false, false, false, 0, null);
slider.dispatchEvent(mousemove);
// 模擬鼠標釋放動作
let mouseout=document.createEvent('MouseEvents');
mouseout.initMouseEvent('mouseup', true, true, window, 0, x1, y1, x1, y1, false, false, false, false, 0, null);
slider.dispatchEvent(mouseout);
}
// 執行滑塊拖動,以下distance和滑塊選擇器只是示例,根據實際情況進行調整
var distance=200;
slide('div.passMod_slide-btn', distance);
}
最后,展示一下通過上面的思路使用playwright實現的旋轉驗證碼的識別過程,本次出現了兩次驗證碼,第一次是滑塊驗證碼,通過后又出現了旋轉驗證碼,可以發現旋轉驗證碼識別了3次才成功,就是因為模型對于最新的百度旋轉驗證碼圖片角度識別率變差導致的,實現上通過增加重試次數進行規避。經測試,無界面模式也可以正常運行。
參考文獻:
[1] https://cloud.tencent.com/developer/article/2418786
[2] https://github.com/Starry-OvO/rotate-captcha-crack
[3] https://gitee.com/fkgeek/ddddocr
[4] https://blog.csdn.net/m0_58618019/article/details/132918404
網頁設計工作中,我們可以給很多元素添加發光的動畫效果,舉幾個例子,“輸入框”、“文字”、“進度條”等。給這些元素加上的發光特效會讓整個網頁變得更加炫酷。今天陜西優就業小編就為大家搜集整理了8款炫酷的HTML發光動畫,這些都可以用作Web前端開發工作中,可以為你節省很多開發時間。
1.HTML5 Canvas五彩繽紛的3D發光水晶球動畫
這是一款基于HTML5 Canvas的超絢麗發光水晶球動畫,就像是酒吧里的那種水晶球射燈一樣,不停地隨機變換射出光線的顏色,給人一種非常動感的視覺效果。整個水晶球是在Canvas畫布上繪制而成,利用CSS3的相關特性使其能夠出現五彩繽紛的發光動畫,而且可以通過鼠標滾輪來放大縮小這個水晶球,不得不說HTML5真的是非常強大。
2.jQuery/CSS3實現漂亮字體發光特效
今天我們要來分享一款很酷的jQuery/CSS3文字發光特效,首先是加載了谷歌的公共字體庫,因此字體非常特別和漂亮,另外利用了jQuery和CSS3的相關特性,當鼠標滑過文字時,文字將會出現發光的動畫特效,非常漂亮。
3.超絢麗CSS3多色彩發光立方體旋轉動畫
之前我們分享過幾個不錯的CSS3立方體動畫,比如這款HTML5 3D立方體旋轉動畫和HTML5 3D立方體圖片切換動畫。今天要分享的也是一款基于CSS3的3D立方體旋轉動畫,不同的是,這款立方體的每一個面都有不同的色彩,并且會帶有絢麗的發光特效。
4.純CSS3實現發光開關切換按鈕
前段時間我們向大家分享過一款牛奶般剔透的CSS3 3D開關按鈕,效果相當贊。今天我們要來分享一款類似的純CSS3發光開關切換按鈕,它的外觀就像一個電燈的開關,可以左右切換。另外開關上的文字還有發光的特效,整體看上去很有立體感。
5.純CSS3和SVG鼠標滑過燈泡發光特效
這次要分享一款利用純CSS3和SVG實現的燈泡發光效果,我們只需要將鼠標滑過燈泡,整個燈泡就會出現發光發亮的動畫特效,效果相當逼真。CSS3的運用,讓燈泡外圍有一層淡淡的光暈。并且在燈光點亮和熄滅的時候有淡入淡出的效果。
6.HTML5 Canvas發光Loading動畫
之前我們分享過很多基于CSS3的Loading動畫效果,相信大家都很喜歡。今天我們要來分享一款基于HTML5 Canvas的發光Loading加載動畫特效。Loading旋轉圖標是在canvas畫布上繪制的,整個loading動畫是發光3D的視覺效果,HTML5非常強大。
7.CSS3發光Loading加載動畫
今天我們要分享一款與眾不同的CSS3 Loading動畫效果,它是由幾個不同的動畫效果組合而成的,像文字打印效果、發光效果、飛入飛出效果,這幾種效果都非常酷。另外我們可以再回顧一下其他的CSS3 Loading效果:HTML5 Canvas實現超酷Loading動畫、很有個性的CSS3彈跳Loading動畫。
8.純CSS3實現發光動畫按鈕特效
這是一款基于純CSS3的發光按鈕,按鈕發光的顏色是隨機的,這樣一排按鈕就顯得五彩繽紛,非常絢麗。之前我們也介紹過不少樣式很獨特的CSS3按鈕,比如純CSS3 3D開關按鈕、純CSS3實現動感彈性按鈕等,都非常不錯,也有HTML5動畫按鈕,大家可以自己看看。
陜西優就業:http://www.ujiuye.com/shaanxi/
IT學習交流:468910291
源于公眾號前埔寨 ,
作者榮頂
我們想在畫布上畫個基本的簡單形狀的時候,使用 Canvas 不會覺得有什么繁瑣。但當畫布上需要任何形式的互動,繪制復雜的圖形和在特定情況需要改變圖片的時候,使用原生 canvas API 將會變得很困難。
而 Fabric 旨在解決這個問題。
Fabric.js 是一個強大而簡單的 Javascript HTML5 畫布庫 Fabric 在畫布元素之上提供交互式對象模型 Fabric 還具有 SVG-to-canvas(和 canvas-to-SVG)解析器
為了方便,下面我將通過 vue項目 為大家講解如何使用 Fabric
yarn add fabric -S
#or
npm i fabric -S
也可以在 官網 下載最新 js 文件,通過 script 標簽引入
<!-- html -->
<canvas id="canvas" width="500" height="500"></canvas>
Fabric 提供了 7 種基礎形狀:
fabric.Circle (圓)
fabric.Ellipse (橢圓)
fabric.Line (線)
fabric.Polyline (多條線繪制成圖形)
fabric.triangle (三角形)
fabric.Rect (矩形)
fabric.Polygon (多邊形)
//引入fabric
import { fabric } from "fabric";
// 創建一個fabric實例
let canvas=new fabric.Canvas("canvas"); //可以通過鼠標方法縮小,旋轉
// or
// let canvas=new fabric.StaticCanvas("canvas");//沒有鼠標交互的fabric對象
// 創建一個矩形對象
let rect=new fabric.Rect({
left: 200, //距離左邊的距離
top: 200, //距離上邊的距離
fill: "green", //填充的顏色
width: 200, //矩形寬度
height: 200, //矩形高度
});
// 將矩形添加到canvas畫布上
canvas.add(rect);
可以看到界面中填充了一個可以通過鼠標放大縮小且可以旋轉的綠色矩形
通過對象的形式配置元素樣式,非常的方便!
let circle=new fabric.Circle({
left: 0, //距離左邊的距離
top: 0, //距離上邊的距離
fill: "red", //填充的顏色
radius: 50, //圓的半徑
});
// 創建一個三角形對象
let triangle=new fabric.Triangle({
left: 200, //距離左邊的距離
top: 0, //距離上邊的距離
fill: "blue", //填充的顏色
width: 100, //寬度
height: 100, //高度
});
// 將圖形形添加到canvas畫布上
canvas.add(circle, triangle);
我們可以通過以下屬性設置,決定是否可以對相關元素進行交互
rect.set("selectable", false); // 只是禁止這個矩形選中
主要有通過 url 和 img 標簽繪制兩種方式
fabric.Image.fromURL(
//本地圖片需要通過require來引入,require("./xxx.jpeg")
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.thaihot.com.cn%2Fuploadimg%2Fico%2F2021%2F0711%2F1625982535739193.jpg&refer=http%3A%2F%2Fimg.thaihot.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630940858&t=e1d24ff0a7eaeea2ff89cedf656a9374",
(img)=> {
img.scale(0.5);
canvas.add(img);
}
);
//也可以通過標簽繪制
let img=document.getElementById("img");
let image=new fabric.Image(img, {
left: 100,
top: 100,
opacity: 0.8,
});
canvas.add(image);
在此之前我們需要了解幾個參數的含義
customPath.set({
left: 100,
top: 100,
fill: "green",
});
canvas.add(customPath);
"M 0 0 L 300 100 L 170 100 L 70 300 L 20 200 C136.19,2.98,128.98,0,121.32,0 z"
);
可以看到通過路徑繪制,我們可以制作非常復雜的圖形(但是一般用不到,我們一般用它來解析 SVG 后拿到 path 復原圖形)
第一個參數是動畫的屬性,第二個參數是動畫的最終位置,第三個參數是一個可選的對象,指定動畫的細節:持續時間,回調,動效等。
第三個參數主要有
duration 默認為 500ms。可以用來改變動畫的持續時間。
from 允許指定動畫屬性的起始值(如果我們不希望使用當前值)。
onComplete 動畫結束之后的回調。
easing 動效函數。
let rect=new fabric.Rect({
left: 400, //距離左邊的距離
top: 200, //距離上邊的距離
fill: "green", //填充的顏色
width: 200, //寬度
height: 200, //高度
});
rect.animate("left", 100, {
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
});
canvas.add(rect);
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
});
rect.animate("angle", "-=90", {
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
});
默認情況下,動畫使用“easeInSine”動效執行。如果這不是你需要的,fabric 為我們提供了很多內置動畫效果, fabric.util.ease 下有一大堆動效的選項。
常用的有easeOutBounce,easeInCubic,easeOutCubic,easeInElastic,easeOutElastic,easeInBounce 和 easeOutExpo等
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
easing: fabric.util.ease.easeOutBounce,
});
目前 Fabric 為我們提供了以下內置濾鏡
img.scale(0.5);
canvas.add(img);
});
fabric.Image.fromURL(require("./aaa.jpeg"), (img)=> {
img.scale(0.5);
// 添加濾鏡
img.filters.push(new fabric.Image.filters.Grayscale());
// 圖片加載完成之后,應用濾鏡效果
img.applyFilters();
img.set({
left: 300,
top: 250,
});
canvas.add(img);
});
“filters”屬性是一個數組,我們可以用數組方法執行任何所需的操作:移除濾鏡(pop,splice,shift),添加濾鏡(push,unshift,splice),甚至可以組合多個濾鏡。當我們調用 applyFilters 時,“filters”數組中存在的任何濾鏡將逐個應用,所以讓我們嘗試創建一個既色偏又明亮(Brightness)的圖像。
img.scale(0.5);
// 添加濾鏡
img.filters.push(
new fabric.Image.filters.Grayscale(),
new fabric.Image.filters.Sepia(), //色偏
new fabric.Image.filters.Brightness({ brightness: 0.2 }) //亮度
);
// 圖片加載完成之后,應用濾鏡效果
img.applyFilters();
img.set({
left: 300,
top: 250,
});
canvas.add(img);
});
可以看到多個濾鏡的效果疊加顯示了,當然 Fabric 還支持自定義濾鏡,在本篇文章點贊過 500 后我將更新 fabric 高級篇,感謝大家的支持~
無論你是使用十六進制,RGB 或 RGBA 顏色,Fabric 都能處理的很好
new fabric.Color("#aa3123");
new fabric.Color("356333");
new fabric.Color("rgb(100,50,100)");
new fabric.Color("rgba(100, 200, 30, 0.5)");
new fabric.Color('rgb(100,100,100)').toHex(); // "646464"
new fabric.Color('fff').toHex(); // "FFFFFF"
我們還可以用另一種顏色疊加,或將其轉換為灰度版本。
let greenish=new fabric.Color("#5f5");
redish.overlayWith(greenish).toHex(); // "AAAA55"
redish.toGrayscale().toHex(); // "A1A1A1"
Fabric 通過 setGradient 方法支持漸變,在所有對象上定義。調用 setGradient('fill', { ... })就像設置一個對象的“fill”值一樣。
left: 100,
top: 100,
radius: 50
});
circle.setGradient("fill", {
// 漸變開始的位置
x1: 0,
y1: 0,
// 漸變結束的位置
x2: circle.width,
y2: 0,
//漸變的顏色
colorStops: {
// 漸變的范圍(0,0.1,0.3,0.5,0.75,1)0-1之間都可以
0: "red",
0.2: "orange",
0.4: "yellow",
0.6: "green",
0.8: "blue",
1: "purple"
},
});
fabric.Text 對象對于文本,提供了比 canvas 更豐富的功能,包括:
支持多行 Multiline support 不幸的是,原生文本方法忽略了新建一行。
文本對齊 Text alignment 左,中,右。使用多行文本時很有用。
文本背景 Text background 背景也支持文本對齊。
文字裝飾 Text decoration 下劃線,上劃線,貫穿線。
行高 Line Height 在使用多行文本時有用。
字符間距 Char spacing 使文本更緊湊或更間隔。
子范圍 Subranges 將顏色和屬性應用到文本對象的子對象中。
多字節 Multibyte 支持表情符號。
交互式畫布編輯 On canvas editing 可以直接在畫布上鍵入文本。
"大家好~這里是前埔寨\n我是榮頂~\n一個要成為開發王的男人!",
{
left: 0,
top: 200,
fontFamily: "Comic Sans", //字體
fontSize: 50, //字號
fontWeight: 800, //字體粗細,可以使用關鍵字(“normal”,“bold”)或數字(100,200,400,600,800)
shadow: "green 3px 3px 2px", //文字陰影,顏色,水平偏移,垂直偏移和模糊大小。
underline: true, //下劃線
linethrough: true, //刪除線
overline: true, //上劃線
fontStyle: "italic", //字體風格,normal(正常)或italic(斜體)
stroke: "#c3bfbf", //描邊的顏色
strokeWidth: 1, //描邊的寬度
textAlign: "center", //文本對齊方式
lineHeight: 1.5, //行高
textBackgroundColor: "#91A8D0", //文本背景顏色
}
);
canvas.add(text);
fabric 中通過 on 方法來初始化事件,off 方法用來刪除事件。常用的事件有以下
還有一大堆:
鼠標事件:“mouse:down” ,“mouse:move”和“mouse:up...” 選擇相關的事件:“before:selection:cleared”, “selection:created”, 詳細的可以查看 官方文檔
canvas.clear();
let text=new fabric.Text("你點我啦~", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
canvas.on("mouse:up", function(options) {
this.text="你沒點我0.0";
canvas.clear();
let text=new fabric.Text("你沒點我0.0", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
Fabric 允許將偵聽器直接附加到 canvas 畫布中的對象上。
rect.on("selected", function() {
console.log("哦吼~你選擇了我");
});
let circle=new fabric.Circle({ radius: 75, fill: "blue" });
circle.on("selected", function() {
console.log("哈哈哈~你選擇了我");
});
Fabric canvas 的 isDrawingMode 屬性設置為 true 即可實現自由繪制模式.
這樣畫布上的點擊和移動就會被立刻解釋為鉛筆或刷子。
canvas.isDrawingMode=true;
canvas.freeDrawingBrush.color="blue";
canvas.freeDrawingBrush.width=5;
很開心寫下這篇文章,它是我用來總結歸納 fabric 的知識點,并且非常用心的一篇文章,希望這篇文章對你有所幫助。目前 fabric 在國內還不是很火,但是 github 上已經有 19.2k 的 star 了,也算是一個明星項目。我們日常開發經常會用到 canvas,但是它的 api 對于處理復雜的業務邏輯會令人感到非常的勞累,分享這篇文章,希望對大家有所幫助!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。