整合營銷服務(wù)商

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

          免費咨詢熱線:

          使用CefSharp和Javascript實現(xiàn)網(wǎng)絡(luò)爬

          使用CefSharp和Javascript實現(xiàn)網(wǎng)絡(luò)爬蟲—DOM操作

          ello,親愛的小伙伴們,歡迎瀏覽“使用CefSharp和Javascript實現(xiàn)網(wǎng)絡(luò)爬蟲”。

          本篇是第2篇,介紹在實現(xiàn)爬蟲過程中會用到的Javascript和C#主要知識點。在使用CefSharp和Javascript實現(xiàn)網(wǎng)絡(luò)爬蟲過程中,我使用到的C#和Javascript知識主要包括三個方面:一是Javascript的Dom操作;二是CefSharp中Javascript和C#之間的調(diào)用和交互;三是C#委托使用,用于接收到數(shù)據(jù)后的回調(diào)處理。

          網(wǎng)絡(luò)爬蟲采用Javascript的DOM操作來抓取目標數(shù)據(jù),并通過CefSharp提供的Javascript和C#交互方法,把目標數(shù)據(jù)傳遞給C#代碼進行處理。下面我將分別進行記錄,分享給感興趣的小伙伴。

          一、Javascript原生DOM操作

          HTML通過瀏覽器解析后形成DOM樹,DOM中每個 HTML標簽都是一個節(jié)點元素,包括屬性、方法、子孫節(jié)點。Javascript有一套操作HTML的DOM編程接口,通過DOM編程接口能夠操作到每個節(jié)點元素(即HTML標簽),支持增、刪、改、查操作。

          1、查找獲取節(jié)點

          查找獲取HTML節(jié)點元素,可能通過document的get方法,或者使用document 的querySelector()和querySelectorAll()方法實現(xiàn)。

          方法1:通過document的get方法

          var elem=document.getElementById(idName) ;//通過id號獲取元素,返回一個元素對象
          var elem=document.getElementsByClassName(className) ;//通過class獲取元素,返回元素數(shù)組
          var elem document.getElementsByTagName(tagName);//通過標簽名獲取元素,返回元素數(shù)組

          以上方法可以串聯(lián)使用,例如:

          // 先定位ID為idName的節(jié)點,再返回其內(nèi)部所有名稱為tagName的節(jié)點:

          var elem=document.getElementById(idName).getElementsByTagName(tagName);

          // 先定位ID為idName的節(jié)點,再返回其內(nèi)部所有class包含className的節(jié)點:

          var elem=document.getElementById(idName).getElementsByClassName(className);

          方法二:使用document 的querySelector()和querySelectorAll()方法

          var elem=document.querySelector('# idName ');// 通過querySelector獲取id為idName的節(jié)點
          var elem=document.querySelectorAll('div');// 通過querySelectorAll獲取所有的div節(jié)點

          2、獲取/設(shè)置元素的屬性值

          通過document的get方法,或者使用document 的querySelector()和querySelectorAll()方法,得到節(jié)點對象后,可進一步可獲取節(jié)點的屬性值。

          elem.parentNode;//獲取當(dāng)前元素的父節(jié)點
          elem.chlidren;//獲取當(dāng)前元素子節(jié)點
          elem.chilidNodes;//獲取當(dāng)前元素子節(jié)點
          elem.firstChild;//獲取當(dāng)前元素的第1個子節(jié)點
          elem.lastChild;//獲取當(dāng)前元素的最后1個子節(jié)點
          elem.innerHTML?? //獲取元素的內(nèi)部文本
          elem.innerText; //獲取當(dāng)前元素的內(nèi)部文本值,只是文本內(nèi)容,不包括html代碼

          此外,通過getAttribute、setAttribute可以實現(xiàn)對屬性值的獲取或設(shè)置。

          elem.getAttribute(attributeName);//傳入屬性名稱,獲取對應(yīng)屬性的屬性值
          elem.setAttribute(attributeName,attributeValue); //傳入屬性名稱,以及屬性值

          二、jQuery操作HTML的DOM

          對于支持jQuery的站點,可以直接使用jQuery方便地進行DOM操作。

          jQuery對Javascript的DOM操作方法進行了封裝,通過jQuery 選擇器能夠?qū)?HTML 節(jié)點元素或節(jié)點元素組進行操作。jQuery 選擇器通過節(jié)點的 ID、類、類型、屬性、屬性值等查找/選擇HTML 節(jié)點元素,jQuery 選擇器以$符號開頭。

          1、查找獲取節(jié)點

          (1)元素選擇器

          使用節(jié)點名選取元素,例如在頁面中選取所有 <div> 元素:$('div')

          (2)#id選擇器

          使用 HTML 元素的 ID屬性選取指定的元素,例如在頁面中選取id='myid'的 <div id='myid'> 元素:$('#myid')

          (3).class 選擇器

          使用 class 查找元素,例如在頁面中選取class='myclass'的 <div class='myclass'>元素:$(".myclass")

          2、獲取/設(shè)置元素的屬性值:

          通過attr() 、html()、val()方法設(shè)置或返回被選元素的屬性值:

          $(selector).attr(attribute); //獲取被選元素的屬性值
          $(selector).attr(attribute,value);//設(shè)置被選元素的屬性和值
          $(selector).html();//獲取或設(shè)置被選元素的內(nèi)容 (innerHTML)
          $(selector).val();//獲取或設(shè)置被選元素的值

          三、DOM操作實踐

          使用Chrome瀏覽器,打開以下網(wǎng)址:

          https://www.toutiao.com/c/user/3601650358695789/#mid=1652236062202883

          (1)按“F12”打開 “開發(fā)者工具”窗口,在“Elements”面板可以看到頁面的DOM結(jié)構(gòu)。

          (2)點擊左上角"箭頭"圖標,在頁面中選擇文章標題,在“開發(fā)者工具”中可以看到被選中元素高亮顯示。

          (3)在“開發(fā)者工具”中“右鍵”點擊高亮顯示內(nèi)容,在彈出菜單中選擇Copy。

          (4)選擇“Copy selector”

          (5)點擊開發(fā)者工具的“Console”選項,在窗口中進行如下輸入:

          a) 輸入"//" ,然后鍵盤按下"Ctrl"+"V" 粘貼上述操作獲取的HTML元素選擇字符串,或者在輸入行“點擊右鍵”,選擇“粘貼(P)”,粘貼上述操作獲取的HTML元素選擇字符串,字符串為:

          #wrapper > div.left > div:nth-child(2) > div > div:nth-child(3) > div > ul > li > div > div.normal.rbox > div > div.title-box > a

          b) 輸入 var elem=$("XXX"),其中XXX是"Ctrl"+"V" 粘貼的字符串

          c) 輸入 elem回車,即可獲得我們選中的文章標題元素

          d) 輸入 elem.href ,即可獲得文章標題的URL鏈接地址

          e) 輸入 elem.innerText,即可獲得文章標題字符串。

          這樣我們就獲得了文章標題和對應(yīng)的URL地址,后面通過CefSharp中Javascript和C#之間的調(diào)用和交互方法,可將標題和對應(yīng)的URL地址傳遞給C#進行處理存儲、打開鏈接獲取文章詳細內(nèi)容等。本篇介紹了Javascript的DOM操作,后面我將對C#委托使用、CefSharp中Javascript和C#之間的調(diào)用和交互進行介紹,敬請指正。

          象語法樹(Abstract Syntax Trees),簡稱AST,如果您正在編寫代碼,那么 AST 很可能已經(jīng)參與了您的開發(fā)流程。它們?yōu)槟拈_發(fā)流程的許多部分提供動力。 有些人可能在編譯器的上下文中聽說過它們,但它們被用于各種工具中。 即使您不編寫通用開發(fā)工具,AST 也可能是您工具帶中的有用工具。 在這篇文章中,我們將討論什么是 AST,它們在哪里使用以及如何利用它們。

          什么是AST

          抽象語法樹或 AST 是代碼的樹型數(shù)據(jù)結(jié)構(gòu)表示。 它們是編譯器工作方式的基本部分。 當(dāng)編譯器轉(zhuǎn)換某些代碼時,基本上有以下步驟:

          1. 詞法分析
          2. 語法分析
          3. 代碼生成

          詞法分析又名標記化

          在此步驟中,您編寫的代碼將被轉(zhuǎn)換為一組描述代碼不同部分的標記。 這與基本語法突出顯示使用的方法基本相同。 這些標記令牌不了解事物如何組合在一起,并且僅關(guān)注文件的組件。

          你可以想象這就像你將一個文本分解成單詞。 您可能能夠區(qū)分標點符號、動詞、名詞、數(shù)字等,但在這個階段,您對句子的組成部分或句子如何組合沒有任何更深入的了解。

          語法分析又名解析

          這是我們將標記列表轉(zhuǎn)換為抽象語法樹的步驟。 它將我們的標記轉(zhuǎn)換為表示代碼實際結(jié)構(gòu)的樹。 以前在標記中我們只有一對 (),現(xiàn)在我們知道它是函數(shù)調(diào)用、函數(shù)定義、分組還是其他東西。

          這里的等價物是將我們的單詞列表轉(zhuǎn)換為表示諸如句子之類的數(shù)據(jù)結(jié)構(gòu),某個名詞在句子中扮演什么角色,或者我們是否在列表中。

          另一個可以與之比較的例子是 DOM。 上一步只是將 HTML 分解為“標簽”和“文本”,而這一步將生成表示為 DOM 樹的層次結(jié)構(gòu)。

          需要注意的一件事是沒有“單一”的 AST 格式。 它們可能會有所不同,這取決于您要轉(zhuǎn)換為 AST 的語言以及您用于解析的工具。 在 JavaScript 中,一個通用標準是 ESTree,但您會看到不同的工具可能會添加不同的屬性。

          一般來說,AST 是一種樹結(jié)構(gòu),其中每個節(jié)點至少有一個類型來指定它所代表的內(nèi)容。

          代碼生成

          此步驟本身可以是多個步驟。 一旦我們有了抽象語法樹,我們就可以操作它,也可以將它“打印”到不同類型的代碼中。 使用 AST 操作代碼比直接在代碼上作為文本或標記列表執(zhí)行這些操作更安全。

          操縱文本總是很危險的; 它顯示最少的上下文。 如果您曾經(jīng)嘗試使用字符串替換或正則表達式來操作文本,您可能會注意到很容易出錯。而且不容易調(diào)試。

          甚至操縱令牌也不容易。 雖然我們可能知道變量是什么,但如果我們想重命名它,我們將無法深入了解變量的范圍或可能與之沖突的任何變量。

          AST 提供了有關(guān)代碼結(jié)構(gòu)的足夠信息,我們可以更有信心地對其進行修改。 例如,我們可以確定變量的聲明位置,并確切地知道由于樹結(jié)構(gòu)而影響程序的哪個部分。

          一旦我們操縱了樹,我們就可以打印樹以輸出任何預(yù)期的代碼輸出。 例如,如果我們要構(gòu)建一個像 TypeScript 編譯器這樣的編譯器,我們會輸出 JavaScript,而另一個編譯器可能會輸出機器代碼。

          同樣,使用 AST 更容易實現(xiàn)這一點,因為相同結(jié)構(gòu)的不同輸出可能具有不同的格式。 使用更線性的輸入(如文本或標記列表)生成輸出會相當(dāng)困難。

          如何處理 AST?

          理論涵蓋了哪些實際生活中的 AST 用例? 我們討論了編譯器,但我們并不是整天都在構(gòu)建編譯器。

          AST 的用例很廣泛,通常可以分為三個總體操作:讀取、修改和打印。 它們是一種添加劑,這意味著如果您正在打印 AST,那么您以前也閱讀過 AST 并對其進行修改的可能性很高。 但我們將介紹每個主要關(guān)注一個用例的示例。

          讀取/遍歷 AST

          從技術(shù)上講,使用 AST 的第一步是解析文本以創(chuàng)建 AST,但在大多數(shù)情況下,提供解析步驟的庫也提供了一種遍歷 AST 的方法。遍歷 AST 意味著訪問樹的不同節(jié)點以獲取細節(jié)或執(zhí)行操作。

          最常見的用例之一是 linting。 例如,ESLint 使用 espree 生成 AST,如果您想編寫任何自定義規(guī)則,您將根據(jù)不同的 AST 節(jié)點編寫這些規(guī)則。 ESLint 文檔有大量關(guān)于如何構(gòu)建自定義規(guī)則、插件和格式化程序的文檔。

          修改/轉(zhuǎn)換 AST

          如前所述,與將代碼修改為標記或原始字符串相比,擁有 AST 使修改所述樹更容易、更安全。您可能想要使用 AST 修改某些代碼的原因有很多種。

          例如,Babel 修改 AST 以向下編譯新功能或?qū)?JSX 轉(zhuǎn)換為函數(shù)調(diào)用。例如,當(dāng)您編譯 React 或 Preact 代碼時會發(fā)生這種情況。

          另一個用例是捆綁代碼。在模塊的世界中,捆綁代碼通常比將文件附加在一起要復(fù)雜得多。更好地了解各個文件的結(jié)構(gòu)可以更輕松地合并這些文件并在必要時調(diào)整導(dǎo)入和函數(shù)調(diào)用。如果您查看 webpack、parcel 或 rollup 等工具的代碼庫,您會發(fā)現(xiàn)它們都使用 AST 作為其捆綁工作流程的一部分。

          打印 AST

          在大多數(shù)情況下,打印和修改 AST 是齊頭并進的,因為您必須輸出剛剛修改的 AST。 但是,雖然像 recast 這樣的一些庫明確專注于以與原始代碼樣式相同的代碼樣式打印 AST,但也有各種用例,您希望以不同的方式顯式打印您的 AST。

          例如,Prettier 使用 AST 根據(jù)您的配置重新格式化您的代碼,而無需更改代碼的內(nèi)容/含義。 他們這樣做的方式是將您的代碼轉(zhuǎn)換為完全與格式無關(guān)的 AST,然后根據(jù)您的規(guī)則重寫它。

          其他常見的用例是用不同的目標語言打印代碼或構(gòu)建自己的縮小工具。

          您可以使用幾種不同的工具來打印 AST,例如 escodegen 或 astring。 您還可以根據(jù)您的用例構(gòu)建自己的格式化程序,或者為 Prettier 構(gòu)建一個插件。

          最后:

          雖然 AST 可能是大多數(shù)開發(fā)人員每天都不會使用的東西,但我相信了解它對今后的工作會有幫助。感謝閱讀。

          瀏覽器訪問網(wǎng)站時,頁面各不相同,你有沒有想過它為何會呈現(xiàn)這個樣子呢?本節(jié)中,我們就來了解一下網(wǎng)頁的基本組成、結(jié)構(gòu)和節(jié)點等內(nèi)容。

          網(wǎng)頁的組成

          網(wǎng)頁可以分為三大部分——HTML、CSS和JavaScript。如果把網(wǎng)頁比作一個人的話,HTML相當(dāng)于骨架,JavaScript相當(dāng)于肌肉,CSS相當(dāng)于皮膚,三者結(jié)合起來才能形成一個完善的網(wǎng)頁。下面我們分別來介紹一下這三部分的功能。

          1. HTML

          HTML是用來描述網(wǎng)頁的一種語言,其全稱叫作Hyper Text Markup Language,即超文本標記語言。網(wǎng)頁包括文字、按鈕、圖片和視頻等各種復(fù)雜的元素,其基礎(chǔ)架構(gòu)就是HTML。不同類型的文字通過不同類型的標簽來表示,如圖片用img標簽表示,視頻用video標簽表示,段落用p標簽表示,它們之間的布局又常通過布局標簽div嵌套組合而成,各種標簽通過不同的排列和嵌套才形成了網(wǎng)頁的框架。

          在Chrome瀏覽器中打開百度,右擊并選擇“檢查”項(或按F12鍵),打開開發(fā)者模式,這時在Elements選項卡中即可看到網(wǎng)頁的源代碼,如圖2-9所示。

          圖2-9 源代碼

          這就是HTML,整個網(wǎng)頁就是由各種標簽嵌套組合而成的。這些標簽定義的節(jié)點元素相互嵌套和組合形成了復(fù)雜的層次關(guān)系,就形成了網(wǎng)頁的架構(gòu)。

          2.CSS

          HTML定義了網(wǎng)頁的結(jié)構(gòu),但是只有HTML頁面的布局并不美觀,可能只是簡單的節(jié)點元素的排列,為了讓網(wǎng)頁看起來更好看一些,這里借助了CSS。

          CSS,全稱叫作Cascading Style Sheets,即層疊樣式表。“層疊”是指當(dāng)在HTML中引用了數(shù)個樣式文件,并且樣式發(fā)生沖突時,瀏覽器能依據(jù)層疊順序處理。“樣式”指網(wǎng)頁中文字大小、顏色、元素間距、排列等格式。

          CSS是目前唯一的網(wǎng)頁頁面排版樣式標準,有了它的幫助,頁面才會變得更為美觀。

          圖2-9的右側(cè)即為CSS

          就是一個CSS樣式。大括號前面是一個CSS選擇器,此選擇器的意思是首先選中id為head_wrapper且class為s-ps-islite的節(jié)點,然后再選中其內(nèi)部的class為s-p-top的節(jié)點。大括號內(nèi)部寫的就是一條條樣式規(guī)則,例如position指定了這個元素的布局方式為絕對布局,bottom指定元素的下邊距為40像素,width指定了寬度為100%占滿父元素,height則指定了元素的高度。也就是說,我們將位置、寬度、高度等樣式配置統(tǒng)一寫成這樣的形式,然后用大括號括起來,接著在開頭再加上CSS選擇器,這就代表這個樣式對CSS選擇器選中的元素生效,元素就會根據(jù)此樣式來展示了。

          在網(wǎng)頁中,一般會統(tǒng)一定義整個網(wǎng)頁的樣式規(guī)則,并寫入CSS文件中(其后綴為css)。在HTML中,只需要用link標簽即可引入寫好的CSS文件,這樣整個頁面就會變得美觀、優(yōu)雅。

          3. JavaScript

          JavaScript,簡稱JS,是一種腳本語言。HTML和CSS配合使用,提供給用戶的只是一種靜態(tài)信息,缺乏交互性。我們在網(wǎng)頁里可能會看到一些交互和動畫效果,如下載進度條、提示框、輪播圖等,這通常就是JavaScript的功勞。它的出現(xiàn)使得用戶與信息之間不只是一種瀏覽與顯示的關(guān)系,而是實現(xiàn)了一種實時、動態(tài)、交互的頁面功能。

          JavaScript通常也是以單獨的文件形式加載的,后綴為js,在HTML中通過script標簽即可引入,例如:

          <script src="jquery-2.1.0.js"></script>

          綜上所述,HTML定義了網(wǎng)頁的內(nèi)容和結(jié)構(gòu),CSS描述了網(wǎng)頁的布局,JavaScript定義了網(wǎng)頁的行為。

          網(wǎng)頁的結(jié)構(gòu)

          我們首先用例子來感受一下HTML的基本結(jié)構(gòu)。新建一個文本文件,名稱可以自取,后綴為html,內(nèi)容如下:

          <!DOCTYPE html>
          <html>
              <head>
                  <meta charset="UTF-8">
                  <title>This is a Demo</title>
              </head>
              <body>
                  <div id="container">
                      <div class="wrapper">
                          <h2 class="title">Hello World</h2>
                          <p class="text">Hello, this is a paragraph.</p>
                      </div>
                  </div>
              </body>
          </html>

          這就是一個最簡單的HTML實例。開頭用DOCTYPE定義了文檔類型,其次最外層是html標簽,最后還有對應(yīng)的結(jié)束標簽來表示閉合,其內(nèi)部是head標簽和body標簽,分別代表網(wǎng)頁頭和網(wǎng)頁體,它們也需要結(jié)束標簽。head標簽內(nèi)定義了一些頁面的配置和引用,如:

          <meta charset="UTF-8">

          它指定了網(wǎng)頁的編碼為UTF-8。

          title標簽則定義了網(wǎng)頁的標題,會顯示在網(wǎng)頁的選項卡中,不會顯示在正文中。body標簽內(nèi)則是在網(wǎng)頁正文中顯示的內(nèi)容。div標簽定義了網(wǎng)頁中的區(qū)塊,它的id是container,這是一個非常常用的屬性,且id的內(nèi)容在網(wǎng)頁中是唯一的,我們可以通過它來獲取這個區(qū)塊。然后在此區(qū)塊內(nèi)又有一個div標簽,它的class為wrapper,這也是一個非常常用的屬性,經(jīng)常與CSS配合使用來設(shè)定樣式。然后此區(qū)塊內(nèi)部又有一個h2標簽,這代表一個二級標題。另外,還有一個p標簽,這代表一個段落。在這兩者中直接寫入相應(yīng)的內(nèi)容即可在網(wǎng)頁中呈現(xiàn)出來,它們也有各自的class屬性。

          將代碼保存后,在瀏覽器中打開該文件,可以看到如圖2-10所示的內(nèi)容。

          圖2-10 運行結(jié)果

          可以看到,在選項卡上顯示了This is a Demo字樣,這是我們在head中的title里定義的文字。而網(wǎng)頁正文是body標簽內(nèi)部定義的各個元素生成的,可以看到這里顯示了二級標題和段落。

          這個實例便是網(wǎng)頁的一般結(jié)構(gòu)。一個網(wǎng)頁的標準形式是html標簽內(nèi)嵌套head和body標簽,head內(nèi)定義網(wǎng)頁的配置和引用,body內(nèi)定義網(wǎng)頁的正文。

          節(jié)點樹及節(jié)點間的關(guān)系

          在HTML中,所有標簽定義的內(nèi)容都是節(jié)點,它們構(gòu)成了一個HTML DOM樹。

          我們先看下什么是DOM,DOM是W3C(萬維網(wǎng)聯(lián)盟)的標準,其英文全稱Document Object Model,即文檔對象模型。它定義了訪問HTML和XML文檔的標準:

          W3C文檔對象模型(DOM)是中立于平臺和語言的接口,它允許程序和腳本動態(tài)地訪問和更新文檔的內(nèi)容、結(jié)構(gòu)和樣式。

          W3C DOM標準被分為3個不同的部分。

          l 核心DOM: 針對任何結(jié)構(gòu)化文檔的標準模型。

          l XML DOM:針對XML文檔的標準模型。

          l HTML DOM:針對HTML文檔的標準模型。

          根據(jù)W3C的HTML DOM標準,HTML文檔中的所有內(nèi)容都是節(jié)點。

          l 整個文檔是一個文檔節(jié)點;

          l 每個HTML元素是元素節(jié)點;

          l HTML元素內(nèi)的文本是文本節(jié)點;

          l 每個HTML屬性是屬性節(jié)點;

          注釋是注釋節(jié)點。

          HTML DOM將HTML文檔視作樹結(jié)構(gòu),這種結(jié)構(gòu)被稱為節(jié)點樹,如圖2-11所示。

          圖2-11 節(jié)點樹

          通過HTML DOM,樹中的所有節(jié)點均可通過JavaScript訪問,所有HTML節(jié)點元素均可被修改,也可以被創(chuàng)建或刪除。

          節(jié)點樹中的節(jié)點彼此擁有層級關(guān)系。我們常用父(parent)、子(child)和兄弟(sibling)等術(shù)語描述這些關(guān)系。父節(jié)點擁有子節(jié)點,同級的子節(jié)點被稱為兄弟節(jié)點。

          在節(jié)點樹中,頂端節(jié)點稱為根(root)。除了根節(jié)點之外,每個節(jié)點都有父節(jié)點,同時可擁有任意數(shù)量的子節(jié)點或兄弟節(jié)點。圖2-12展示了節(jié)點樹以及節(jié)點之間的關(guān)系。

          圖2-12 節(jié)點樹及節(jié)點間的關(guān)系

          本段參考W3SCHOOL,鏈接:http://www.w3school.com.cn/htmldom/dom_nodes.asp。

          選擇器

          我們知道網(wǎng)頁由一個個節(jié)點組成,CSS選擇器會根據(jù)不同的節(jié)點設(shè)置不同的樣式規(guī)則,那么怎樣來定位節(jié)點呢?

          在CSS中,我們使用CSS選擇器來定位節(jié)點。例如,上例中div節(jié)點的id為container,那么就可以表示為#container,其中#開頭代表選擇id,其后緊跟id的名稱。另外,如果我們想選擇class為wrapper的節(jié)點,便可以使用.wrapper,這里以點(.)開頭代表選擇class,其后緊跟class的名稱。另外,還有一種選擇方式,那就是根據(jù)標簽名篩選,例如想選擇二級標題,直接用h2即可。這是最常用的3種表示,分別是根據(jù)id、class、標簽名篩選,請牢記它們的寫法。

          另外,CSS選擇器還支持嵌套選擇,各個選擇器之間加上空格分隔開便可以代表嵌套關(guān)系,如#container .wrapper p則代表先選擇id為container的節(jié)點,然后選中其內(nèi)部的class為wrapper的節(jié)點,然后再進一步選中其內(nèi)部的p節(jié)點。另外,如果不加空格,則代表并列關(guān)系,如div#container .wrapper p.text代表先選擇id為container的div節(jié)點,然后選中其內(nèi)部的class為wrapper的節(jié)點,再進一步選中其內(nèi)部的class為text的p節(jié)點。這就是CSS選擇器,其篩選功能還是非常強大的。

          另外,CSS選擇器還有一些其他語法規(guī)則,具體如表2-4所示。

          表2-4 CSS選擇器的其他語法規(guī)則

          另外,還有一種比較常用的選擇器是XPath,這種選擇方式后面會詳細介紹。

          本節(jié)介紹了網(wǎng)頁的基本結(jié)構(gòu)和節(jié)點間的關(guān)系,了解了這些內(nèi)容,我們才有更加清晰的思路去解析和提取網(wǎng)頁內(nèi)容。


          主站蜘蛛池模板: aⅴ一区二区三区无卡无码| 亚洲av乱码中文一区二区三区| 无码免费一区二区三区免费播放| 精品国产毛片一区二区无码| tom影院亚洲国产一区二区| 精品一区中文字幕| 中文字幕一区二区三区在线不卡| 亚洲AV无码一区二区大桥未久| 日韩毛片一区视频免费| 91亚洲一区二区在线观看不卡| 无码日韩精品一区二区人妻 | 亚洲国产一区在线| 日韩一区二区三区视频| 亚洲AV网一区二区三区| 无码av免费一区二区三区试看| 国产美女口爆吞精一区二区| 天美传媒一区二区三区| 无码乱码av天堂一区二区| 亚洲乱码一区二区三区在线观看 | 国产SUV精品一区二区88L| 精品亚洲AV无码一区二区| 无码免费一区二区三区免费播放| 国产一区二区三区夜色| 国产一区二区不卡在线播放| 四虎精品亚洲一区二区三区| 精品一区二区三区在线视频观看| 激情无码亚洲一区二区三区| 日韩精品中文字幕视频一区| 天天视频一区二区三区| 婷婷国产成人精品一区二| 无码日韩人妻AV一区免费l | 日韩精品无码一区二区三区| 理论亚洲区美一区二区三区 | 精品久久久久久中文字幕一区| 亚洲国产精品综合一区在线 | 乱人伦一区二区三区| 国产精品一区二区香蕉| 相泽亚洲一区中文字幕| 亚洲av无码不卡一区二区三区| 骚片AV蜜桃精品一区| 日韩视频一区二区在线观看|