整合營銷服務商

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

          免費咨詢熱線:

          使用Python進行網(wǎng)頁抓取的介紹

          網(wǎng)頁抓取是一種重要的技術,經(jīng)常在許多不同的環(huán)境中使用,尤其是數(shù)據(jù)科學和數(shù)據(jù)挖掘。 Python在很大程度上被認為是網(wǎng)絡抓取的首選語言,其原因在于Python的內(nèi)嵌電池特性。 使用Python,您可以在大約15分鐘內(nèi)使用不到100行代碼創(chuàng)建一個簡單的抓取腳本。 因此,無論何種用途,網(wǎng)頁抓取都是每個Python程序員必須具備的技能。

          在我們開始動手之前,我們需要退后一步,考慮什么是網(wǎng)頁抓取,什么時候應該使用它,何時避免使用它。

          如您所知,網(wǎng)頁抓取是一種用于從網(wǎng)站自動提取數(shù)據(jù)的技術。 重要的是要理解,網(wǎng)頁抓取是一種從各種來源(通常是網(wǎng)頁)中提取數(shù)據(jù)的粗略技術。 如果網(wǎng)站的開發(fā)人員足夠慷慨地提供API來提取數(shù)據(jù),那么訪問數(shù)據(jù)將是一種更加穩(wěn)定和健壯的方式。 因此,根據(jù)經(jīng)驗,如果網(wǎng)站提供API以編程方式檢索其數(shù)據(jù),請使用它。 如果API不可用,則只能使用網(wǎng)絡抓取。

          請務必遵守有關您使用的每個網(wǎng)站的網(wǎng)頁抓取的任何規(guī)則或限制,因為有些網(wǎng)站不允許這樣做。 有了這個清楚的認識,讓我們直接進入教程。

          在本教程中,我們將抓取http://quotes.toscrape.com/,這是一個列出著名作家名言的網(wǎng)站。

          網(wǎng)頁抓取管道

          我們可以將web-scraping理解為包含3個組件的管道:

          下載:下載HTML網(wǎng)頁

          解析:解析HTML并檢索我們感興趣的數(shù)據(jù)

          存儲:以特定格式將檢索到的數(shù)據(jù)存儲在本地計算機中

          下載HTML

          從網(wǎng)頁中提取任何數(shù)據(jù),從邏輯上講,我們首先要下載它。 我們有兩種方法可以做到這一點:

          1.使用瀏覽器自動化庫

          您可以使用Selenium等瀏覽器自動化庫從網(wǎng)頁下載HTML。 Selenium允許您打開瀏覽器,比方說Chrome,并根據(jù)需要控制它。 您可以在瀏覽器中打開網(wǎng)頁,然后使用Selenium自動獲取該頁面的HTML代碼。

          但是,這種方法有一個很大的缺點 - 它明顯變慢。 原因是運行瀏覽器并在瀏覽器中呈現(xiàn)HTML的開銷。 此方法僅應用于特殊情況 - 我們要抓取的內(nèi)容在瀏覽器中使用JavaScript代碼,或者要求我們單擊按鈕/鏈接以獲取數(shù)據(jù),Selenium可以為我們執(zhí)行此操作。

          2.使用HTTP庫

          與第一種方法不同,HTTP庫(例如Requests模塊或Urllib)允許您發(fā)送HTTP請求,完全不需要打開任何瀏覽器。 這種方法應該始終是首選,因為它比Selenium快得多。

          現(xiàn)在讓我告訴您如何使用Selenium和Requests庫實現(xiàn)管道這個組件:

          使用Requests

          使用以下命令安裝Requests模塊:

          現(xiàn)在您可以在代碼中使用它,如下所示:

          這里,對URL進行HTTP GET請求,這幾乎與下載網(wǎng)頁同義。 然后,我們可以通過訪問requests.get方法返回的結果對象來獲取頁面的HTML源代碼。

          使用Selenium

          您可以通過pip安裝selenium模塊:

          在這里,我們首先創(chuàng)建一個表示瀏覽器的webdriver對象。 這樣做會在運行代碼的計算機上打開Chrome瀏覽器。 然后,通過調(diào)用webdriver對象的get方法,我們可以打開URL。 最后,我們通過訪問webdriver對象的page_source屬性來獲取源代碼。

          在這兩種情況下,URL的HTML源都作為字符串存儲在page變量中。

          解析HTML和提取數(shù)據(jù)

          不必深入計算機科學理論,我們可以將解析定義為分析字符串的過程,以便我們可以理解其內(nèi)容,從而輕松訪問其中的數(shù)據(jù)。

          在Python中,有兩個庫可以幫助我們解析HTML:BeautifulSoup和Lxml。 Lxml是一個比BeautifulSoup更低級的框架,我們可以在BeautifulSoup中使用Lxml作為后端,因此對于簡單的HTML解析,BeautifulSoup將是首選的庫。

          但在我們深入分析之前,我們必須分析網(wǎng)頁的HTML,看看我們想要抓取的數(shù)據(jù)是如何構建和定位的。只有當我們掌握了這些信息時,我們才能從解析的HTML中獲取我們想要的信息。但幸運的是,我們不必在編輯器中打開源代碼,并手動理解每個HTML元素并將其與渲染頁面中的相應數(shù)據(jù)相關聯(lián)。大多數(shù)瀏覽器都提供了一個檢查器,比如Chrome的開發(fā)人員工具,它使我們只需單擊它們即可快速查看任何元素的HTML代碼。

          要在Chrome中執(zhí)行此操作,請在Chrome中打開網(wǎng)頁,然后右鍵單擊要抓取的數(shù)據(jù),然后選擇“檢查”。在Firefox中,此選項稱為Inspect Element - 這是在做相同的事情,但只是名稱不同。

          您會注意到Chrome窗口底部打開了一個窗格,其中包含您單擊的元素的源代碼。 瀏覽一下源代碼,了解我們想要抓取的數(shù)據(jù)是如何在HTML代碼中構建的。

          經(jīng)過一些檢查后你可以理解,http://quotes.toscrape.com/上的每個引用都包含在一個帶有class =“quote”屬性的div中。 在該div中,引用的文本在class =“text”的范圍內(nèi),作者的名稱在class =“author”的小標簽中。 當我們實際解析HTML并提取數(shù)據(jù)時,將需要此信息。

          現(xiàn)在,讓我們開始使用BeautifulSoup解析HTML頁面。 但首先,我們必須安裝它:

          安裝好之后,可以像下面這樣在代碼中調(diào)用:

          首先,我們通過將頁面?zhèn)鬟f給BeautifulSoup類構造函數(shù)來創(chuàng)建頁面的解析版本。 如您所見,我們還將第二個參數(shù)html.parser傳遞給構造函數(shù)。 這是Beautiful Soup將用于解析傳遞給它的字符串的解析器的名稱。 你可以使用我們之前談到過的解析器lxml,因為你已經(jīng)安裝了Lxml庫。

          然后,我們提取包含class =“quote”的頁面中的所有div標簽,因為我們知道這些是包含引用的div。 為此,Beautiful Soup 4提供了find_all功能。 我們將標記名稱和類名稱傳遞給find_all函數(shù),并返回滿足條件的所有標記,即包含引用的標記。

          這里需要注意的一件重要事情是,我們在這里使用樹結構。 變量soup以及引用的每個元素都是樹。 在某種程度上,引用的元素是較大的soup樹的一部分。 無論如何,為避免進入不同的討論,讓我們繼續(xù)。

          我們知道引用的文本是帶有class =“text”的span標記,而作者是帶有class =“author”的小標記。 要從quote元素中提取它們,我們再次使用類似的函數(shù)find。 find函數(shù)使用與find_all函數(shù)相同的參數(shù)。 唯一的區(qū)別是它返回滿足條件的第一個標記,而find_all返回標記列表。 此外,我們希望訪問返回對象的text屬性,該對象包含該標記中包含的文本。

          因此,正如您在代碼中看到的那樣,我們遍歷列表引用的所有元素,并提取引用文本和作者名稱,將它們存儲在名稱為scraped的列表。 在控制臺上打印時,已抓取的列表如下所示:

          存儲檢索的數(shù)據(jù)

          一旦我們獲得了數(shù)據(jù),我們就可以以任何我們想要的格式存儲它,例如CSV文件,SQL數(shù)據(jù)庫或NoSQL數(shù)據(jù)庫。 嚴格來說,這一步不應算作抓取過程的一部分,但為了完整起見,我將簡要介紹它。

          我想說最流行的存儲抓取數(shù)據(jù)的方法是將它們存儲為CSV電子表格,所以我將簡要介紹如何做到這一點。 我不會詳細介紹,因為您應該參考官方的Python文檔。 所以,不用多說,讓我們看看代碼。

          我們可以看到,代碼非常明顯。 我們從打開的quotes.csv文件創(chuàng)建一個CSV編寫器對象,然后使用writerow函數(shù)逐個寫入引用。 很明顯,writerow函數(shù)接受一個列表作為輸入,然后將其作為一行寫入CSV。

          結論和后續(xù)步驟

          本教程應該幫助您了解在學習自己實現(xiàn)簡單的scraper時基本上是什么。 這種抓取應該足以實現(xiàn)簡單的自動化或小規(guī)模數(shù)據(jù)檢索。 但是如果你想有效地提取大量數(shù)據(jù),你應該研究一下抓取框架,特別是Scrapy。 它可以幫助您使用幾行代碼編寫非常快速,高效的scraper。 無論你使用什么樣的框架,在那個閃亮的表面下面,框架也使用這些非常基本的抓取原則,所以理解本教程應該可以幫助你為開始抓取的探險建立基礎知識。

          英文原文:https://stackabuse.com/introduction-to-web-scraping-with-python/
          譯者:javylee

          實際開發(fā)當中,我們經(jīng)常會遇到類似諸如下面的需求:

          1. 獲取滿足特定條件的數(shù)組中的所有項目
          2. 要檢查是否滿足條件?
          3. 檢查數(shù)組中是否有特定值?
          4. 在數(shù)組中找到指定值的索引?

          在本文中,我們將討論四種可用于搜索數(shù)組中項目的方法。這些方法是:

          1. filter
          2. find
          3. includes
          4. indexOf

          接下來,我們就一起來看一下這四種方式

          Array.filter()

          我們可以使用 Array.filter() 方法在數(shù)組中查找滿足特定條件的元素。

          例如,如果我們要獲取大于10的數(shù)字數(shù)組中的所有項目,則可以執(zhí)行以下操作:

          const array = [10, 11, 3, 20, 5];
          
          const greaterThanTen = array.filter(element => element > 10);
          
          console.log(greaterThanTen) //[11, 20]

          使用 array.filter() 方法的語法如下:

          let newArray = array.filter(callback);

          著這里:

          • newArray是返回的新數(shù)組
          • array 是我們要進行查找的數(shù)組本身
          • callback 是應用于數(shù)組每個元素的回調(diào)函數(shù)

          如果數(shù)組中沒有項目符合條件,則返回一個空數(shù)組。

          有時,我們不需要滿足特定條件的所有元素。我們只需要一個符合條件的元素。在這種情況下,需要使用find()方法。

          Array.find()

          使用 Array.find()方法查找滿足特定條件的第一個元素。就像 filter 方法一樣,它以回調(diào)為參數(shù),并返回滿足回調(diào)條件的第一個元素。

          我們嘗試一下在上面的示例中對數(shù)組使用 find 方法。

          const array = [10, 11, 3, 20, 5];
          
          const greaterThanTen = array.find(element => element > 10);
          
          console.log(greaterThanTen)//11

          array.find() 的語法為

          let element = array.find(callback);

          callback 是在數(shù)組中的每個值上執(zhí)行的函數(shù),帶有三個參數(shù):

          • element -當前被遍歷的元素(必填)
          • index -當前遍歷的元素的索引/位置(可選)
          • array- 當前數(shù)組(可選)

          但是請注意,如果數(shù)組中沒有項目符合條件,則返回 undefined。

          但是,如果想檢查某個元素是否在數(shù)組中怎么辦?

          Array.includes()

          includes() 方法確定數(shù)組是否包含某個值,并在適當時返回 true 或 false。

          因此,在上面的示例中,如果我們要檢查20是否為數(shù)組中的元素之一,則可以執(zhí)行以下操作:

          const array = [10, 11, 3, 20, 5];
          
          const includesTwenty = array.includes(20);
          
          console.log(includesTwenty)//true

          你會注意到此方法與其他方法之間的區(qū)別。此方法接受值而不是回調(diào)作為參數(shù)。這是 include 方法的語法:

          const includesValue = array.includes(valueToFind, fromIndex)
          • valueToFind 是要在數(shù)組中檢查的值(必填)
          • fromIndex 是要開始從中搜索元素的數(shù)組中的索引或位置(可選)

          要了解索引的概念,讓我們再次使用上面的示例。

          如果要檢查數(shù)組是否在第一個元素之外的其他位置包含10個,可以執(zhí)行如下操作:

          const array = [10, 11, 3, 20, 5];
          
          const includesTenTwice = array.includes(10, 1);
          
          console.log(includesTenTwice)//false

          Array.indexOf()

          indexOf() 方法返回可以在數(shù)組中找到給定元素的第一個索引。如果數(shù)組中不存在該元素,則返回 -1。

          回到例子。讓我們找到數(shù)組中 3 的索引。

          const array = [10, 11, 3, 20, 5];
          
          const indexOfThree = array.indexOf(3);
          
          console.log(indexOfThree)//2

          其語法類似于該 includes 方法的語法。

          const indexOfElement = array.indexOf(element, fromIndex)
          • element 是要在數(shù)組中檢查的元素(必填),并且
          • fromIndex 是要從數(shù)組中搜索元素的啟始索引或位置(可選)

          請務必注意,includes 和 indexOf 方法都使用嚴格的相等性('===')搜索數(shù)組。如果值的類型不同(例如4和'4'),它們將分別返回 false 和 -1。

          總結

          使用這些數(shù)組方法,無需使用 for 循環(huán)即可搜索數(shù)組。根據(jù)您的需求,您可以決定哪種方法最適合您的用例。

          以下是何時使用每種方法的摘要:

          • 如果你想找到在符合特定條件的陣列中的所有項目,使用 filter。
          • 如果你想檢查是否至少有一個項目符合特定的條件,請使用 find。
          • 如果你想檢查一個數(shù)組包含一個特定的值,請使用 includes。
          • 如果要在數(shù)組中查找特定項目的索引,請使用indexOf 。

          TML 中使用 <input> 元素表示單行輸入框和 <textarea> 元素表示多行文本框。

          HTML中使用的 <input> 元素在 JavaScript 中對應的是 HTMLInputElement 類型。HTMLInputElement 繼承自 HTMLElement 接口:

          interface HTMLInputElement extends HTMLElement {
              ...
          }

          HTMLInputElement 類型有一些獨有的屬性和方法:

          • name:表示 <input> 元素的名稱。
          • disabled:表示 <input> 元素是否禁止使用。在表單提交時不會包含被禁止的 <input> 元素。
          • autofocus:表示頁面加載時,該元素是否會自動獲得焦點。
          • required:表示表單提交時,該 <input>元素是否為必填。
          • value:表示該 <input> 元素的值。
          • validity:返回一個 ValidityState 對象,表示 <input> 元素的校驗狀態(tài)。是只讀屬性。
          • validationMessage:表示 <input> 元素校驗失敗時,用戶看到的報錯信息。如果該元素不需要校驗,或者通過校驗,該屬性為空字符串。是只讀屬性。
          • willValidate:表示表單提交時,<input> 元素是否會被校驗。是只讀屬性。
          • select():選中 <input> 元素內(nèi)部的所有文本。
          • click():模擬鼠標點擊當前的 <input> 元素。

          而在上述介紹 HTMLInputElement 類型中的屬性時,type 屬性要特別關注一下,因為根據(jù) type 屬性的改變,可以改變<input>的屬性。

          類型

          描述

          text

          文本輸入

          password

          密碼輸入

          submit

          表單數(shù)據(jù)提交

          button

          按鈕

          radio

          單選框

          checkbox

          復選框

          file

          文件

          hidden

          隱藏的字段

          image

          定義圖像作為提交按鈕

          reset

          重置按鈕

          省略 type 屬性與 type="text"效果一樣, <input> 元素顯示為文本框。

          type 的值為text/password/number/時,會有以下屬性對 <input> 元素有效。

          屬性

          類型

          描述

          autocomplete

          string

          字符串on或off,表示<input>元素的輸入內(nèi)容可以被瀏覽器自動補全。

          maxLength

          long

          指定<input>元素允許的最多字符數(shù)。

          size

          unsigned long

          表示<input>元素的寬度,這個寬度是以字符數(shù)來計量的。

          pattern

          string

          表示<input>元素的值應該滿足的正則表達式

          placeholder

          string

          表示<input>元素的占位符,作為對元素的提示。

          readOnly

          boolean

          表示用戶是否可以修改<input>的值。

          min

          string

          表示<input>元素的最小數(shù)值或日期。

          max

          string

          表示<input>元素的最大數(shù)值或日期。

          selectionStart

          unsigned long

          表示選中文本的起始位置。如果沒有選中文本,返回光標在<input>元素內(nèi)部的位置。

          selectionEnd

          unsigned long

          表示選中文本的結束位置。如果沒有選中文本,返回光標在<input>元素內(nèi)部的位置。

          selectionDirection

          string

          表示選中文本的方向。可能的值包括forwardbackwardnone

          下面創(chuàng)建一個 type="text" ,一次顯示 25 個字符,但最多允許顯示 50 個字符的文本框:

          <input type="text" size="25" maxlength="50" value="initial value">

          HTML 使用的 <textarea> 元素在 JavaScript 中對應的是 HTMLTextAreaElement 類型。HTMLTextAreaElement類型繼承自 HTMLElement 接口:

          interface HTMLTextAreaElement extends HTMLElement {
              ...
          }

          HTMLTextAreaElement 類型有一些獨有的屬性和方法:

          • form:只讀屬性,返回對父表單元素的引用。如果此元素未包含在表單元素中,則它可以是同一文檔中 id 屬性同 form 值的 <form> 元素,如果沒有,該值為 null
          • type:只讀屬性,返回字符串textarea
          • valuestring類型,返回/設置控件中包含的原始值。
          • textLength:只讀屬性,long類型,返回<textarea>元素的value值的長度。與 value.length 相同。
          • defaultValuestring類型,返回/設置textarea元素的默認值。
          • placeholderstring類型,返回/設置 textarea 元素的占位符,作為對輸入內(nèi)容的提示。
          • rowsunsigned long類型,返回/設置textarea元素的可見文本行數(shù)。
          • colsunsigned long類型,返回/設置 textarea 元素的可見寬度。
          • autofocusboolean類型,返回/設置textarea元素在頁面加載時自動獲取焦點。
          • name:返回/設置 textarea 元素的名稱。
          • disabledboolean類型,返回/設置 textarea 元素是否應當被禁用。
          • HTMLTextAreaElement.labelsNodeList類型,返回與此select元素關聯(lián)的標簽元素列表。
          • maxLengthlong類型,返回/設置元素可以輸入的最大字符數(shù)。僅在值更改時才評估此約束。
          • minLengthlong類型,返回/設置元素可以輸入的最小字符數(shù)。僅在值更改時才評估此約束。
          • accessKeyboolean類型,返回/設置訪問 textarea 的鍵盤快捷鍵。
          • readOnlyboolean類型,返回/設置 textarea 元素是否為只讀。
          • requiredboolean 類型,返回/設置 textarea 元素是否為必填項。
          • tabIndexlong類型,返回/設置 textarea 元素的 tab 鍵導航順序中元素的位置。

          下面創(chuàng)建一個高度為 25,寬度為 5 的 <textarea> 多行文本框。它與 <input> 不同的是,初始值顯示在 <textarea>...</textarea> 之間:

          <textarea rows="25" cols="5">initial value</textarea>

          注意:處理文本框值的時候最好不要使用 DOM 方法,而應該使用 value 屬性。

          選擇文本

          <input><textarea> 都支持 select() 方法,該方法用于選中文本框中的所有內(nèi)容。該方法的語法為:

          select(): void

          下面看一個示例:

          let textbox = document.forms[0].elements["input-box"];
          textbox.select();

          也可以在文本框獲得焦點時,選中文本框的內(nèi)容:

          textbox.addEventListener("focus", (event) => {
              event.target.select();
          });

          select 事件

          當選中文本框中的文本或使用 select() 方法時,會觸發(fā) select 事件。

          let textbox = document.forms[0].elements["textbox1"];
          textbox.addEventListener("select", (event) => {
              console.log(`Text selected: ${textbox.value}`);
          });

          取得選中的文本

          HTML5 對 select 事件進行了擴展,通過 selectionStartselectionEnd 屬性獲取文本選區(qū)的起點偏移量和終點偏移量。如下所示:

          function getSelectedText(textbox){
              return textbox.value.substring(textbox.selectionStart,
          textbox.selectionEnd);
          }

          注意:在 IE8 及更早版本不支持這兩個屬性。

          選中部分文本

          HTML5 提供了 setSelectionRange() 方法用于選中部分文本:

          setSelectionRange(start, end, direction): void;
          • start:被選中的第一個字符的位置索引,從 0 開始。如果這個值比元素的 value 長度還大,則會被看做 value 最后一個位置的索引。
          • end:被選中的最后一個字符的下一個位置索引。如果這個值比元素的 value 長度還大,則會被看做 value 最后一個位置的索引。
          • direction:該參數(shù)是可選的字符串類型,表示選擇方向,可以傳入 “forward”/“backward”/“none” 三個值。

          下面看一個例子:

          <input type="text" id="text-sample" size="20" value="Hello World!">
          <button onclick="selectText()">選中部分文本</button>
          <script>
              function selectText() {
                  let input = document.getElementById("text-sample");
                  input.focus();
                  input.setSelectionRange(4, 8);    // o Wo
              }
          </script>

          如果想要看到選中效果,必須讓文本框獲得焦點。

          輸入過濾

          不同文本框經(jīng)常需要保證輸入特定類型或格式的數(shù)據(jù),或許數(shù)據(jù)需要包含特定字符或必須匹配某個特定模式。而文本框并未提供驗證功能,因此要配合 JavaScript 腳本實現(xiàn)輸入過濾功能。

          屏蔽字符

          有些輸入框需要出現(xiàn)或不出現(xiàn)特定字符。如果想要將輸入框變成只讀的,只需要使用 preventDefault()方法將按鍵都屏蔽:

          input.addEventListener("keypress", (event) => {
              event.preventDefault();
          });

          而要屏蔽特定字符,就需要檢查事件的 charCode 屬性。如下所示,使用正則表達式實現(xiàn)只允許輸入數(shù)字的輸入框:

          input.addEventListener("keypress", (event) => {
              if (!/\d/.test(event.key)) {
                  event.preventDefault();
              }
          });

          還有一個問題需要處理:復制、粘貼及涉及Ctrl 鍵的其他功能。在除IE 外的所有瀏覽器中,前面代碼會屏蔽快捷鍵Ctrl+C、Ctrl+V 及其他使用Ctrl 的組合鍵。因此,最后一項檢測是確保沒有按下Ctrl鍵,如下面的例子所示:

          textbox.addEventListener("keypress", (event) => {
          if (!/\d/.test(String.fromCharCode(event.charCode)) &&
          event.charCode > 9 &&
          !event.ctrlKey){
          event.preventDefault();
          }
          });

          最后這個改動可以確保所有默認的文本框行為不受影響。這個技術可以用來自定義是否允許在文本框中輸入某些字符。

          處理剪貼板

          IE 是第一個實現(xiàn)了剪切板相關的事件以及通過JavaScript訪問剪切板數(shù)據(jù)的瀏覽器,其它瀏覽器在后來也都支持了相同的事件和剪切板的訪問,后來 HTML5 將其納入了規(guī)范。以下是與剪切板相關的 6 個事件:

          • beforecopy:發(fā)生復制操作前觸發(fā)。
          • copy:發(fā)生復制操作時觸發(fā)。
          • beforecut:發(fā)生剪切操作前觸發(fā)。
          • cut:發(fā)生剪切操作時觸發(fā)。
          • beforepaste:發(fā)生粘貼操作前觸發(fā)。
          • paste:發(fā)生粘貼操作時觸發(fā)。

          剪切板事件的行為及相關對象會因瀏覽器而異。在 Safari、Chrome 和 Firefox 中,beforecopybeforecutbeforepaste 事件只會在顯示文本框的上下文菜單時觸發(fā),但 IE 不僅在這種情況下觸發(fā),也會在 copycutpaste 事件在所有瀏覽器中都會按預期觸發(fā)。

          在實際的事件發(fā)生之前,通過beforecopybeforecutbeforepaste 事件可以在向剪貼板發(fā)送或從中檢索數(shù)據(jù)前修改數(shù)據(jù)。不過,取消這些事件并不會取消剪貼板操作。要阻止實際的剪貼板操作,必須取消 copycutpaste 事件。

          剪貼板的數(shù)據(jù)通過 clipboardData 對象來獲取,且clipboardData 對象提供 3 個操作數(shù)據(jù)的方法:

          • getData(format):從剪貼板獲取指定格式的數(shù)據(jù),接收的參數(shù)為指定獲取的數(shù)據(jù)格式,如果沒有指定數(shù)據(jù)格式或指定數(shù)據(jù)格式不存在,則此方法返回一個空字符串。
          • setData(format, data):給剪貼板賦予指定格式的數(shù)據(jù),第一個參數(shù)指定數(shù)據(jù)格式,第二個參數(shù)為第一個參數(shù)賦予數(shù)據(jù)。如果指定數(shù)據(jù)格式不存在,則將其添加到數(shù)據(jù)存儲的末尾;如果指定數(shù)據(jù)格式存在,則將數(shù)據(jù)替換在指定數(shù)據(jù)格式的位置。
          • clearData(format):刪除指定格式的數(shù)據(jù),接收的參數(shù)為指定要刪除的數(shù)據(jù)格式,如果指定格式不存在,則此方法不執(zhí)行任何操作;如果此參數(shù)為空字符串或未提供,則將刪除所有格式的數(shù)據(jù)。

          clipboardData 對象在 IE 中使用 window 獲取,在 Firefox、Safari 和 Chrome 中使用 event 獲取。為防止未經(jīng)授權訪問剪貼板,只能在剪貼板事件期間訪問 clipboardData 對象;IE 會在任何時候都暴露 clipboardData 對象。因此,要兼容兩者,最好在剪貼板事件期間使用該對象。

          function getClipboardText(event){
              var clipboardData = (event.clipboardData || window.clipboardData);
              return clipboardData.getData("text");
          }
          function setClipboardText (event, value){
              if (event.clipboardData){
                  return event.clipboardData.setData("text/plain", value);
              } else if (window.clipboardData){
                  return window.clipboardData.setData("text", value);
              }
          }

          如果文本框只有數(shù)字,那剪貼時,就需要使用paste事件檢查剪貼板上的文本是否無效。如果無效,可以取消默認行為:

          input.addEventListener("paste", (event) => {
              let text = getClipboardText(event);
              if (!/^\d*$/.test(text)){
                  event.preventDefault();
              }
          });

          注意:Firefox、Safari和Chrome只允許在onpaste事件中訪問getData()方法。

          自動切換

          在 JavaScript 中,可以用在當前字段完成時自動切換到下一個字段的方式來增強表單字段的易用性。比如,常用手機號分為國家好加手機號。因此,我們設置 2 個文本框:

          <form>
              <input type="text" name="phone1" id="phone-id-1" maxlength="4">
              <input type="text" name="phone2" id="phone-id-2" maxlength="11">
          </form>

          當文本框輸入到最大允許字符數(shù)后,就把焦點移到下一個文本框,這樣可以增加表單的易用性并加速數(shù)據(jù)輸入。如下所示:

          <script>
              function tabForward(event){
                  let target = event.target;
                  if (target.value.length == target.maxLength){
                      let form = target.form;
                      for (let i = 0, len = form.elements.length; i < len; i++) {
                          if (form.elements[i] == target) {
                              if (form.elements[i+1]) {
                                  form.elements[i+1].focus();
                              }
                              return;
                          }
                      }
                  }
              }
              let inputIds = ["phone-id-1", "phone-id-2"];
              for (let id of inputIds) {
                  let textbox = document.getElementById(id);
                  textbox.addEventListener("keyup", tabForward);
              }
          </script>

          這里,tabForward() 函數(shù)通過比較用戶輸入文本的長度與 maxLength 屬性的值來檢測輸入是否達到了最大長度。如果兩者相等,就通過循環(huán)表中的元素集合找到當前文本框,并把焦點設置到下一個元素。

          注意:上面的代碼只適用于之前既定的標記,沒有考慮可能存在的隱藏字段。

          HTML5

          HTML5 新增了一些表單提交前,瀏覽器會基于指定的規(guī)則進行驗證,并在出錯時顯示適當?shù)腻e誤信息。而驗證會基于某些條件應用到表單字段中。

          必填字段

          表單字段中添加 required 屬性,用于標注該字段是必填項,不填則無法提交。該屬性適用于<input><textarea><select>。如下所示:

          <input type="text" name="account" required>

          也可以通過 JavaScript 檢測對應元素的 required 屬性來判斷表單字段是否為必填項:

          let isRequired = document.forms[0].elements["account"].required;

          也可以檢測瀏覽器是否支持 required 屬性:

          let isRequiredSupported = "required" in document.createElement("input");

          注意:不同瀏覽器處理必填字段的機制不同。Firefox、Chrome、IE 和Opera 會阻止表單提交并在相應字段下面顯示有幫助信息的彈框,而Safari 什么也不做,也不會阻止提交表單。

          更多輸入類型

          HTML5 為 <input> 元素增加了幾個新的 type 值。如下所示:

          類型

          描述

          number

          數(shù)字值的輸入

          date

          日期輸入

          color

          顏色輸入

          range

          一定范圍內(nèi)的值的輸入

          month

          允許用戶選擇月份和年份

          week

          允許用戶選擇周和年份

          time

          允許用戶選擇時間(無時區(qū))

          datetime

          允許用戶選擇日期和時間(有時區(qū))

          datetime-local

          允許用戶選擇日期和時間(無時區(qū))

          email

          電子郵件地址的輸入

          search

          搜索(表現(xiàn)類似常規(guī)文本)

          tel

          電話號碼的輸入

          url

          URL地址的輸入

          這些輸入表名字段應該輸入的數(shù)據(jù)類型,并且提供了默認驗證。如下所示:

          <input type="email" name="email">
          <input type="url" name="homepage">

          要檢測瀏覽器是否支持新類型,可以在 JavaScript 中創(chuàng)建 <input> 并設置 type 屬性,之后讀取它即可。老版本中會將我只類型設置為 text,而支持的會返回正確的值。如下所示:

          let input = document.createElement("input");
          input.type = "email";
          let isEmailSupported = (input.type == "email");

          數(shù)值范圍

          而上面介紹的幾個如 number/range/datetime/datetime-local/date/month/week/time 幾個填寫數(shù)字的類型,都可以指定 min/max/step 等幾個與數(shù)值有關的屬性。step 屬性用于規(guī)定合法數(shù)字間隔,如 step="2",則合法數(shù)字應該為 0、2、4、6,依次類推。如下所示:

          <input type="number" min="0" max="100" step="5" name="count">

          上面的例子是<input>中只能輸入從 0 到 100 中 5 的倍數(shù)。

          也可以使用 stepUp()stepDown() 方法對 <input> 元素中的值進行加減,它倆會接收一個可選參數(shù),用于表示加減的數(shù)值。如下所示:

          input.stepUp(); // 加1
          input.stepUp(5); // 加5
          input.stepDown(); // 減1
          input.stepDown(10); // 減10

          輸入模式

          HTML5 還為文本添加了 pattern 屬性,用于指定一個正則表達式。這樣就可以自己設置 <input> 元素的輸入模式了。如下所示:

          <input type="text" pattern="\d+" name="count">

          注意模式的開頭和末尾分別假設有^$。這意味著輸入內(nèi)容必須從頭到尾都嚴格與模式匹配。

          與新增的輸入類型一樣,指定 pattern 屬性也不會阻止用戶輸入無效內(nèi)容。模式會應用到值,然后瀏覽器會知道值是否有效。通過訪問 pattern 屬性可以讀取模式:

          let pattern = document.forms[0].elements["count"].pattern;

          使用如下代碼可以檢測瀏覽器是否支持pattern 屬性:

          let isPatternSupported = "pattern" in document.createElement("input");

          檢測有效性

          HTML5 新增了 checkValidity() 方法,用來檢測表單中任意給定字段是否有效。而判斷的條件是約束條件,因此必填字段如果沒有值會被視為無效,字段值不匹配 pattern 屬性也會被視為無效。如下所示:

          if (document.forms[0].elements[0].checkValidity()){
              // 字段有效,繼續(xù)
          } else {
              // 字段無效
          }

          要檢查整個表單是否有效,可以直接在表單上調(diào)用checkValidity()方法。這個方法會在所有字段都有效時返回true,有一個字段無效就會返回false

          if(document.forms[0].checkValidity()){
              // 表單有效,繼續(xù)
          } else {
              // 表單無效
          }

          validity 屬性會返回一個ValidityState 對象,表示 <input> 元素的校驗狀態(tài)。返回的對象包含一些列的布爾值的屬性:

          • customError:如果設置了 setCustomValidity() 就返回 true,否則返回false。
          • patternMismatch:如果字段值不匹配指定的 pattern 屬性則返回true。
          • rangeOverflow:如果字段值大于 max 的值則返回true。
          • rangeUnderflow:如果字段值小于 min 的值則返回true。
          • stepMisMatch:如果字段值與 minmaxstep 的值不相符則返回true。
          • tooLong:如果字段值的長度超過了 maxlength 屬性指定的值則返回true。
          • typeMismatch:如果字段值不是 "email""url" 要求的格式則返回true。
          • valid:如果其他所有屬性的值都為false 則返回true。與checkValidity()的條件一致。
          • valueMissing:如果字段是必填的但沒有值則返回true。

          因此,通過 validity 屬性可以檢查表單字段的有效性,從而獲取更具體的信息,如下所示:

          if (input.validity && !input.validity.valid){
              if (input.validity.valueMissing){
                  console.log("請指定值.")
              } else if (input.validity.typeMismatch){
                  console.log("請指定電子郵件地址.");
              } else {
                  console.log("值無效.");
              }
          }

          禁用驗證

          通過指定 novalidate 屬性可以禁止對表單進行任何驗證:

          <form method="post" action="/signup" novalidate>
              <!-- 表單元素 -->
          </form>

          也可以在 JavaScript 通過 noValidate 屬性設置,為 true 表示屬性存在,為 false 表示屬性不存在:

          document.forms[0].noValidate = true; // 關閉驗證

          如果一個表單中有多個提交按鈕,那么可以給特定的提交按鈕添加formnovalidate 屬性,指定通過該按鈕無需驗證即可提交表單:

          <form method="post" action="/foo">
              <!-- 表單元素 -->
              <input type="submit" value="注冊提交">
              <input type="submit" formnovalidate name="btnNoValidate"
          value="沒有驗證的提交按鈕">
          </form>

          也可以使用 JavaScript 設置 formNoValidate 屬性:

          // 關閉驗證
          document.forms[0].elements["btnNoValidate"].formNoValidate = true;

          總結

          以上總結了 <input><textarea> 兩個元素的一些功能,主要是 <input> 元素可以通過設置 type 屬性獲取不同類型的輸入框,可以通過監(jiān)聽鍵盤事件并檢測要插入的字符來控制文本框的內(nèi)容。

          還有一些與剪貼板相關的事件,并對剪貼的內(nèi)容進行檢測。還介紹了一些 HTML5 新增的屬性和方法和新增的更多的 <input> 元素的類型,和一些與驗證相關的屬性和方法。


          主站蜘蛛池模板: 无码少妇A片一区二区三区| 国产亚洲情侣一区二区无| 午夜影院一区二区| 久久精品一区二区三区AV| 无码精品久久一区二区三区| 精品国产一区二区麻豆| 欧美日韩精品一区二区在线观看| 亚洲日韩中文字幕无码一区| 无码人妻一区二区三区免费n鬼沢| 色一乱一伦一区一直爽| 成人免费区一区二区三区| 精品一区二区三区视频| 麻豆一区二区99久久久久| 日本精品啪啪一区二区三区| 日本人的色道www免费一区| 日韩精品一区二三区中文 | 无码一区二区三区在线| 天美传媒一区二区三区| 国产亚洲欧洲Aⅴ综合一区| 日韩在线不卡免费视频一区| 亚洲色大成网站www永久一区| 精品免费国产一区二区| 一区五十路在线中出| 国产成人无码AV一区二区| 鲁大师成人一区二区三区| 成人精品一区二区三区中文字幕| 麻豆视传媒一区二区三区| 一区二区高清在线| 免费国产在线精品一区| 本免费AV无码专区一区| 久久99精品一区二区三区| 亚洲一区精品中文字幕| 亚洲综合无码一区二区痴汉| 97se色综合一区二区二区| 无码人妻精品一区二区三区东京热| 国产福利在线观看一区二区| 亚洲AV无码一区二区一二区| 国产精品一区二区无线| 日本高清成本人视频一区| 精品爆乳一区二区三区无码av| 亚洲国产日韩在线一区|