Web 開發中,有許多情況需要解析 URL,這篇主要學習如何使用 URL 對象實現這一點。
開始
創建一個以下內容的 HTML 文件,并在瀏覽器中打開。
<html> <head> <title>JavaScript URL parsing</title> </head> <body> <script> // 激動人心的代碼即將寫在這里 </script> </body> </html>
如果你想嘗試本文中的任何內容,可以將其放在 <script> 標記中,保存,重新加載頁面,看看會發生什么! 在本教程中,將使用 console.log 來打印所需要的內容,你可以打開開發都工具,來查看內容。
什么是 URL
這應該是相當簡單的,但讓我們說清楚。 URL 是網頁的地址,可以在瀏覽器中輸入以獲取該網頁的唯一內容。 可以在地址欄中看到它:
URL 是統一資源定位符,對可以從互聯網上得到的資源的位置和訪問方法的一種簡潔的表示,是互聯網上標準資源的地址。互聯網上的每個文件都有一個唯一的 URL,它包含的信息指出文件的位置以及瀏覽器應該怎么處理它。
此外,如果你不熟悉基本 URL 路徑的工作方式,可以查看此文學習。
URL 不都長的一樣的
這是一個快速提醒 - 有時 URL 可能非常奇怪,如下:
:1234/page/?a=b
file:///Users/username/folder/file.png
獲取當前URL
獲取當前頁面的 URL 非常簡單 - 我們可以使用 window.location。
試著把這個添加到我們形如寫的的腳本中:
console.log(window.location);
查看瀏覽器的控制臺:
不是你想要的?這是因為它不返回你在瀏覽器中看到的實際 URL 地址——它返回的是一個 URL 對象。使用這個 URL 對象,我們可以解析 URL 的不同部分,接下來就會講到。
創建 URL 對象
很快就會看到,可以使用 URL 對象來了解 URL 的不同部分。如果你想對任何 URL 執行此操作,而不僅僅是當前頁面的 URL,該怎么辦? 我們可以通過創建一個新的 URL 對象來實現。 以下是如何創建一個:
var myURL = new URL('https://example.com');
就這么簡單! 可以打印 myURL 來查看 myURL 的內容:
console.log(myURL);
出于本文的目的,將 myURL 設置為這個值:
var myURL = new URL('https://example.com:4000/folder/page.html?x=y&a=b#section-2')
將其復制并粘貼到 <script> 元素中,以便你可以繼續操作! 這個 URL 的某些部分可能不熟悉,因為它們并不總是被使用 - 但你將在下面了解它們,所以不要擔心!
URL 對象的結構
使用 URL 對象,可以非常輕松地獲取 URL 的不同部分。 以下是你可以從 URL 對象獲得的所有內容。 對于這些示例,我們將使用上面設置的 myURL。
href
URL 的 href 基本上是作為字符串(文本)的整個 URL。如果你想把頁面的 URL 作為字符串而不是 URL 對象,你可以寫 window.location.href。
console.log(myURL.href); // Output: "https://example.com:4000/folder/page.html?x=y&a=b#section-2"
協議 (protocol)
URL的協議是一開始的部分。這告訴瀏覽器如何訪問該頁面,例如通過 HTTP 或 HTTPS。 但是還有很多其他協議,比如 ftp(文件傳輸協議)和 ws(WebSocket)。通常,網站將使用 HTTP 或 HTTPS。
雖然如果你的計算機上打開了文件,你可能正在使用文件協議! URL對象的協議部分包括:,但不包括 //。 讓我們看看 myURL 吧!
console.log(myURL.protocol); // Output: "https:"
主機名(hostname)
主機名是站點的域名。 如果你不熟悉域名,則它是在瀏覽器中看到的URL的主要部分 - 例如 google.com 或codetheweb.blog。
console.log(myURL.hostname); // Output: "example.com"
端口(port)
URL 的端口號位于域名后面,用冒號分隔(例如 example.com:1234)。 大多數網址都沒有端口號,這種情況非常罕見。
端口號是服務器上用于獲取數據的特定“通道” - 因此,如果我擁有 example.com,我可以在多個不同的端口上發送不同的數據。 但通常域名默認為一個特定端口,因此不需要端口號。 來看看 myURL 的端口號:
console.log(myURL.port); // Output: "4000"
主機(host)
主機只是主機名和端口放在一起,嘗試獲取 myURL 的主機:
console.log(myURL.host); // Output: "example.com:4000"
來源(origin)
origin 由 URL 的協議,主機名和端口組成。 它基本上是整個 URL,直到端口號結束,如果沒有端口號,到主機名結束。
console.log(myURL.origin); // Output: "https://example.com:4000"
pathname(文件名)
pathname 從域名的最后一個 “/” 開始到 “?” 為止,是文件名部分,如果沒有 “?” ,則是從域名最后的一個 “/” 開始到 “#” 為止 , 是文件部分, 如果沒有 “?” 和 “#” , 那么從域名后的最后一個 “/” 開始到結束 , 都是文件名部分。
console.log(myURL.pathname); // Output: "/folder/page.html"
錨點(hash)
從 “#” 開始到最后,都是錨部分。可以將哈希值添加到 URL 以直接滾動到具有 ID 為該值的哈希值 的元素。 例如,如果你有一個 id 為 hello 的元素,則可以在 URL 中添加 #hello 就可以直接滾動到這個元素的位置上。通過以下方式可以在 URL 獲取 “#” 后面的值:
console.log(myURL.hash); // Output: "#section-2"
查詢參數 (search)
你還可以向 URL 添加查詢參數。它們是鍵值對,意味著將特定的“變量”設置為特定值。 查詢參數的形式為 key=value。 以下是一些 URL 查詢參數的示例:
?key1=value1&key2=value2&key3=value3
請注意,如果 URL 也有 錨點(hash),則查詢參數位于 錨點(hash)(也就是 ‘#’)之前,如我們的示例 URL 中所示:
console.log(myURL.search); // Output: "?x=y&a=b"
但是,如果我們想要拆分它們并獲取它們的值,那就有點復雜了。
使用 URLSearchParams 解析查詢參數
要解析查詢參數,我們需要創建一個 URLSearchParams 對象,如下所示:
var searchParams = new URLSearchParams(myURL.search);
然后可以通過調用 searchParams.get('key')來獲取特定鍵的值。 使用我們的示例網址 - 這是原始搜索參數:
?x=y&a=b
因此,如果我們調用 searchParams.get('x'),那么它應該返回 y,而 searchParams.get('a')應該返回 b,我們來試試吧!
console.log(searchParams.get('x')); // Output: "y" console.log(searchParams.get('a')); // Output: "b"
擴展
獲取 URL 的中參數
方法一:正則法
function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'); var r = window.location.search.substr(1).match(reg); if (r != null) { return unescape(r[2]); } return null; } // 這樣調用: alert(GetQueryString("參數名1")); alert(GetQueryString("參數名2")); alert(GetQueryString("參數名3"));
方法二:split拆分法
function GetRequest() { var url = location.search; //獲取url中"?"符后的字串 var theRequest = new Object(); if (url.indexOf("?") != -1) { var str = url.substr(1); strstrs = str.split("&"); for(var i = 0; i < strs.length; i ++) { theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]); } } return theRequest; } var Request = new Object(); Request = GetRequest(); // var 參數1,參數2,參數3,參數N; // 參數1 = Request['參數1']; // 參數2 = Request['參數2']; // 參數3 = Request['參數3']; // 參數N = Request['參數N'];
修改 URL 的中某個參數值
般我們日常在上網的時候,會在瀏覽器的地址欄里輸入一個網站的 "網址",點擊下回車,就會跳到你想去的網站,就類似這樣
但其實,叫做 "網址" 并不是特別的準確,確切地說,應該叫做 URL
那到底啥是 URL 呢? 不就是一個網址嗎?
URL 是英文 Uniform Resource Locator 的縮寫,即統一資源定位器,是因特網上用于指定信息位置的表示方法,通過它就能找到網上的某個你要的資源
雖然我們平時使用瀏覽器的時候,只要輸入baidu.com或者qq.com就能正常上網了,但其實我們輸入的只是整個URL中的一小部分
來,我先看看一個相對完整的URL的整體結構是怎么樣的
這里大致分了幾個部分,我們一個個來看,它們具體是干什么的
圖中http://這部分就是協議部分,即指定了URL是以什么協議發送網絡請求的
常見的協議如:http://、https://、ftp://、file://,比如: http://就是超文本傳輸協議,平時上網大多用這個協議,https://是以安全為目標的HTTP協議。
圖中localhost就是地址部分,用來確定URL所要訪問的服務器的網絡地址(也就是網址)。在URL中,地址可以用三個形式來表示:域名、主機名、IP地址
我們平時輸入的www.baidu.com、www.qq.com就是域名,域名也分一級域名、二級域名、以及頂級域名。
不過,域名也只是一串文字,計算機和路由器并不能直接認出它,還需要通過DNS服務器找到域名對應的IP地址,再通過底層的TCP/IP協議路由到對應的機器上去 (這些內容不是本文的重點暫時略過,先挖個坑再說)
主機名就是某臺計算機的名字,在一個局域網內,可以通過主機名找到你要訪問的計算機。主機名和域名一樣,計算機和路由器不認它,需要通過HOSTS文件這樣的技術找到主機名和IP地址的關聯關系,最后還是翻譯成IP地址再繼續發送網絡請求
圖中的localhost也是主機名,但是一種比較特殊的主機名,是給 回環地址的一個標準主機名,就是代表本機自己的地址。
在URL中也可以直接用IP地址來代替域名或主機名,如192.168.0.1,關于IP地址的相關知識點放到以后再講(繼續挖坑)
圖中在冒號:后面的那串數字8080就是端口號,一臺服務器上可以開多個端口號,往往一個網絡服務程序就對應一個端口號
比如,我在機器 A 上,開了兩個服務程序,分別是 Tomcat和SSH,讓它們分別關聯端口8080和22,那URL中如果端口號是8080就是會訪問到Tomcat程序,22就會連接SSH服務。
但可能有小伙伴會有疑問:誒,我平時上百度看到的URL是http://www.baidu.com沒看到有端口號啊
其實是有的,端口號是80,只是它被隱藏起來了,我們看不到而已,而這個80端口也就是URL的默認端口號
但不是所有URL的默認端口號都是80,如果協議是http://,默認端口號為80,但若是https://協議,默認端口號就是443了
從第一個斜杠/開始,到最后一個斜杠/結束的那部分,也就是圖中/app/user/那部分即為虛擬目錄
它就類似我們電腦中文件目錄的格式,第一個/為根目錄,每多一個/就多進入一層目錄
從域名后開始算起的最后一個斜杠/開始,到?為止,沒有?則到#為止,或者?和#都沒有就是到整個URL結束為止的那部分就為文件名
說起來很繞吧,其實就是圖中 info.do 這部分,它一般包含文件名和擴展名('.'后面那部分),用來指代一個URL所訪問的具體文件或資源,它可以是圖片、html文件、css文件,也可以是js文件、字體文件等等,它也可以不是某種文件,而是服務端后臺執行的某段程序。
甚至可以省略不寫虛擬目錄和文件名,因為它們本來就不是必須的,就如http://www.baidu.com這樣的URL就沒有文件名,但服務器會在缺省的情況下給你定位到某個特定的文件或程序上去。
從?后到#結束,即圖中的?uid=101&ty=2為查詢參數
查詢參數,也稱為URL參數、查詢字符串,英文名為 Query,它是用來向服務端以字符串的形式傳遞參數和少數數據用的
其參數形式一般都以多個鍵值對的形式進行表示,如 a=1、b=2就是兩個鍵值對,鍵為"a"和"b",值為對應的"1"和"2", 多個鍵值對應&連起來:a=1&b=2
但參數要傳遞的某些值往往帶有特殊字符,這些字符和URL標準的格式沖突,比如要傳a&b這樣字符串,和查詢參數鍵值對的連接符&沖突了,若不加以區分就會產生歧義
而最簡單的辦法,就是對參數值進行編碼,稱為 URL Encoding,通過編碼,a&b變成了a%26b,就不再包含會沖突的特殊字符
而有些參數即便有特殊字符,也不會被編碼,除非自行強制編碼,比如URL中參數值是另外一串URL,就可以寫成 http://localhost/do?url=http://www.baidu.com
這種特殊情況不會有歧義,因為計算機系統認得出參數是另一串URL,就會按URL的形式來解析,但當子URL又包含子參數和多子鍵值對的時候也難免會分不清參數到底是兒子的還是父親的,這時還是強制編碼的好
URL的參數是一個個鍵值對,即一個key對應一個value,那如果是一個key要傳遞多個值,也就是一個列表咋辦?也好辦
URL的參數名是可以重復的,比如a=1&a=2&a=3,這里穿了3個參數名都為a的查詢參數,是完全可以的,可以利用這種特性,按順序將 1、2、3作為參數a的列表值
為了表示更清楚點,一般都會在列表參數名后面加上一對方括號[],如:a[]=1&a[]=2&a[]=3
但是,對于URL參數的寫法和格式的標準,也沒有特別嚴格的規定,以上幾種形式一般都會支持
圖中#后面那部分字符串,#abc就是錨部分
錨,英文稱做Reference,通常也是用來傳遞參數等信息,但與查詢參數的本質區別就是這部分內容不會被傳遞到服務器端
錨一般用于頁面,比如在瀏覽網頁的時候,按個按鈕突然幫你定位到頁首或頁面中的某個位子去了,這就是錨
現在隨著前后端分離技術,尤其是 vue、reactjs 等前端框架的興起,錨作為前端javascript程序處理的參數載體也越來越重要了
URL看似已經習以為常、非常簡單的東西,背后往往也隱藏著很多技術細節和知識點,甚至這短短一篇文章也沒辦法窮盡
其實URL的內容還有不少,比如<用戶名>@<密碼>這種用戶驗證信息在URL中的傳遞,由于篇幅的關系還沒有講到
所以我講分幾篇文章來講解HTTP協議的其中幾個重要部分,如果這一系列文章對你有幫助,別忘了關注哦~
發送HTTP請求:首先,你需要向目標網頁發送HTTP請求以獲取其HTML內容。這可以通過Java的內置庫java.net.HttpURLConnection或者使用更高級的庫如Apache Http Client OkHttp等來完成。
·讀取響應內容:一旦你發送了請求并收到了響應,你需要讀取響應的內容,這通常是HTML格式的字符串。
·解析HTML:然后,你需要解析HTML字符串以提取所需的信息,這可以通過正則表達式來完成。但通常建議使用專門的HTML解析庫,如Jsoup。Jsoup提供了一種非常方便的方式來解析HTML文檔,并可以通過類似于CSS或jQuery的選擇器語法來提取和操作數據。
·如果你需要處理更復雜的網頁或進行更高級的網頁抓取和解析任務,你可能還需要考慮使用如Selenium這樣的瀏覽器自動化工具來模擬真實的瀏覽器行為。但是請注意,頻繁或大規模地抓取網頁可能會違反網站的使用條款甚至可能構成法律問題。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。