ML HttpRequest(XHR) 技術(shù)是構(gòu)建動態(tài)、響應(yīng)式網(wǎng)站的關(guān)鍵。這項技術(shù)使得網(wǎng)頁能在不重新加載整個頁面的情況下與服務(wù)器進(jìn)行數(shù)據(jù)交互,極大地優(yōu)化了用戶的交互體驗。
XML HttpRequest 是一種瀏覽器與服務(wù)器進(jìn)行數(shù)據(jù)交換的 API。盡管它的名字包含 “XML”,XHR 實際上支持多種數(shù)據(jù)格式,如 JSON、HTML 和純文本等。初期,它主要用于處理 XML 格式數(shù)據(jù),但隨著時間的發(fā)展,XHR 的功能已經(jīng)大為擴展。
使用 XML HttpRequest 的基本步驟包括:
以下 JavaScript 代碼演示了如何通過 XML HttpRequest 發(fā)起一個 GET 請求:
// 初始化一個XML HttpRequest對象
var xhr = new XML HttpRequest();
// 設(shè)置請求的方法和URL
xhr.open('GET', 'https://api.example.com/data', true);
// 定義響應(yīng)的處理邏輯
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText); // 輸出響應(yīng)數(shù)據(jù)
}
};
// 執(zhí)行請求
xhr.send();
在此示例中,我們配置了請求和如何在接收到響應(yīng)后處理數(shù)據(jù)。
XML HttpRequest 允訟網(wǎng)頁動態(tài)地加載和顯示數(shù)據(jù),而無需刷新頁面,提高了網(wǎng)站的整體性能和用戶體驗。
使用 XHR,表單數(shù)據(jù)可以異步提交,從而避免頁面刷新,用戶可以無縫繼續(xù)他們的網(wǎng)站活動。
對于需要頻繁更新數(shù)據(jù)的應(yīng)用,如實時報表或聊天應(yīng)用,XHR 提供了持續(xù)與服務(wù)器通信的能力。
雖然 Fetch API 在現(xiàn)代 Web 開發(fā)中逐漸成為新的標(biāo)準(zhǔn),提供了更簡潔的 API 和更好的錯誤處理機制,F(xiàn)etch 的使用示例如下:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Fetch 基于 Promises,簡化了處理異步操作的復(fù)杭性。
XML HttpRequest 是 Web 開發(fā)者必須掌握的重要工具之一。盡管有更現(xiàn)代的技術(shù)如 Fetch API,了解 XHR 仍對處理舊項目或理解 Web 開發(fā)的歷史背景非常有用。無論是更新現(xiàn)有的網(wǎng)站還是開發(fā)新的應(yīng)用,XHR 都是一個寶貴的資源。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jsx</title>
<style>
.title{
background-color: orange:
width: 200px;
}
</style><!--定義個樣式,也可以寫在CSS文件里,引入進(jìn)來-->
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
</body>
<script type="text/babel">
const myid= "lOVE you"
const mydata= "hellO jsx"
const VDOM = ( // <!--h2標(biāo)簽引入樣式,用className,span標(biāo)簽引入內(nèi)聯(lián)樣式的時候,不是用雙引號,而是雙花括號,-->
<div>
<h2 className="title" id={myid.toLowerCase()}>
<span style={{color:'red',fontSize:'29px'}}>{mydata.toLowerCase()}</span>
</h2>)// <!--標(biāo)簽中混入JS表達(dá)式時要用花括號{},如這里mydata取值 -->
//jsx中只能有一個根標(biāo)簽,比如這里的h2,可以在h2的外面包一層div,就可以寫兩個h2
<h2 className="title" id={myid.toUpperCase()}>
<span style={{color:'red',fontSize:'29px'}}>{mydata.toLowerCase()}</span>
</h2>)
//標(biāo)簽首字母若是小寫字母,則將該標(biāo)簽轉(zhuǎn)為html中同名元素,若html中無該標(biāo)簽對應(yīng)的同名元素,則報錯
//標(biāo)簽首字母若是大寫字母,react就去渲染對應(yīng)的組件,若組件沒有定義,則報錯
</div>
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</html>
<script type="text/babel">
const data=['A','B','C']
const VDOM = (
<div> //js表達(dá)式會產(chǎn)生一個值。js語句(代碼),有if,for,switch判斷,
<h1>jsx框架</h1>
<ul>
{
data.map((item,index)=>{
return <li key={index}>{item}</li>
}) //item拿到data里面對應(yīng)的值,map遍歷的第二個值是索引值,
}
</ul>
</div>
)
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
對應(yīng)的網(wǎng)頁如下:
模塊是向外提供特定功能的js程序,一般就是一個js文件。
組件比模塊更高一級,比如實現(xiàn)一個網(wǎng)頁的頭部的html,字體,css,js,圖像這些元素組合在一起,就形成了頭部這個組件。
函數(shù)式組件:
<script type="text/babel">
function MyComponent(){
return <h2>show the function component</h2>
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
//<MyComponent/>要寫上標(biāo)簽,函數(shù)定義首字母需要大寫
</script>
執(zhí)行了ReactDOM.render(<MyComponent/>。。之后,React解析組件標(biāo)簽,找到MyComponent組件,發(fā)現(xiàn)組件是使用函數(shù)定義的,隨后調(diào)用該函數(shù),將返回的虛擬DOM轉(zhuǎn)為真是DOM,隨后呈現(xiàn)在頁面中。
類式組件:
上一篇文章中:Python如何解析HTML和XML數(shù)據(jù),我們介紹如何使用Python解析HTML和XML數(shù)據(jù),其中提到xpath的使用。事實上,xpath的功能非常強大,熟練使用可以給數(shù)據(jù)提取帶來極大的方便,所以今天打算做進(jìn)一步的介紹。
準(zhǔn)備
本文依然使用lxml進(jìn)行html/xml數(shù)據(jù)解析,可以自行使用pip進(jìn)行安裝,如不熟悉pip的使用,可以參考另一篇文章:如何管理python軟件包。
先使用urllib2去抓取一個HTML頁面,比如前篇提到的中航電子2017年一季度交易記錄:
>>> import urllib2
>>> url = 'http://quotes.money.163.com/trade/lsjysj_600372.html?year=2017&season=1'
>>> rsp = urllib2.urlopen(url).read()
使用lxml.html軟件包進(jìn)行解析:
>>> from lxml import html
>>> doc = html.document_fromstring(rsp)
>>> doc.tag
'html'
可以看到,當(dāng)前doc代表的是html元素。
什么是XPath
XPath,是XML Path Language的縮寫,是一種用于從XML文檔中選取節(jié)點的查詢語言,也可以用于對節(jié)點內(nèi)容進(jìn)行計算。xpath的標(biāo)準(zhǔn)是由W3C制定的。xpath雖然經(jīng)歷了多個版本(1999-v1.0, 2007-v2.0, 2014-v3.0, 2017-v3.1),但v1.0的使用仍然最廣泛,其官方文檔可以參考:
https://www.w3.org/TR/xpath/
XPath表達(dá)式
在xpath看來,XML文檔就是一顆由節(jié)點構(gòu)成的樹,其中節(jié)點可以分為元素節(jié)點(element node)、屬性節(jié)點(attribute node)和文本節(jié)點(text node)。xpath最基本的語法結(jié)構(gòu)是表達(dá)式(expression),表達(dá)式運行之后可以返回一下四類結(jié)果:
一組節(jié)點(不重復(fù))
布爾取值true/false
數(shù)值(浮點類型)
字符串
分別看下面例子:
>>> doc.xpath('child::*')
[<Element head at 0x10f478ec0>, <Element body at 0x10f478ba8>]
>>> doc.xpath('3 < 2')
False
>>> doc.xpath('3 = 3')
True
>>> doc.xpath('3 + 2')
5.0
>>> doc.xpath('2 * 3')
6.0
>>> doc.xpath('6 div 3')
2.0
>>> doc.xpath('3 mod 2')
1.0
>>> doc.xpath('/html/head/meta[@name="robots"]/@name')
['robots']
路徑與步
XPath最重要的一類表達(dá)式,是用于節(jié)點選取的路徑(Location Path),看一個例子:
>>> doc.xpath('/html/head/meta[@name="robots"]')
[<Element meta at 0x10f478ba8>]
可以看到,一條路徑有若干步(step)組成,步之間使用斜杠"/"分隔,每一步都從上下文節(jié)點中選取滿足條件的若干節(jié)點。路徑可分為相對路徑和絕對路徑類,比如:
>>> doc.xpath('/html/head/meta[@name="robots"]') #絕對路徑,從根節(jié)點開始
[<Element meta at 0x10f478ba8>]
>>> doc.xpath('head/meta[@name="robots"]') #相對路徑,從當(dāng)前節(jié)點開始
[<Element meta at 0x10f478ba8>]
如果想同時查詢多條路徑,可以使用或“|”操作符:
>>> doc.xpath('/html/head | /html/body')
[<Element head at 0x10f478c58>, <Element body at 0x10f478c00>]
軸(axis)
上面的路徑采用的都是縮寫的形式,其實它還有完全形式的寫法,比如:
>>> doc.xpath('/child::html/child::head/child::meta[@name="robots"]')
[<Element meta at 0x10f478ba8>]
在該寫法中,以child::meta[@name="robots"]為例,這一步是什么意思呢?對該步而言,上下文節(jié)點是head,該步的意思是從head的meta類型的子節(jié)點中選取name屬性取值為robots的節(jié)點,其中child是axis的名字,meta是要選擇的節(jié)點類型,@name="robots"是要滿足的條件。事實上,每一步都由這三部分構(gòu)成的,它們的作用:
一個軸(axis):指明該步要選取的節(jié)點跟當(dāng)前節(jié)點的關(guān)系,例如上面的child說明要選取當(dāng)前節(jié)點的子節(jié)點
一個節(jié)點測試(node test):指明這個路徑步要選取的節(jié)點類型,比如上面child::meta要選取的是meta類型的節(jié)點
零個或多個謂詞(predicates)組成:起過濾作用、選取特定節(jié)點,比如上面[@name="robots"]要篩選屬性值為robots的節(jié)點
除了child axis, xpath還定義了很多其他的axis,請看下表:
看下面一些例子:
1) 獲取子節(jié)點:getchildren()等價于child::*
>>> doc.xpath('child::*')
[<Element head at 0x10e8bad60>, <Element body at 0x10e8e5d60>]
>>> doc.getchildren()
[<Element head at 0x10e8bad60>, <Element body at 0x10e8e5d60>]
2) 獲取當(dāng)前節(jié)點:"."等價于 self::node()
>>> doc.xpath(".")
[<Element html at 0x10dc1d4c8>]
>>> doc.xpath("self::node()")
[<Element html at 0x10dc1d4c8>]
3) 獲取父節(jié)點:".."等價于parent::node()
>>> doc.head.xpath("..")
[<Element html at 0x10dc1d4c8>]
>>> doc.head.xpath("parent::node()")
[<Element html at 0x10dc1d4c8>]
4)ancestor軸和descendant軸
分別代表當(dāng)前元素所有祖先元素、所有后代元素,比如:
>>> meta.xpath('ancestor::*')
[<Element html at 0x10dc1d4c8>, <Element head at 0x10e8bad60>]
>>> meta.xpath('ancestor::head')
[<Element head at 0x10e8bad60>]
>>> doc.xpath('descendant::table')
>>> doc.xpath('descendant::table[@id="tcdatafields"]')
>>> doc.xpath('//table[@id="tcdatafields"]')
5)ancestor-or-self 和 descendant-or-self軸
分別表示當(dāng)前元素或其所有祖先元素、當(dāng)前元素或其所有后代元素,比如:
>>> meta.xpath('ancestor-or-self::*')
[<Element html at 0x10dc1d4c8>, <Element head at 0x10e8bad60>, <Element meta at 0x10e8bae68>]
6)child和parent軸
分別表示當(dāng)前元素所有子元素、父元素:
>>> doc.xpath('child::*')
[<Element head at 0x10e8bad60>, <Element body at 0x10e8baf18>]
>>> doc.xpath('child::head')
[<Element head at 0x10e8bad60>]
>>> head.xpath('child::meta[1]')
[<Element meta at 0x10e8baf18>]
>>> head.xpath('child::meta[position()<3]')
[<Element meta at 0x10e8baf18>, <Element meta at 0x10e8bad08>]
7)attribute軸
表示當(dāng)前元素的所有屬性,例如下面是meta元素的name和content兩個屬性以及取值:
>>> meta.items()
[('name', 'googlebot'), ('content', 'index, follow')]
獲取所有屬性取值:
>>> meta.xpath('attribute::*')
['googlebot', 'index, follow']
獲取name屬性的取值:
>>> meta.xpath('attribute::name')
['googlebot']
8)following和preceding
分別表示當(dāng)前元素的所有后繼元素、前置元素,比如:
>>> meta.xpath('following::*')
>>> meta.xpath('preceding::*')
9)following-sibling和preceding-sibling軸
分別表示當(dāng)前元素的所有平級后繼元素、平級前置元素,比如:
>>> meta.xpath('preceding-sibling::*')
>>> meta.xpath('following-sibling::*')
10)self軸
表示當(dāng)前元素自身
>>> doc.xpath("self::*")
[<Element html at 0x10dc1d4c8>]
使用謂詞(predicates)
謂詞就是step中使用中括號[...]定義的那部分,使用謂詞能實現(xiàn)精確查找,看下面的例子:
>>> doc.xpath('/html/head/meta')
[<Element meta at 0x10e8baf70>, <Element meta at 0x10e8bae10>, <Element meta at 0x10e8bacb0>, <Element meta at 0x10e8baf18>, <Element meta at 0x10e8bad08>, <Element meta at 0x10e8bafc8>, <Element meta at 0x10e8bae68>]
1) 位置謂詞
>>> doc.xpath('/html/head/meta[1]')
[<Element meta at 0x10e8baf70>]
>>> doc.xpath('/html/head/meta[2]')
[<Element meta at 0x10e8bae10>]
>>> doc.xpath('/html/head/meta[last()]')
[<Element meta at 0x10e8bae68>]
>>> doc.xpath('/html/head/meta[last()-1]')
[<Element meta at 0x10e8bae10>]
>>> doc.xpath('/html/head/meta[position()<3]')
[<Element meta at 0x10e8baf70>, <Element meta at 0x10e8bae10>]
注:這里使用了last()和position()兩個函數(shù),xpath還支持更多的函數(shù),結(jié)合這些函數(shù)可以獲得非常強大的處理能力。
2) 屬性謂詞
含有屬性name的meta元素:
>>> doc.xpath('/html/head/meta[@name]')
[<Element meta at 0x10e8bacb0>, <Element meta at 0x10e8baf70>, <Element meta at 0x10e8bae10>, <Element meta at 0x10e8bae68>]
含有屬性name而且其取值為robots的meta元素:
>>> doc.xpath('/html/head/meta[@name="robots"]')
[<Element meta at 0x10e8bacb0>]
含有任意屬性的meta元素:
>>> doc.xpath('/html/head/meta[@*]')
3) 函數(shù)謂詞
xpath內(nèi)置很多函數(shù),靈活使用這些函數(shù),可以極大提升查找效率,比如:
-使用 text()函數(shù)
>>> doc.xpath('//td[text()="2017-03-21"]')
[<Element td at 0x10e8bacb0>]
- 使用contains函數(shù)
>>> [ td.text for td in doc.xpath('//td[contains(text(), "2017-03-2")]')]
['2017-03-29', '2017-03-28', '2017-03-27', '2017-03-24', '2017-03-23', '2017-03-22', '2017-03-21', '2017-03-20']
- 使用starts-with函數(shù)
>>> [ td.text for td in doc.xpath('//td[starts-with(text(),"2017-02-2")]')]
['2017-02-28', '2017-02-27', '2017-02-24', '2017-02-23', '2017-02-22', '2017-02-21', '2017-02-20']
>>> [ td.text for td in doc.xpath('//td[text()>21.0 and text()<23.0]')]
['21.02']
>>> [ td.text for td in doc.xpath('//td[text()< -2.5 or text()>21.0]')]
['21.02', '-2.64']
通配符
xpath也支持通配符"*",其中'*"可以匹配任何標(biāo)簽元素,"@*"可以匹配任何元素屬性,node()可以匹配任何節(jié)點:
>>> head.xpath('./*')
[<Element title at 0x10e8baf18>, <Element meta at 0x10e8bacb0>, <Element meta at 0x10e8baf70>, <Element meta at 0x10e8bad08>, <Element meta at 0x10e8bafc8>, <Element meta at 0x10e8bae10>, <Element meta at 0x10e8c6050>, <Element meta at 0x10e8bae68>, <Element link at 0x10e8c60a8>, <Element link at 0x10e8c6100>]
>>> head.xpath('./meta[@*]')
[<Element meta at 0x10e8baf18>, <Element meta at 0x10e8bacb0>, <Element meta at 0x10e8baf70>, <Element meta at 0x10e8bad08>, <Element meta at 0x10e8bafc8>, <Element meta at 0x10e8bae10>, <Element meta at 0x10e8bae68>]
>>> head.xpath('./node()')
['\r\n', <Element title at 0x10e8badb8>, '\r\n', <Element meta at 0x10e8baf18>, '\r\n', <Element meta at 0x10e8bacb0>, '\r\n', <Element meta at 0x10e8baf70>, '\r\n', <Element meta at 0x10e8bad08>, '\r\n', <Element meta at 0x10e8bafc8>, '\r\n', <Element meta at 0x10e8bae10>, '\r\n', <Element meta at 0x10e8bae68>, '\r\n', <Element link at 0x10e8c6050>, '\n', <Element link at 0x10e8c60a8>, '\r\n']
今天就寫這么多。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。