- Python爬蟲開發(fā)與項目實戰(zhàn)
- 范傳輝
- 12073字
- 2019-01-05 01:17:28
第2章 Web前端基礎(chǔ)
爬蟲主要是和網(wǎng)頁打交道,了解Web前端的知識是非常重要的。Web前端的知識范圍非常廣泛,不可能面面俱到和深入講解,本章主要是抽取Web前端中和爬蟲相關(guān)的知識點進行講解,幫助讀者了解這些必備的知識,為之后的Python爬蟲開發(fā)打下基礎(chǔ)。
2.1 W3C標(biāo)準(zhǔn)
如果說你只知道Web前端的一個標(biāo)準(zhǔn),估計肯定是W3C標(biāo)準(zhǔn)了。W3C,即萬維網(wǎng)聯(lián)盟,是Web技術(shù)領(lǐng)域最具權(quán)威和影響力的國際中立性技術(shù)標(biāo)準(zhǔn)機構(gòu)。萬維網(wǎng)聯(lián)盟(W3C)標(biāo)準(zhǔn)不是某一個標(biāo)準(zhǔn),而是一系列標(biāo)準(zhǔn)的集合。網(wǎng)頁主要由三部分組成:結(jié)構(gòu)(Structure)、表現(xiàn)(Presentation)和行為(Behavior)。對應(yīng)的標(biāo)準(zhǔn)也分三方面:結(jié)構(gòu)化標(biāo)準(zhǔn)語言主要包括XHTML和XML,表現(xiàn)標(biāo)準(zhǔn)語言主要包括CSS,行為標(biāo)準(zhǔn)主要包括對象模型(如W3C DOM)、ECMAScript等。本節(jié)我們主要講解HTML、CSS、JavaScript、Xpath和JSON等5個部分,基本上覆蓋了爬蟲開發(fā)中需要了解的Web前端基本知識。
2.1.1 HTML
什么是HTML標(biāo)記語言?HTML不是編程語言,是一種表示網(wǎng)頁信息的符號標(biāo)記語言。標(biāo)記語言是一套標(biāo)記,HTML使用標(biāo)記來描述網(wǎng)頁。Web瀏覽器的作用是讀取HTML文檔,并以網(wǎng)頁的形式顯示出它們。瀏覽器不會顯示HTML標(biāo)記,而是使用標(biāo)記來解釋頁面的內(nèi)容。HTML語言的特點包括:
□ 可以設(shè)置文本的格式,比如標(biāo)題、字號、文本顏色、段落,等等。
□ 可以創(chuàng)建列表。
□ 可以插入圖像和媒體。
□ 可以建立表格。
□ 超鏈接,可以使用鼠標(biāo)點擊超鏈接來實現(xiàn)頁面之間的跳轉(zhuǎn)。
下面從HTML的基本結(jié)構(gòu)、文檔設(shè)置標(biāo)記、圖像標(biāo)記、表格和超鏈接五個方面講解。
1.HTML的基本結(jié)構(gòu)
首先在瀏覽器上訪問google網(wǎng)站(如圖2-1所示),右鍵查看源代碼,如圖2-2所示。

圖2-1 谷歌網(wǎng)站首頁

圖2-2 谷歌首頁源代碼
從谷歌首頁的源代碼中可以分析出HTML的基本結(jié)構(gòu):
□ <html>內(nèi)容</html>:HTML文檔是由<html></html>包裹,這是HTML文檔的文檔標(biāo)記,也稱為HTML開始標(biāo)記。這對標(biāo)記分別位于網(wǎng)頁的最前端和最后端,<html>在最前端表示網(wǎng)頁的開始,</html>在最后端表示網(wǎng)頁的結(jié)束。
□ <head>內(nèi)容</head>:HTML文件頭標(biāo)記,也稱為HTML頭信息開始標(biāo)記。用來包含文件的基本信息,比如網(wǎng)頁的標(biāo)題、關(guān)鍵字,在<head></head>內(nèi)可以放<title></title>、<meta></meta>、<style></style>等標(biāo)記。注意:在<head></head>標(biāo)記內(nèi)的內(nèi)容不會在瀏覽器中顯示。
□ <title>內(nèi)容</title>:HTML文件標(biāo)題標(biāo)記。網(wǎng)頁的“主題”,顯示在瀏覽器的窗口的左上邊。
□ <body>內(nèi)容</body>:<body>...</body>是網(wǎng)頁的主體部分,在此標(biāo)記之間可以包含如<p></p>、<h1></h1>、<br>、<hr>等等標(biāo)記,正是由這些內(nèi)容組成了我們所看見的網(wǎng)頁。
□ <meta>內(nèi)容</meta>:頁面的元信息(meta-information)。提供有關(guān)頁面的元信息,比如針對搜索引擎和更新頻度的描述和關(guān)鍵詞。注意meta標(biāo)記必須放在head元素里面。
2.文檔設(shè)置標(biāo)記
文檔設(shè)置標(biāo)記分為格式標(biāo)記和文本標(biāo)記。下面通過一個標(biāo)準(zhǔn)的HTML文檔對格式標(biāo)記進行講解,文檔如下所示:
<html> <head> <title>Python爬蟲開發(fā)與項目實戰(zhàn)</title> <meta charset="UTF-8"> </head> <body> 文檔設(shè)置標(biāo)記<br> <p>這是段落。</p> <p>這是段落。</p> <p>這是段落。</p> <hr> <center>居中標(biāo)記1</center> <center>居中標(biāo)記2</center> <hr> <pre> [00:00](music) [00:28]你我皆凡人,生在人世間; [00:35]終日奔波苦,一刻不得閑; [00:43]既然不是仙,難免有雜念; </pre> <hr> <p> [00:00](music) [00:28]你我皆凡人,生在人世間; [00:35]終日奔波苦,一刻不得閑; [00:43]既然不是仙,難免有雜念; </p> <hr> <br> <ul> <li>Coffee</li> <li>Milk</li> </ul> <ol type="A"> <li>Coffee</li> <li>Milk</li> </ol> <dl> <dt>計算機</dt> <dd>用來計算的儀器... ...</dd> <dt>顯示器</dt> <dd>以視覺方式顯示信息的裝置... ...</dd> </dl> <div > <h3>這是標(biāo)題</h3> <p>這是段落。</p> </div> </body> </html>
在瀏覽器中打開運行,效果如圖2-3所示。

圖2-3 運行效果圖
格式標(biāo)記包括:
□ <br>:強制換行標(biāo)記。讓后面的文字、圖片、表格等等,顯示在下一行。
□ <p>:換段落標(biāo)記。換段落,由于多個空格和回車在HTML中會被等效為一個空格,所以HTML中要換段落就要用<p>, <p>段落中也可以包含<p>段落。例如:<p>This is a paragraph.</p>。
□ <center>:居中對齊標(biāo)記。讓段落或者是文字相對于父標(biāo)記居中顯示。
□ <pre>:預(yù)格式化標(biāo)記。保留預(yù)先編排好的格式,常用來定義計算機源代碼。和<p>進行一下對比,就可以理解。
□ <li>:列表項目標(biāo)記。每一個列表使用一個<li>標(biāo)記,可用在有序列表(<ol>)和無序列表(<ul>)中。
□ <ul>:無序列表標(biāo)記。<ul>聲明這個列表沒有序號。
□ <ol>:有序列表標(biāo)記。可以顯示特定的一些順序。有序列表的type屬性值"1"表示阿拉伯?dāng)?shù)字1.2.3等等;默認type屬性值"A"表示大小字母A、B、C等等;上面的程序使用屬性"a",這表示小寫字母a、b、c等等;"Ⅰ"表示大寫羅馬數(shù)字Ⅰ、Ⅱ、Ⅲ、Ⅳ等等;"ⅰ"表示小寫羅馬數(shù)字ⅰ、ⅱ、ⅲ、ⅳ等等。注意:列表可以進行嵌套。
□ <dl><dt><dd>:定義型列表。對列表條目進行簡短說明。
□ <hr>:水平分割線標(biāo)記。可以用作段落之間的分割線。
□ <div>:分區(qū)顯示標(biāo)記,也稱為層標(biāo)記。常用來編排一大段的HTML段落,也可以用于將表格式化,和<p>很相似,可以多層嵌套使用。
接下來通過一個HTML文檔對文本標(biāo)記進行講解,文檔如下所示:
<html> <head> <title>Python爬蟲開發(fā)與項目實戰(zhàn)</title> <meta charset="UTF-8"> </head> <body> Hn標(biāo)題標(biāo)記---->> <br> <h1>Python爬蟲</h1> <h2>Python爬蟲</h2> <h3>Python爬蟲</h3> <h4>Python爬蟲</h4> <h5>Python爬蟲</h5> <h6>Python爬蟲</h6> font標(biāo)記---->> <font size="1">Python爬蟲</font> <font size="3">Python爬蟲</font> <font size="7">Python爬蟲</font> <font size="7" color="red" face="微軟雅黑">Python爬蟲</font> <font size="7" color="red" face="宋體">Python爬蟲</font> <font size="7" color="red" face="新細明體">Python爬蟲</font> <br> B標(biāo)記加粗---->> <b>Python爬蟲</b> <br> i標(biāo)記斜體---->> <i>Python爬蟲</i> <br> sub下標(biāo)標(biāo)記---->> 2<sub>2</sub> <br> sup上標(biāo)標(biāo)記---->> 2<sup>2</sup> <br> 引用標(biāo)記---->> <cite>Python爬蟲</cite> <br> em標(biāo)記表示強調(diào),顯示為斜體---->> <em>Python爬蟲</em> <br> strong標(biāo)記表示強調(diào),加粗顯示---->> <strong>Python爬蟲</strong> <br> small標(biāo)記,可以顯示小一號字體,可以嵌套使用---->> <small>Python爬蟲</small> <small><small>Python爬蟲</small></small> <small><small><small>Python爬蟲</small></small></small> <br> big標(biāo)記,顯示大一號的字體---->> <big>Python爬蟲</big> <big><big>Python爬蟲</big></big> <br> u標(biāo)記是顯示下劃線---->> <big><big><big><u>Python爬蟲</u></big></big></big> <br> </body> </html>
在瀏覽器中打開運行,效果如圖2-4所示。

圖2-4 運行效果圖
其中文本標(biāo)記包括:
□ <hn>:標(biāo)題標(biāo)記。共有6個級別,n的范圍為1~6,不同級別對應(yīng)不同顯示大小的標(biāo)題,h1最大,h6最小。
□ <font>:字體設(shè)置標(biāo)記。用來設(shè)置字體的格式,一般有三個常用屬性:size(字體大小), <font size="14px">; color(顏色), <font color="red">; face(字體), <font face="微軟雅黑">。
□ <b>:粗字體標(biāo)記。
□ <i>:斜字體標(biāo)記。
□ < sub>:文字下標(biāo)字體標(biāo)記。
□ <sup>:文字上標(biāo)字體標(biāo)記。
□ <tt>:打印機字體標(biāo)記。
□ <cite>:引用方式的字體,通常是斜體。
□ <em>:表示強調(diào),通常顯示為斜體字。
□ <strong>:表示強調(diào),通常顯示為粗體字。
□ <small>:小型字體標(biāo)記。
□ <big>:大型字體標(biāo)記。
□ <u>:下劃線字體標(biāo)記。
3.圖像標(biāo)記
<img>稱為圖像標(biāo)記,用來在網(wǎng)頁中顯示圖像。使用方法為:<img src="路徑/文件名.圖片格式"width="屬性值"height="屬性值"border="屬性值"alt="屬性值">。<img>標(biāo)記主要包括以下屬性:
□ src屬性用來指定我們要加載的圖片的路徑、圖片的名稱以及圖片格式。
□ width屬性用來指定圖片的寬度,單位為px、em、cm、mm。
□ height屬性用來指定圖片的高度,單位為px、em、cm、mm。
□ border屬性用來指定圖片的邊框?qū)挾龋瑔挝粸閜x、em、cm、mm。
□ alt屬性有三個作用:1)當(dāng)網(wǎng)頁上的圖片被加載完成后,鼠標(biāo)移動到上面去,會顯示這個圖片指定的屬性文字;2)如果圖像沒有下載或者加載失敗,會用文字來代替圖像顯示;3)搜索引擎可以通過這個屬性的文字來抓取圖片。
我們可以在瀏覽器上訪問博客園首頁,對博客園首頁的圖片進行審查,就可以看到的img標(biāo)記的使用方法,如圖2-5所示。

圖2-5 img標(biāo)記
注意
<img>為單標(biāo)記,不需要使用</img>閉合。在加載圖像文件的時候,文件的路徑、文件名或者文件格式錯誤,將無法加載圖片。
4.超鏈接的使用
爬蟲開發(fā)中經(jīng)常需要抽取鏈接,鏈接的引用使用的是<a>標(biāo)記。
<a>標(biāo)記的基本語法:<a href="鏈接地址"target="打開方式"name="頁面錨點名稱">鏈接文字或者圖片</a>。<a>標(biāo)記主要包括以下屬性:
□ href屬性值是鏈接的地址,鏈接的地址可以是一個網(wǎng)頁,也可以是一個視頻、圖片、音樂等。
□ target屬性用來定義超鏈接的打開方式。當(dāng)屬性值為_blank時,作用是在一個新的窗口中打開鏈接;當(dāng)屬性值為_self(默認值)時,作用是在當(dāng)前窗口中打開鏈接;當(dāng)屬性值為_parent時,作用是在在父窗口中打開頁面;當(dāng)屬性值為_top時,在頂層窗口中打開文件。
□ name屬性用來指定頁面的錨點名稱。
5.表格
表格的基本結(jié)構(gòu)包括<table>、<caption>、<tr>、<td>和<th>等標(biāo)記。
<table>標(biāo)記的基本格式為<table屬性1="屬性值1"屬性2="屬性值2"......>表格內(nèi)容</table>。table標(biāo)記有以下常見屬性:
□ width屬性:表示表格的寬度,它的值可以是像素(px)也可以是父級元素的百分比(%)。
□ height屬性:表示表格的高度,它的值可以是像素(px)也可以是父級元素的百分比(%)。
□ border屬性:表示表格外邊框的寬度。
□ align屬性用來表示表格的顯示位置。left居左顯示,center居中顯示,right居右顯示。
□ cellspacing屬性:單元格之間的間距,默認是2px,單位為像素。
□ cellpadding屬性:單元格內(nèi)容與單元格邊框的顯示距離,單位為像素。
□ frame屬性用來控制表格邊框最外層的四條線框。void(默認值)表示無邊框;above表示僅頂部有邊框;below表示僅有底部邊框;hsides表示僅有頂部邊框和底部邊框;lhs表示僅有左側(cè)邊框;rhs表示僅有右側(cè)邊框;vsides表示僅有左右側(cè)邊框;border表示包含全部4個邊框。
□ rules屬性用來控制是否顯示以及如何顯示單元格之間的分割線。屬性值none(默認值)表示無分割線;all表示包括所有分割線;rows表示僅有行分割線;clos表示僅有列分割線;groups表示僅在行組和列組之間有分割線。
<caption>標(biāo)記用于在表格中使用標(biāo)題。<caption>屬性的插入位置,直接位于<table>屬性之后,<tr>表格行之前。<caption>標(biāo)記中align屬性可以取四個值:top表示標(biāo)題放在表格的上部;bottom表示標(biāo)題放在表格的下部;left表示標(biāo)題放在表格的左部;right表示標(biāo)題放在表格的右部。
<tr>標(biāo)記用來定義表格的行,對于每一個表格行,都是由一對<tr>...</tr>標(biāo)記表示,每一行<tr>標(biāo)記內(nèi)可以嵌套多個<td>或者<th>標(biāo)記。<tr>標(biāo)記中的常見屬性包括:
□ bgcolor屬性用來設(shè)置背景顏色,格式為bgcolor="顏色值"。
□ align屬性用來設(shè)置垂直方向?qū)R方式,格式為align="值"。值為bottom時,表示靠頂端對齊;值為top時,表示靠底部對齊;值為middle時,表示居中對齊。
□ valign屬性用來設(shè)置水平方向?qū)R方式,格式為valign="值"。值為left時,表示靠左對齊;值為right時,表示靠右對齊;值為center時,表示居中對齊。
<td>和<th>都是單元格的標(biāo)記,其必須嵌套在<tr>標(biāo)記內(nèi),成對出現(xiàn)。<th>是表頭標(biāo)記,通常位于首行或者首列,<th>中的文字默認會被加粗,而<td>不會。<td>是數(shù)據(jù)標(biāo)記,表示該單元格的具體數(shù)據(jù)。<td>和<th>兩者的標(biāo)記屬性都是一樣的,常用屬性如下:
□ bgcolor設(shè)置單元格背景。
□ align設(shè)置單元格對齊方式。
□ valign設(shè)置單元格垂直對齊方式。
□ width設(shè)置單元格寬度。
□ height設(shè)置單元格高度。
□ rowspan設(shè)置單元格所占行數(shù)。
□ colspan設(shè)置單元格所占列數(shù)。
下面通過一個HTML文檔來演示表格的使用,文檔如下:
<html> <head> <title>學(xué)生信息表</title> <meta charset="UTF-8"> </head> <body> <table width="960" align="center" border="1" rules="all" cellpadding="15"> <tr> <th>學(xué)號</th> <th>班級</th> <th>姓名</th> <th>年齡</th> <th>籍貫</th> </tr> <tr align="center"> <td>1500001</td> <td>(1)班</td> <td>張三</td> <td>16</td> <td>上海</td> </tr> <tr align="center"> <td>1500011</td> <td>(2)班</td> <td>李四</td> <td>15</td> <td bgcolor="# ccc">浙江</td> </tr> </table> <br/> <table width="960" align="center" border="1" rules="all" cellpadding= "15"> <tr bgcolor="# ccc"> <th>學(xué)號</th> <th>班級</th> <th>姓名</th> <th>年齡</th> <th>籍貫</th> </tr> <tr align="center"> <td>1500001</td> <td>(1)班</td> <td>張三</td> <td>16</td> <td bgcolor="red"><font color="white">上海</font></td> </tr> <tr align="center"> <td>1500011</td> <td>(2)班</td> <td>李四</td> <td>15</td> <td>浙江</td> </tr> </table> </body> </html>
在瀏覽器中打開運行,效果如圖2-6所示。

圖2-6 表格運行效果圖
2.1.2 CSS
CSS指層疊樣式表(Cascading Style Sheets),用來定義如何顯示HTML元素,一般和HTML配合使用。CSS樣式表的目的是為了解決內(nèi)容與表現(xiàn)分離的問題,即使同一個HTML文檔也能表現(xiàn)出外觀的多樣化。在HTML中使用CSS樣式的方式,一般有三種做法:
□ 內(nèi)聯(lián)樣式表:CSS代碼直接寫在現(xiàn)有的HTML標(biāo)記中,直接使用style屬性改變樣式。例如,<body style="background-color:green; margin:0; padding:0; "></body>。
□ 嵌入式樣式表:CSS樣式代碼寫在<style type="text/css"></style>標(biāo)記之間,一般情況下嵌入式CSS樣式寫在<head></head>之間。
□ 外部樣式表:CSS代碼寫一個單獨的外部文件中,這個CSS樣式文件以“.css”為擴展名,在<head>內(nèi)(不是在<style>標(biāo)記內(nèi))使用<link>標(biāo)記將CSS樣式文件鏈接到HTML文件內(nèi)。例如,<link rel="StyleSheet" type="text/css" href="style.css">。
CSS規(guī)則由兩個主要的部分構(gòu)成:選擇器,以及一條或多條聲明。選擇器通常是需要改變樣式的HTML元素。每條聲明由一個屬性和一個值組成。屬性(property)是希望設(shè)置的樣式屬性(style attribute)。每個屬性有一個值。屬性和值由冒號分開。例如:h1 { color : blue ;font-size : 12px}。其中h1為選擇器,color和font-size是屬性,blue和12px是屬性值,這句話的意思是將h1標(biāo)記中的顏色設(shè)置為藍色,字體大小為12px。根據(jù)選擇器的定義方式,可以將樣式表的定義分成三種方式:
□ HTML標(biāo)記定義:上面舉的例子就是使用的這種方式。假如想修改<p>...</p>的樣式,可以定義CSS:p{屬性:屬性值;屬性1:屬性值1}。p可以叫做選擇器,定義了標(biāo)記中內(nèi)容所執(zhí)行的樣式。一個選擇器可以控制若干個樣式屬性,他們之間需要用英語的“; ”隔開,最后一個可以不加“; ”。
□ ID選擇器定義:ID選擇器可以為標(biāo)有特定ID的HTML元素指定特定的樣式。HTML元素以ID屬性來設(shè)置ID選擇器,CSS中ID選擇器以"#"來定義。假如定義為#word{text-align:center; color:red; },就將HTML中ID為word的元素設(shè)置為居中,顏色為紅色。
□ class選擇器定義:class選擇器用于描述一組元素的樣式,class選擇器有別于ID選擇器,它可以在多個元素中使用。class選擇器在HTML中以class屬性表示,在CSS中,class選擇器以一個點“.”號顯示。例如,.center{text-align:center; }將所有擁有center類的HTML元素設(shè)為居中。當(dāng)然也可以指定特定的HTML元素使用class,例如,p.center{text-align:center; }是對所有的p元素使用class="center",讓該元素的文本居中。
介紹完選擇器,接著說一下CSS中一些常見的屬性。常見屬性主要說明一下顏色屬性、字體屬性、背景屬性、文本屬性和列表屬性。
1.顏色屬性
顏色屬性color用來定義文本的顏色,可以使用以下方式定義顏色:
□ 顏色名稱,如color:green。
□ 十六進制,如color:#ff6600。
□ 簡寫方式,如color:#f60。
□ RGB方式,如rgb(255,255,255),紅(R)、綠(G)、藍(B)的取值范圍均為0~255
□ RGBA方式,如color:rgba(255,255,255,1), RGBA表示Red(紅色)、Green(綠色)、Blue(藍色)和Alpha的(色彩空間)透明度。
2.字體屬性
可以使用字體屬性定義文本形式,有如下方法:
□ font-size定義字體大小,如font-size:14px。
□ font-family定義字體,如font-family:微軟雅黑,serif。字體之間可以使用“, ”隔開,以確保當(dāng)字體不存在的時候直接使用下一個字體。
□ font-weight定義字體加粗,取值有兩種方式。一種是使用名稱,如normal(默認值)、bold(粗)、bolder(更粗)、lighter(更細);一種是使用數(shù)字,如100、200、300~900, 400=normal,而700=bold。
3.背景屬性
可以用背景屬性定義背景顏色、背景圖片、背景重復(fù)和背景的位置,內(nèi)容如下:
□ background-color用來定義背景的顏色,用法參考顏色屬性。
□ background-image用來定義背景圖片,如background-image:url(圖片路徑),也可以設(shè)置為background-image:none,表示不使用圖片。
□ background-repeat用來定義背景重復(fù)方式。取值為repeat,表示整體重復(fù)平鋪;取值為repeat-x,表示只在水平方向平鋪;取值為repeat-y,表示只在垂直方向平鋪;取值為no-repeat,表示不重復(fù)。
□ background-position用來定義背景位置。在橫向上,可以取left、center、right;在縱向上可以取top、center、bottom。
□ 簡寫方式可以簡化背景屬性的書寫,同時定義多個屬性,格式為background:背景顏色url(圖像)重復(fù)位置。如background:#f60 url(images/bg、jpg) no-repeat top center。
4.文本屬性
可以用文本屬性設(shè)置行高、縮進和字符間距,具體如下:
□ text-align設(shè)置文本對齊方式,屬性值可以取left、center、right。
□ line-height設(shè)置文本行高,屬性值可以取具體數(shù)值,來設(shè)置固定的行高值。也可以取百分比,是基于字體大小的百分比行高。
□ text-indent代表首行縮進,如text-indent:50px,意思是首行縮進50個像素。
□ letter-spacing用來設(shè)置字符間距。屬性值默認是normal,規(guī)定字符間沒有額外的空間;可以設(shè)置具體的數(shù)值(可以是負值),如letter-spacing: 3px;可以取inherit,從父元素繼承l(wèi)etter-spacing屬性的值。
5.列表
在HTML中,有兩種類型的列表:無序和有序。其實使用CSS,可以列出進一步的樣式,并可用圖像作列表項標(biāo)記。接下來主要講解以下幾種屬性:
□ list-style-type用來指明列表項標(biāo)記的類型。常用的屬性值有:none(無標(biāo)記)、disc(默認,標(biāo)記是實心圓)、circle(標(biāo)記是空心圓)、square(標(biāo)記是實心方塊)、decimal(標(biāo)記是數(shù)字)、decimal-leading-zero(0開頭的數(shù)字標(biāo)記)、lower-roman(小寫羅馬數(shù)字i、ii、iii、iv、v等)、upper-roman(大寫羅馬數(shù)字I、II、III、IV、V等)、lower-alpha(小寫英文字母a、b、c、d、e等)、upper-alpha(大寫英文字母A、B、C、D、E等)。例如,ul.a{list-style-type: circle; }是將class選擇器的值為a的ul標(biāo)記設(shè)置為空心圓標(biāo)記。
□ list-style-position用來指明列表項中標(biāo)記的位置。屬性值可以取inside、outside和inherit。inside指的是列表項標(biāo)記放置在文本以內(nèi),且環(huán)繞文本根據(jù)標(biāo)記對齊。outside為默認值,保持標(biāo)記位于文本的左側(cè),列表項標(biāo)記放置在文本以外,且環(huán)繞文本不根據(jù)標(biāo)記對齊。inherit規(guī)定應(yīng)該從父元素繼承l(wèi)ist-style-position屬性的值。
□ list-style-image用來設(shè)置設(shè)置圖像列表標(biāo)記。屬性值可以為URL(圖像的路徑)、none(默認無圖形被顯示)、inherit(從父元素繼承l(wèi)ist-style-image屬性的值)。例如,ul{list-style-image:url('image.gif'); },意思是給ul標(biāo)記前面的標(biāo)記設(shè)置為image.gif圖片。
以上就將關(guān)于CSS的基本知識講解完成了,接下來通過一個綜合的例子將所有知識點進行融合,采用嵌入式樣式表的方式,HTML文檔如下:
<! DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Python爬蟲開發(fā)</title> <style> h1 { background-color:# 6495ed; /*--背景顏色--*/ color:red; /* 字體顏色 */ text-align:center; /* 文本居中 */ font-size:40px; /* 字體大小*/ } p { background-color:# e0ffff; text-indent:50px; /* 首行縮進 */ font-family:"Times New Roman", Times, serif; /* 設(shè)置字體 */ } p.ex {color:rgb(0,0,255); } div { background-color:# b0c4de; } ul.a {list-style-type:square; } ol.b {list-style-type:upper-roman; } ul.c{list-style-image:url('http://www.cnblogs.com/images/logo_small.gif'); } </style> </head> <body> <h1>CSS background-color演示</h1> <div> 該文本插入在div元素中。 <p>該段落有自己的背景顏色。</p> <p class="ex">這是一個類為"ex"的段落。這個文本是藍色的。</p> 我們?nèi)匀辉谕粋€div中。 </div> <p>無序列表實例:</p> <ul class="a"> <li>Coffee</li> <li>Tea</li> <li>Coca Cola</li> </ul> <p>有序列表實例:</p> <ol class="b"> <li>Coffee</li> <li>Tea</li> <li>Coca Cola</li> </ol> <p>圖片列表示例</p> <ul class="c"> <li>Coffee</li> <li>Tea</li> <li>Coca Cola</li> </ul> </body> </html>
在瀏覽器中打開文檔,通過運行效果和之前的知識點進行對比,將更加容易理解。效果如圖2-7所示。

圖2-7 運行效果圖
2.1.3 JavaScript
JavaScript是一種輕量級的腳本語言,和Python語言是一樣的,只不過JavaScript是由瀏覽器進行解釋執(zhí)行。JavaScript可以插入HTML頁面中,可由所有的現(xiàn)代瀏覽器執(zhí)行。由于JavaScript是一門新的編程語言,知識點很多,本節(jié)不進行深入講解,主要介紹一下JavaScript的用法和基本語法。大家如果想深入學(xué)習(xí),需要額外看一些教程。
如何使用JavaScript呢?主要有直接插入代碼和外部引用js文件兩種做法:
1)直接插入代碼。在<script></script>標(biāo)記中編寫代碼。JavaScript代碼可以直接嵌在網(wǎng)頁的任何地方,不過通常我們都把JavaScript代碼放到<head>中,示例如下:
<html> <head> <script type='text/javascript'> alert('Hello, world'); </script> </head> <body> python爬蟲 </body> </html>
<script>標(biāo)記中包含的就是JavaScript代碼,可以直接被瀏覽器執(zhí)行,彈出一個警告框。
2)外部引用js文件。把JavaScript代碼放到一個單獨的.js文件,然后在HTML中通過<script src=’目標(biāo)文檔的URL'></script>的方式來引入js文件,其中目標(biāo)文檔的URL即是鏈接外部的js文件。示例如下:
<html> <head> <script src="/static/js/jquery.js"></script> </head> <body> python爬蟲 </body> </html>
這樣/static/js/jquery.js就會被瀏覽器執(zhí)行。把JavaScript代碼放入一個單獨的.js文件中更利于維護代碼,并且多個頁面可以各自引用同一份.js文件,減少程序員編碼量。在頁面中多次編寫JavaScript代碼,瀏覽器按照順序依次執(zhí)行。
一般在正常的開發(fā)中都是采用上述兩種做法結(jié)合的方式,之后在做Python爬蟲開發(fā)時會經(jīng)常見到。
為了能讓零基礎(chǔ)的讀者在讀完本節(jié)后能看懂簡單的JavaScript代碼,下面將從基本語法、數(shù)據(jù)類型和變量、運算符和操作符、條件判斷、循環(huán)和函數(shù)等六個方面介紹JavaScript基礎(chǔ)。
1.JavaScript基本語法
JavaScript嚴(yán)格區(qū)分大小寫,JavaScript會忽略關(guān)鍵字、變量名、數(shù)字、函數(shù)名或其他各種元素之間的空格、制表符或換行符。我們可以使用縮進、換行來使代碼整齊,提高可讀性。一條完整的語句如下:
var x = 1;
這條語句定義了一個x的變量。從這條語句中可以看到以分號“; ”作為結(jié)束。一行可以定義多條語句,但不推薦這么做。最后一個語句的分號可以省略,但盡量不要省略。示例語句如下:
var x = 1; var y = 2;
語句塊是一組語句的集合,使用{...}形成一個塊block。例如,下面的代碼先做了一個判斷,如果判斷成立,將執(zhí)行{...}中的所有語句:
var x = 2; var y = 1; if (x > y) { x = 3; y = 2; }
{...}還可以嵌套,形成層級結(jié)構(gòu)。將以上的代碼進行改造,程序如下:
var x = 2; var y = 1; if (x > y) { x = 3; y = 4; if(x<y){ x = 2; y = 1; } }
注釋主要分為單行注釋和多行注釋。單行注釋使用//作為注釋符,多行注釋使用/* */來注釋內(nèi)容。示例如下:
//var x = 2; var y = 1; /* var x = 2; var y = 1; */
2.?dāng)?shù)據(jù)類型和變量
和Python一樣,JavaScript也有自己的數(shù)據(jù)類型。在JavaScript中定義了以下幾種數(shù)據(jù)類型:
□ Number類型:JavaScript中不區(qū)分整數(shù)和浮點數(shù),統(tǒng)一使用Number表示。示例如下:100(整數(shù))、0.45(浮點數(shù))、1.234e3(科學(xué)計數(shù)法表示)、-10(負數(shù))、NaN(無法計算時候使用)、Infinity(無限大)、0xff(十六進制)。
□ 字符串類型:字符串是以單引號或雙引號括起來的任意文本,比如’abc', "xyz"等。
□ 布爾值類型:一個布爾值只有true、false兩種值。
□ 數(shù)組類型:數(shù)組是一組按順序排列的集合,集合的每個值稱為元素。JavaScript的數(shù)組可以包括任意數(shù)據(jù)類型,示例如下:var array = [1, 2, 3.14, 'Hello', null, true]。上述數(shù)組包含6個元素。數(shù)組用[]表示,元素之間用“, ”分隔。另一種創(chuàng)建數(shù)組的方法是通過Array()函數(shù)實現(xiàn),示例如下:var array = new Array(1, 2, 3)。數(shù)組的元素可以通過索引來訪問,索引的起始值為0。
□ 對象類型:javaScript的對象是一組由鍵-值組成的無序集合,類似Python中的字典。示例如下:var person = {name: 'qiye', age: 24, tags: ['python', 'web', 'hacker'], city: 'Beijing', man:true}。JavaScript對象的鍵都是字符串類型,值可以是任意數(shù)據(jù)類型。要獲取一個對象的屬性,我們用“對象變量.屬性名”的方式,如person. name。
JavaScript是弱類型的編程語言,聲明變量的時候都是使用關(guān)鍵字var,沒有int、char之說,為變量賦值時會自動判斷類型并進行轉(zhuǎn)換。變量名是大小寫英文、數(shù)字、“$”和“_”的組合,且不能用數(shù)字開頭。變量名也不能是JavaScript的關(guān)鍵字,如if、while等。申明一個變量用var語句,比如:vars_007 = '007'。
3.運算符和操作符
JavaScript中的運算符和操作符,與Python中的用法非常相似,表2-1總結(jié)了javaScript常用的運算符和操作符。
表2-1 運算符和操作符

4.條件判斷
JavaScript使用if(){...}else{...}來進行條件判斷,和C語言的使用方法一樣。例如,根據(jù)年齡顯示不同內(nèi)容,可以用if語句實現(xiàn)如下:
var role = 20; if (age >= 18) { alert('adult'); } else { alert('teenager'); }
5.循環(huán)
JavaScript的循環(huán)有兩種:一種是for循環(huán),一種是while循環(huán)。
首先說一下for循環(huán)。舉個例子,計算1到100相加之和,程序如下:
var x = 0; var i; for (i=1; i<=100; i++) { x = x + i; }
for循環(huán)常用來遍歷數(shù)組。另外for循環(huán)還有一個變體是for...in循環(huán),它可以把一個對象的所有屬性依次循環(huán)出來,示例如下:
var person = { name: 'qiye', age: 20, city: 'Beijing' }; for (var key in person ) { alert(key); // 'name', 'age', 'city' }
最后說一下while循環(huán)。使用方法和C語言一樣,分為while(){...}循環(huán)和do{...}while(),具體使用不再細說。
6.函數(shù)
在JavaScript中,定義函數(shù)使用function關(guān)鍵字,使用方式如下:
function add(x, y) { return x+y; }
上述add()函數(shù)的定義如下:
□ function指出這是一個函數(shù)定義;
□ add是函數(shù)的名稱。
□ (x, y)括號內(nèi)列出函數(shù)的參數(shù),多個參數(shù)以“, ”分隔。
□ {...}之間的代碼是函數(shù)體,可以包含若干語句,甚至可以沒有任何語句。
調(diào)用函數(shù)時,按順序傳入?yún)?shù)即可:add(10,9); //返回19。
由于JavaScript允許傳入任意個參數(shù)而不影響調(diào)用,因此傳入的參數(shù)比定義的參數(shù)多也沒有問題,雖然函數(shù)內(nèi)部并不需要這些參數(shù):add(10, 9, 'blablabla'); //返回19。
傳入的參數(shù)比定義的少也沒有問題:add(); //返回NaN。此時add(x, y)函數(shù)的參數(shù)x和y收到的值為undefined,計算結(jié)果為NaN。
2.1.4 XPath
XPath是一門在XML文檔中查找信息的語言,被用于在XML文檔中通過元素和屬性進行導(dǎo)航。XPath雖然是被設(shè)計用來搜尋XML文檔,不過它也能很好地在HTML文檔中工作,并且大部分瀏覽器也支持通過XPath來查詢節(jié)點。在Python爬蟲開發(fā)中,經(jīng)常使用XPath查找提取網(wǎng)頁中的信息,因此XPath非常重要。
XPath既然叫Path,就是以路徑表達式的形式來指定元素,這些路徑表達式和我們在常規(guī)的電腦文件系統(tǒng)中看到的表達式非常相似。由于XPath一開始是被用來搜尋XML文檔的,所以接下來就以XML文檔為例子來講解XPath。接下來從節(jié)點、語法、軸和運算符等四個方面講解XPath的使用。
1.XPath節(jié)點
在XPath中,XML文檔是被作為節(jié)點樹來對待的,有七種類型的節(jié)點:元素、屬性、文本、命名空間、處理指令、注釋以及文檔(根)節(jié)點。樹的根被稱為文檔節(jié)點或者根節(jié)點。以下面的XML文檔為例進行說明,文檔如下:
<? xml version="1.0" encoding="ISO-8859-1"? > <classroom> <student> <id>1001</id> <name lang="en">marry</name> <age>20</age> <country>China</country> </student> </classroom>
上面的XML文檔中的節(jié)點例子包括:<classroom>(文檔節(jié)點)、<id>1001</id>(元素節(jié)點)、lang="en"(屬性節(jié)點)、marry(文本)。
接著說一下節(jié)點關(guān)系,包括父(Parent)、子(Children)、同胞(Sibling)、先輩(Ancestor)、后代(Descendant)。在上面的文檔中:
□ student元素是id、name、age以及country元素的父。
□ id、name、age以及country元素都是student元素的子。
□ id、name、age以及country元素都是同胞節(jié)點,擁有相同的父節(jié)點。
□ name元素的先輩是student元素和classroom元素,也就是此節(jié)點的父、父的父等。
□ classroom的后代是id、name、age以及country元素,也就是此節(jié)點的子,子的子等。
2.XPath語法
XPath使用路徑表達式來選取XML文檔中的節(jié)點或節(jié)點集。節(jié)點是沿著路徑(path)或者步(steps)來選取的。接下來的重點是如何選取節(jié)點,下面給出一個XML文檔進行分析:
<? xml version="1.0" encoding="ISO-8859-1"? > <classroom> <student> <id>1001</id> <name lang="en">marry</name> <age>20</age> <country>China</country> </student> <student> <id>1002</id> <name lang="en">jack</name> <age>25</age> <country>USA</country> </student> </classroom>
首先列舉出一些常用的路徑表達式進行節(jié)點的選取,如表2-2所示。
表2-2 路徑表達式

通過表2-2中的路徑表達式,我們嘗試著對上面的文檔進行節(jié)點選取。以表格的形式進行說明,如表2-3所示。
表2-3 節(jié)點選取示例

上面選取的例子最后實現(xiàn)的效果都是選取了所有符合條件的節(jié)點,是否能選取某個特定的節(jié)點或者包含某一個指定的值的節(jié)點呢?這就需要用到謂語,謂語被嵌在方括號中,接下來通過表格2-4來解釋謂語的用法。
表2-4 謂語示例

XPath在進行節(jié)點選取的時候可以使用通配符“*”匹配未知的元素,同時使用操作符“|”一次選取多條路徑,還是通過一個表格進行演示,如表2-5所示。
表2-5 通配符“*”與“1”操作符

3.XPath軸
軸定義了所選節(jié)點與當(dāng)前節(jié)點之間的樹關(guān)系。在Python爬蟲開發(fā)中,提取網(wǎng)頁中的信息會遇到這種情況:首先提取到一個節(jié)點的信息,然后想在在這個節(jié)點的基礎(chǔ)上提取它的子節(jié)點或者父節(jié)點,這時候就會用到軸的概念。軸的存在會使提取變得更加靈活和準(zhǔn)確。
在說軸的用法之前,需要了解位置路徑表達式中的相對位置路徑、絕對位置路徑和步的概念。位置路徑可以是絕對的,也可以是相對的。絕對路徑起始于正斜杠(/),而相對路徑不會這樣。在兩種情況中,位置路徑均包括一個或多個步,每個步均被斜杠分割:/step/step/...(絕對位置路徑), step/step/...(相對位置路徑)。
步(step)包括:軸(axis)、節(jié)點測試(node-test)、零個或者更多謂語(predicate),用來更深入地提煉所選的節(jié)點集。步的語法為:軸名稱::節(jié)點測試[謂語],大家可能覺比較抽象,通過之后的示例分析,會明白如何使用它。
表2-6列舉了XPath軸中使用的節(jié)點集。
表2-6 XPath軸

首先給出一個XML文檔,實例分析就按照這個文檔來進行,文檔如下:
<? xml version="1.0" encoding="ISO-8859-1"? > <classroom> <student> <id>1001</id> <name lang="en">marry</name> <age>20</age> <country>China</country> </student> <student> <id>1002</id> <name lang="en">jack</name> <age>25</age> <country>USA</country> </student> <teacher> <classid>1</classid> <name lang="en">tom</name> <age>50</age> <country>USA</country> </teacher> </classroom>
針對上面的文檔進行示例演示,如表2-7所示。
表2-7 XPath軸示例分析

4.XPath運算符
XPath表達式可返回節(jié)點集、字符串、邏輯值以及數(shù)字。表2-8列舉了可用在XPath表達式中的運算符。
表2-8 XPath運算符示例分析

2.1.5 JSON
JSON是JavaScript對象表示法(JavaScript Object Notation),用于存儲和交換文本信息。JSON比XML更小、更快、更易解析,因此JSON在網(wǎng)絡(luò)傳輸中,尤其是Web前端中運用非常廣泛。JSON使用JavaScript語法來描述數(shù)據(jù)對象,但是JSON仍然獨立于語言和平臺。JSON解析器和JSON庫支持許多不同的編程語言,其中就包括Python。
下面主要講解一下JSON的語法,具體的存儲解析放到第5章中進行講解。JSON語法非常簡單,主要包括以下幾個方面:
□ JSON名稱/值對。JSON數(shù)據(jù)的書寫格式是:名稱/值對。名稱/值對包括字段名稱(在雙引號中),緊接著是一個冒號,最后是值。例如,"name" : "qiye",非常像Python中字典。
□ JSON值。JSON值可以是:數(shù)字(整數(shù)或浮點數(shù))、字符串(在雙引號中)、邏輯值(true或false)、數(shù)組(在方括號中)、對象(在花括號中)、null。
□ JSON對象。JSON對象在花括號中書寫,對象可以包含多個名稱/值對。例如:{ "name":"qiye" , "age":"20" },其實就是Python中的字典。
□ JSON數(shù)組。JSON數(shù)組在方括號中書寫,數(shù)組可包含多個對象。例如:{"reader":[{ "name":"qiye" , "age":"20"}, { "name":"marry" , "age":"21" }]},這里對象" reader "是包含兩個對象的數(shù)組。
2.2 HTTP標(biāo)準(zhǔn)
HTTP協(xié)議(HyperText Transfer Protocol,超文本傳輸協(xié)議)是用于從WWW服務(wù)器傳輸超文本到本地瀏覽器的傳送協(xié)議。它可以使瀏覽器更加高效,減少網(wǎng)絡(luò)傳輸。它不僅保證計算機正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內(nèi)容首先顯示(如文本先于圖形)等。之后的Python爬蟲開發(fā),主要就是和HTTP協(xié)議打交道。
2.2.1 HTTP請求過程
HTTP協(xié)議采取的是請求響應(yīng)模型,HTTP協(xié)議永遠都是客戶端發(fā)起請求,服務(wù)器回送響應(yīng)。模型如圖2-8所示。

圖2-8 請求響應(yīng)模型
HTTP協(xié)議是一個無狀態(tài)的協(xié)議,同一個客戶端的這次請求和上次請求沒有對應(yīng)關(guān)系。一次HTTP操作稱為一個事務(wù),其執(zhí)行過程可分為四步:
□ 首先客戶端與服務(wù)器需要建立連接,例如單擊某個超鏈接,HTTP的工作就開始了。
□ 建立連接后,客戶端發(fā)送一個請求給服務(wù)器,請求方式的格式為:統(tǒng)一資源標(biāo)識符(URL)、協(xié)議版本號,后邊是MIME信息,包括請求修飾符、客戶機信息和可能的內(nèi)容。
□ 服務(wù)器接到請求后,給予相應(yīng)的響應(yīng)信息,其格式為一個狀態(tài)行,包括信息的協(xié)議版本號、一個成功或錯誤的代碼,后邊是MIME信息,包括服務(wù)器信息、實體信息和可能的內(nèi)容。
□ 客戶端接收服務(wù)器所返回的信息,通過瀏覽器將信息顯示在用戶的顯示屏上,然后客戶端與服務(wù)器斷開連接。
如果以上過程中的某一步出現(xiàn)錯誤,那么產(chǎn)生錯誤的信息將返回到客戶端,在顯示屏輸出,這些過程是由HTTP協(xié)議自己完成的。
2.2.2 HTTP狀態(tài)碼含義
當(dāng)瀏覽者訪問一個網(wǎng)頁時,瀏覽者的瀏覽器會向網(wǎng)頁所在服務(wù)器發(fā)出請求。在瀏覽器接收并顯示網(wǎng)頁前,此網(wǎng)頁所在的服務(wù)器會返回一個包含HTTP狀態(tài)碼的信息頭(server header)用以響應(yīng)瀏覽器的請求。HTTP狀態(tài)碼主要是是為了標(biāo)識此次HTTP請求的運行狀態(tài)。下面是常見的HTTP狀態(tài)碼:
□ 200——請求成功。
□ 301——資源(網(wǎng)頁等)被永久轉(zhuǎn)移到其他URL。
□ 404——請求的資源(網(wǎng)頁等)不存在。
□ 500——內(nèi)部服務(wù)器錯誤。
HTTP狀態(tài)碼由三個十進制數(shù)字組成,第一個十進制數(shù)字定義了狀態(tài)碼的類型。HTTP狀態(tài)碼共分為5種類型,如表2-9所示。
表2-9 HTTP狀態(tài)碼

全部的HTTP狀態(tài)碼的信息,請大家查詢HTTP協(xié)議標(biāo)準(zhǔn)手冊。
2.2.3 HTTP頭部信息
HTTP頭部信息由眾多的頭域組成,每個頭域由一個域名、冒號(:)和域值三部分組成。域名是大小寫無關(guān)的,域值前可以添加任何數(shù)量的空格符,頭域可以被擴展為多行,在每行開始處,使用至少一個空格或制表符。
通過瀏覽器訪問博客園首頁時,使用F12打開開發(fā)者工具,里面可以監(jiān)控整個HTTP訪問的過程。下面就以訪問博客園的HTTP請求進行分析,首先是瀏覽器發(fā)出請求,請求頭的數(shù)據(jù)如下:
GET / HTTP/1.1 Host: www.cnblogs.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8 Accept-Language: zh-CN, zh; q=0.8, en-US; q=0.5, en; q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive If-Modified-Since: Sun, 30 Oct 2016 10:13:18 GMT
在請求頭中包含以下內(nèi)容:
□ GET代表的是請求方式,HTTP/1.1表示使用HTTP 1.1協(xié)議標(biāo)準(zhǔn)。
□ Host頭域,用于指定請求資源的Intenet主機和端口號,必須表示請求URL的原始服務(wù)器或網(wǎng)關(guān)的位置。HTTP/1.1請求必須包含主機頭域,否則系統(tǒng)會以400狀態(tài)碼返回。
□ User-Agent頭域,里面包含發(fā)出請求的用戶信息,其中有使用的瀏覽器型號、版本和操作系統(tǒng)的信息。這個頭域經(jīng)常用來作為反爬蟲的措施。
□ Accept請求報頭域,用于指定客戶端接受哪些類型的信息。例如:Accept:image/gif,表明客戶端希望接受GIF圖象格式的資源;Accept:text/html,表明客戶端希望接受html文本。
□ Accept-Language請求報頭域,類似于Accept,但是它用于指定一種自然語言。例如:Accept-Language:zh-cn.如果請求消息中沒有設(shè)置這個報頭域,服務(wù)器假定客戶端對各種語言都可以接受。
□ Accept-Encoding請求報頭域,類似于Accept,但是它用于指定可接受的內(nèi)容編碼。例如:Accept-Encoding:gzip.deflate。如果請求消息中沒有設(shè)置這個域服務(wù)器假定客戶端對各種內(nèi)容編碼都可以接受。
□ Connection報頭域允許發(fā)送用于指定連接的選項。例如指定連接的狀態(tài)是連續(xù),或者指定“close”選項,通知服務(wù)器,在響應(yīng)完成后,關(guān)閉連接。
□ If-Modified-Since頭域用于在發(fā)送HTTP請求時,把瀏覽器端緩存頁面的最后修改時間一起發(fā)到服務(wù)器去,服務(wù)器會把這個時間與服務(wù)器上實際文件的最后修改時間進行比較。如果時間一致,那么返回HTTP狀態(tài)碼304(不返回文件內(nèi)容),客戶端收到之后,就直接把本地緩存文件顯示到瀏覽器中。如果時間不一致,就返回HTTP狀態(tài)碼200和新的文件內(nèi)容,客戶端收到之后,會丟棄舊文件,把新文件緩存起來,并顯示到瀏覽器中。
請求發(fā)送成功后,服務(wù)器進行響應(yīng),接下來看一下響應(yīng)的頭信息,數(shù)據(jù)如下:
HTTP/1.1200 OK Date: Sun, 30 Oct 2016 10:13:50 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Encoding Cache-Control: public, max-age=3 Expires: Sun, 30 Oct 2016 10:13:54 GMT Last-Modified: Sun, 30 Oct 2016 10:13:24 GMT Content-Encoding: gzip
響應(yīng)頭中包含以下內(nèi)容:
□ HTTP/1.1表示使用HTTP 1.1協(xié)議標(biāo)準(zhǔn),200 OK說明請求成功。
□ Date表示消息產(chǎn)生的日期和時間。
□ Content-Type實體報頭域用于指明發(fā)送給接收者的實體正文的媒體類型。text/html;charset=utf-8代表HTML文本文檔,UTF-8編碼。
□ Transfer-Encoding:chunked表示輸出的內(nèi)容長度不能確定。
□ Connection報頭域允許發(fā)送用于指定連接的選項。例如指定連接的狀態(tài)是連續(xù),或者指定“close”選項,通知服務(wù)器,在響應(yīng)完成后,關(guān)閉連接。
□ Vary頭域指定了一些請求頭域,這些請求頭域用來決定當(dāng)緩存中存在一個響應(yīng),并且該緩存沒有過期失效時,是否被允許利用此響應(yīng)去回復(fù)后續(xù)請求而不需要重復(fù)驗證。
□ Cache-Control用于指定緩存指令,緩存指令是單向的,且是獨立的。請求時的緩存指令包括:no-cache(用于指示請求或響應(yīng)消息不能緩存)、no-store、max-age、max-stale、min-fresh、only-if-cached;響應(yīng)時的緩存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。
□ Expires實體報頭域給出響應(yīng)過期的日期和時間。為了讓代理服務(wù)器或瀏覽器在一段時間以后更新緩存中(再次訪問曾訪問過的頁面時,直接從緩存中加載,縮短響應(yīng)時間和降低服務(wù)器負載)的頁面,我們可以使用Expires實體報頭域指定頁面過期的時間。
□ Last-Modified實體報頭域用于指示資源的最后修改日期和時間。
□ Content-Encoding實體報頭域被用作媒體類型的修飾符,它的值指示了已經(jīng)被應(yīng)用到實體正文的附加內(nèi)容的編碼,因而要獲得Content-Type報頭域中所引用的媒體類型,必須采用相應(yīng)的解碼機制。
從上面分析的過程中,大家基本上了解了請求和響應(yīng)的頭信息,最后進行一下總結(jié):
HTTP消息報頭主要包括普通報頭、請求報頭、響應(yīng)報頭、實體報頭。具體如下:
1)在普通報頭中,有少數(shù)報頭域用于所有的請求和響應(yīng)消息,但并不用于被傳輸?shù)膶嶓w,只用于傳輸?shù)南ⅰ?/p>
2)請求報頭允許客戶端向服務(wù)器端傳遞請求的附加信息以及客戶端自身的信息。
3)響應(yīng)報頭允許服務(wù)器傳遞不能放在狀態(tài)行中的附加響應(yīng)信息,以及關(guān)于服務(wù)器的信息和對Request-URI所標(biāo)識的資源進行下一步訪問的信息。
4)請求和響應(yīng)消息都可以傳送一個實體。一個實體由實體報頭域和實體正文組成,但并不是說實體報頭域和實體正文要在一起發(fā)送,可以只發(fā)送實體報頭域。實體報頭定義了關(guān)于實體正文和請求所標(biāo)識的資源的元信息。
通過表2-10~表2-13對報文頭進行分類列舉說明。
表2-10 常見普通報頭

表2-11 常見請求報頭

表2-12 常見響應(yīng)報頭

表2-13 常見實體報頭

2.2.4 Cookie狀態(tài)管理
Cookie和Session都用來保存狀態(tài)信息,都是保存客戶端狀態(tài)的機制,它們都是為了解決HTTP無狀態(tài)的問題所做的努力。對于爬蟲開發(fā)來說,我們更加關(guān)注的是Cookie,因為Cookie將狀態(tài)保存在客戶端,Session將狀態(tài)保存在服務(wù)器端。
Cookie是服務(wù)器在本地機器上存儲的小段文本并隨每一個請求發(fā)送至同一個服務(wù)器。網(wǎng)絡(luò)服務(wù)器用HTTP頭向客戶端發(fā)送Cookie,瀏覽器則會解析這些Cookie并將它們保存為一個本地文件,它會自動將同一服務(wù)器的任何請求綁定上這些Cookie。
Cookie的工作方式:服務(wù)器給每個Session分配一個唯一的JSESSIONID,并通過Cookie發(fā)送給客戶端。當(dāng)客戶端發(fā)起新的請求的時候,將在Cookie頭中攜帶這個JSESSIONID。這樣服務(wù)器能夠找到這個客戶端對應(yīng)的Session,流程如圖2-9所示。

圖2-9 Cookie工作流程
2.2.5 HTTP請求方式
HTTP的請求方法包括如下幾種:
□ GET
□ POST
□ HEAD
□ PUT
□ DELETE
□ OPTIONS
□ TRACE
□ CONNECT
其中常用的請求方式是GET和POST:
□ GET方式:是以實體的方式得到由請求URL所指定資源的信息,如果請求URL只是一個數(shù)據(jù)產(chǎn)生過程,那么最終要在響應(yīng)實體中返回的是處理過程的結(jié)果所指向的資源,而不是處理過程的描述。
□ POST方式:用來向目的服務(wù)器發(fā)出請求,要求它接受被附在請求后的實體,并把它當(dāng)作請求隊列中請求URL所指定資源的附加新子項。
GET與POST方法有以下區(qū)別:
□ 在客戶端,Get方式通過URL提交數(shù)據(jù),數(shù)據(jù)在URL中可以看到:POST方式,數(shù)據(jù)放置在實體區(qū)內(nèi)提交。
□ GET方式提交的數(shù)據(jù)最多只能有1024字節(jié),而POST則沒有此限制。
□ 安全性問題。使用Get的時候,參數(shù)會顯示在地址欄上,而Post不會。所以,如果這些數(shù)據(jù)是非敏感數(shù)據(jù),那么使用Get;如果用戶輸入的數(shù)據(jù)包含敏感數(shù)據(jù),那么還是使用Post為好。
在爬蟲開發(fā)中基本處理的也是GET和POST請求。GET請求在訪問網(wǎng)頁時很常見,POST請求則是常用在登錄框、提交框的位置。下面展示一個完整的POST請求,這是登錄知乎社區(qū)時捕獲的請求,上面一部分是請求頭,下面全部加粗的數(shù)據(jù)是請求實體。請求內(nèi)容如下:
POST /login/phone_num HTTP/1.1 Host: www.zhihu.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0 Accept: */* Accept-Language: zh-CN, zh; q=0.8, en-US; q=0.5, en; q=0.3 Accept-Encoding: gzip, deflate, br X-Xsrftoken: ade0896dc13cc3b2204a8f7742ad7f48 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Referer: https://www.zhihu.com/ Content-Length: 117 Cookie:q_c1=7bc53a12dd7942d3b64776441ab69983|1477975324000|1465870098000; d_c0="ACAAa1M-EwqPTgdv2RIP3IIzHO2R7zKBGpw=|1465870098"; __utma=51854390.1118849962.1465870098.1466355392.1477975328.3; __utmz=51854390.1465870098.1.1. utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=51854390.000--|3=entr y_date=20160614=1; _zap=7514ab27-5b42-4c95-a4cc-e31ce5757e14; _za=4ab6eb3b-c 34f-4772-aac2-7182f21894cb; _xsrf=ade0896dc13cc3b2204a8f7742ad7f48; l_cap_id="ZjBkODkyYjdiZWZkNDQ2NWE4YzI1ZTk3Njc0MDZlMWM=|1477975324|95c5032340720551391178c9ee67cd8a3e2849d5"; cap_id="ZjAxNjBmNzU5NzZkNDI2ZTlkYTk3ZDVlNDNhNzgy ZTA=|1477975324|0616dfa45cd15d66fe792484c6ae0af71557cb3c"; n_c=1; __utmb=51854390.2.10.1477975328; __utmc=51854390; __utmt=1; login="ZWU1NTFlM2EzYzg4NDNjNzlhODY wN2ZhYzgyZmExOTE=|1477975348|735a805117328df9e557f0126eb348e7712e310c" Connection: keep-alive _xsrf=ade0896dc13cc3b2204a8f7742ad7f48&password=xxxxxxxx&captcha_type=cn&rememb er_me=true&phone_num=xxxxxxxxx
2.3 小結(jié)
本章主要講解了Web前端中標(biāo)記語言、腳本語言和HTTP的基本概念,在這些知識中,重點掌握HTML標(biāo)記語言、XPath路徑表達式的書寫和HTTP請求流程,這對接下來的Python爬蟲開發(fā)有著非常直接的作用,有助于爬蟲開發(fā)的快速入門。本章講解的只是Web前端的基礎(chǔ)知識,希望大家有時間系統(tǒng)地學(xué)習(xí)Web前端的知識,這樣對之后涉及協(xié)議分析和反爬蟲措施的應(yīng)對方面有很大幫助。
- Mastering JavaScript Functional Programming
- 國際大學(xué)生程序設(shè)計競賽中山大學(xué)內(nèi)部選拔真題解(二)
- ASP.NET Core 5.0開發(fā)入門與實戰(zhàn)
- Python數(shù)據(jù)分析基礎(chǔ)
- Visual Basic程序設(shè)計(第3版):學(xué)習(xí)指導(dǎo)與練習(xí)
- Java程序設(shè)計:原理與范例
- Go并發(fā)編程實戰(zhàn)
- Vue.js 2 Web Development Projects
- TypeScript圖形渲染實戰(zhàn):2D架構(gòu)設(shè)計與實現(xiàn)
- Learning Kotlin by building Android Applications
- 數(shù)據(jù)結(jié)構(gòu):Python語言描述
- Raspberry Pi Blueprints
- 自己動手構(gòu)建編程語言:如何設(shè)計編譯器、解釋器和DSL
- Learning Yeoman
- 網(wǎng)絡(luò)工程方案設(shè)計與實施(第二版)