Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
近項目做暈頭,一個接一個,其中遇到這樣的一個功能,在網頁中高亮關鍵字的實現方法,下面小編把實現代碼及解決方案分享給大家,感興趣的的朋友跟隨小編一起看看吧
最近做項目遇到這樣的一個功能:在網頁中高亮關鍵字。
本以為一個 innerHTML replace 就能實現的簡單操作,卻遇到了許多的問題。本文就記錄這些問題和最終的完美解決辦法, 希望能對有同樣遭遇的小伙伴有所幫助。只對結果感興趣的,忽略過程,直接跳過看結果吧~
常用做法:正則替換
思路:要想高亮元素,那么需要將關鍵字提取出來用標簽包裹,然后對標簽進行樣式調整。使用 innerHTML,或 outHTML, 而不能使用 innerText,outText。
const regex = new RegExp(keyword,"g") element.innerHTML = element.innerHTML.replace(regex,"<b class="a">"+keyword+"</b>") element.classList.add("highlight")
這樣做存在的隱患有如下:
()\ div <div id="parent"> <div class="test">test</div> </div>
關鍵字父節(jié)點 element 通過 class 來進行背景染色處理,對原始DOM有一定程度污染,可能對 element 再次定位造成影響。(作為插件希望盡可能少改變原始DOM)
正則優(yōu)化一:僅處理位于標簽內的元素
var formatKeyword = text.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') // 轉義處理keyword包含的特殊字符,如 /. var finder = new RegExp(">.*?"++".*?<") // 提取位于標簽內的文本,避免誤操作 class、id 等 element.innerHTML = element.innerHTML.replace(finder,function(matched){ return matched.replace(text,"<br>"+text+</br>) })// 對提取的標簽內文本進行關鍵字替換
以能解決大多數問題,但依舊存在的問題是,只要標簽屬性存在類似 < 符號,將會打破匹配規(guī)則導致正則提取內容錯誤, HTML5 dataset 可以自定義任意內容,故這些特殊字符是無法避免的。
<div dataset="p>d">替換</div>
正則優(yōu)化二:清除可能影響的標簽
<div id="keyword">keyword</div> =》將閉合標簽用變量替換 [replaced1]keyword[replaced2]//閉合標簽內 id="keyword" 不會被處理 =》 [replaced1]<b>keyword</b>[replaced2] =》將暫存變量 replaced 替換為原先標簽 <div id="keyword"><b>keyword</b></div>
最重要的,當標簽值中包含 <> 符號時,此方法也不能正確的提取標簽
總之在經過了N多嘗試之后,通過正則都沒能有效的處理各種情況。然后換了個思路,不通過字符串的方式,通過節(jié)點處理。element.childNodes 可以最有效的清理標簽內的干擾信息。
[完美解決方案]通過 DOM 節(jié)點處理
<div id="parent"> keyword 1 <span id="child"> keyword 2 </span> </div>
通過 parent.childNodes 得到所有子節(jié)點。child 節(jié)點可以通過 innerText.replce(keyword,result) 的方式替換得到想要的高亮效果,如下: <span id="child"><b>keyword</b> 2</span> (遞歸處理:當child節(jié)點不含子節(jié)點時進行replace操作)。
但是 keyword 1 是屬于文本節(jié)點,只能修改文本內容,無法增加 HTML,更無法單獨控制其樣式。而文本節(jié)點也不能轉換為普通節(jié)點,這也是最苦惱的事情。
最后~,本文的重點來了,因為這個功能,讓我第一次認真接觸到了文本節(jié)點這個東西。從這里發(fā)現了Text,使用切割文本節(jié)點并替換的方式實現高亮。
源碼以及還原高亮見源碼
const reg = new RegExp(keyword.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')) highlight = function (node,reg){ if (node.nodeType == 3) { //只處理文本節(jié)點 const match = node.data.match(new RegExp(reg)); if (match) { const highlightEl = document.createElement("b"); highlightEl.dataset.highlight="y" const wordNode = node.splitText(match.index) wordNode.splitText(match[0].length); // 切割成前 關鍵詞 后三個Text 節(jié)點 const wordNew = document.createTextNode(wordNode.data); highlightEl.appendChild(wordNew);//highlight 節(jié)點構建成功 wordNode.parentNode.replaceChild(highlightEl, wordNode);// 替換該文本節(jié)點 } } else if (node.nodeType == 1 && node.dataset.highlight!="y" ) { for (var i = 0; i < node.childNodes.length; i++) { highlight(node.childNodes[i], reg); i++ } } }
總結
以上所述是小編給大家介紹的HTML高亮關鍵字的完美解決方案,希望對大家有所幫助,
學習從來不是一個人的事情,要有個相互監(jiān)督的伙伴,想要學習或交流前端問題的小伙伴可以私信“學習”小明加群獲取2019web前端最新入門資料,一起學習,一起成長!
頭條創(chuàng)作挑戰(zhàn)賽#
只需要按照3個步驟,就可以使用ChatGPT代碼解釋器從網站提取數據。
在之前的文章中,我向您展示了如何使用ChatGPT和ChatGPT的插件“Scraper”來抓取網站。這些都是不錯的方法,但也存在一些限制和缺點。
但是,ChatGPT代碼解釋器將網絡抓取提升到了一個不同的層次。
在本文中,我們將探討如何使用ChatGPT代碼解釋器自動化網絡抓取。
要使用ChatGPT代碼解釋器抓取網站,我們需要上傳目標網站的HTML文件。
為此,訪問目標網站并按CTRL+S,并將文件保存為HTML。
假設我想提取Amazon上的電視價格。我只需要訪問Amazon并輸入“TVs”。
然后我按CTRL+S,下面的窗口就會彈出。確保你將文件保存為HTML。
這個HTML文件包含了Amazon網站的所有數據。現在我們需要使用代碼解釋器上傳該文件。
現在我們需要轉到ChatGPT,選擇GPT-4,然后點擊“Code Interpreter”。
代碼解釋器只對ChatGPT Plus訂閱者開放。如果你還沒有啟用它,可以按照此指南中的步驟激活它。
現在你應該在聊天欄中看到一個加號按鈕。點擊它上傳HTML文件。
然后我們需要使用以下提示來提取數據并導出到CSV文件:
從HTML文件中提取產品名稱和價格,將數據放在表格中,并導出到CSV文件。
前面的提示有時就足夠了,但為了使提示更為健壯,我們需要指定我們的數據所在的HTML元素。
為此,訪問目標網站,找到你想提取的數據(在這種情況下,是產品的名稱和價格),然后右鍵點擊它并選擇“檢查”。
開發(fā)者工具將彈出,并高亮顯示包含你希望提取的數據的HTML元素,復制藍色高亮的元素。
這是我復制的元素:
<span class="a-size-medium a-color-base a-text-normal">Introducing Amazon Fire TV 40" 2-Series 1080p HD smart TV, stream live TV without cable</span>
如果你重復這個步驟對價格進行操作,你會得到如下面的元素:
<span class="a-price-whole">189<span class="a-price-decimal">.</span></span>
現在,如果你有過抓取網站的經驗,你可能知道總會有數據缺失,所以我們必須在我們的提示中處理這種情況。
這是我們將要使用的最后的提示:
從HTML文件中提取產品名稱和價格,將數據放在表格中,并導出到CSV文件。
這是一個產品的元素:
<span class="a-size-medium a-color-base a-text-normal">Introducing Amazon Fire TV 40" 2-Series 1080p HD smart TV, stream live TV without cable</span>
這是價格的元素:
<span class="a-price-whole">189<span class="a-price-decimal">.</span></span>
如果產品的價格缺失,請將該價格作為空數據。
在給ChatGPT發(fā)出提示后,我得到了我請求的表格的預覽和下載CSV文件的鏈接。
注意:仔細檢查你的CSV文件。有時,ChatGPT會復制其他行的數據,而不是將空數據作為一個空單元格。如果是這種情況,你需要使用下面的提示:
有些產品(如LG 55-Inch Class UQ7570 Series 4K Smart TV, AI-Powered 4K, Cloud Gaming (55UQ7570PUJ, 2022)沒有價格,您錯誤地將其他產品的價格指定給了它。您能解決這個問題并告訴我哪些產品沒有價格嗎?
那還不是全部!你可以通過提供新的HTML文件來抓取第2、3、4...頁
到目前為止,我們抓取了Amazon的第一頁,但還有其他頁有更多的數據。要抓取所有頁面,我們需要轉到我們想要的頁面,并將其保存為HTML。
然后我們上傳這個新的HTML文件,并使用下面的提示。
這是前面網站的第[n]頁。使用HTML文件提取數據,按照我之前描述的相同步驟。
這是我下載的CSV文件的一部分。
附加內容:使用略有不同的方法抓取Glassdoor
假設我們想抓取Glassdoor上的職位發(fā)布信息。我們將遵循相同的步驟。
首先,我們會訪問Glassdoor,搜索我們想要的職位,然后按CTRL+S將頁面保存為HTML。然后我們檢查想要提取的數據,但現在我們不是復制藍色高亮的整個元素,而是選擇一個屬性。在這種情況下,我會選擇id。
我檢查的元素的id是“job-title-1008760392125”。這可以簡化為“job-title”。如果我們重復對崗位的雇主、地點和薪資的處理,我們會構建下面的提示:
從HTML文件中,查找下列ids的元素并提取其數據
job-employer
job-title
job-location
job-salary
將數據放在表格中,并導出到CSV文件。如果有缺失的數據,將其作為空數據。
現在你可能會收到下面的消息。
這是因為我們通過移除數字來縮短“job-title-1008760392125”,所以id的名稱并不完整。因此我們必須告訴ChatGPT使用正則表達式匹配id名稱的部分:
這些是ids的一部分,使用正則表達式匹配id名稱的部分
然后我們得到了我們的數據!
邊框的設定在web設計中使用率非常的高,border:1px solid #00f;屬于標準的邊線寫法,也可以實現單方向邊線border-left:1px solid red;
1px red solid邊線
(單邊線)左邊線
在CSS標準盒模型中,邊線border是計算在容器總寬度和高度之中的,
總寬高是102*102
瀏覽器中呈現的總寬度和總高度102*102
但隨著web布局要求越來越高,自適應布局應用逐漸廣泛,橫向排布四個div 各占據四分之一的寬度,但如果某一個要有邊線border修飾,因為border是占據寬度的,最終會導致最后一個元素掉下來,因為實際寬度大于了總寬度。
各占據四分之一的寬度
第四個元素掉了下來
outline可以實現和border相同的效果,標準語法也基本相同(outline:1px solid red),也支持outline-style,outline-width,outline-color等分散屬性。
但是outline不占位,不會增加元素的寬高。
outline使用,總寬高不變還是100*100
outline標準寫法
outline缺點:
①不支持圓角 outline-radius:3px;
②不支持單方向outline。
不支持部分屬性
默認的文本框input[type="text"]獲取光標時會有邊線高亮。
文本框高亮獲取光標(新版本之前是藍色邊線)
實際上高亮的部分為outline在起作用
.text:focus{outline: 3px solid #00f;}
使用outline:none,可以去除默認文本框獲取光標時出現的邊線
outline:none
.outline{
/*標準寫法*/
outline:1px solid red;
/*單方向邊線*/
outline-left:4px solid #000;
}
.outline:focus{
/*去除默認邊線*/
outline: none;
}
outline作為一個特殊的屬性存在,在特殊的場景中會產生很棒的效果,靈活使用才能發(fā)揮出最大作用。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。