官术网_书友最值得收藏!

第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)對方面有很大幫助。

主站蜘蛛池模板: 德化县| 阿拉善盟| 项城市| 灵川县| 雷波县| 曲水县| 葵青区| 海兴县| 永昌县| 瓦房店市| 尚义县| 仪陇县| 阿荣旗| 霍城县| 景洪市| 威信县| 汾西县| 屏东市| 尤溪县| 瓮安县| 马龙县| 开江县| 集安市| 铜川市| 松滋市| 镇平县| 米林县| 义乌市| 敦化市| 宜阳县| 黄石市| 尼玛县| 璧山县| 吉安市| 广元市| 新乡市| 军事| 香港 | 桂东县| 乐都县| 定西市|