一,、數(shù)據(jù)的類型網(wǎng)頁中數(shù)據(jù)的類型簡單來說可以分成以下三類: 1,、結(jié)構(gòu)化數(shù)據(jù)可以用統(tǒng)一的結(jié)構(gòu)加以表示的數(shù)據(jù),??梢允褂藐P(guān)系型數(shù)據(jù)庫表示和存儲,,表現(xiàn)為二維形式的數(shù)據(jù),。一般特點是:數(shù)據(jù)以行為單位,,一行數(shù)據(jù)表示一個實體的信息,每一行數(shù)據(jù)的屬性是相同的,。 比如MySQL數(shù)據(jù)庫表中的數(shù)據(jù): id name age gender aid1 馬化騰 46 male aid2 馬云 53 male aid3 李彥宏 49 male 2,、半結(jié)構(gòu)化數(shù)據(jù)是結(jié)構(gòu)化數(shù)據(jù)的一種形式,并不符合關(guān)系型數(shù)據(jù)庫或其他數(shù)據(jù)表的形式關(guān)聯(lián)起來的數(shù)據(jù)模型結(jié)構(gòu),,但包含相關(guān)標記,,用來分隔語義元素以及對記錄和字段進行分層。因此,,它也被稱為自描述的結(jié)構(gòu),。常見的半結(jié)構(gòu)數(shù)據(jù)有HTML,XML和JSON等,,實際上是以樹或者圖的結(jié)構(gòu)來存儲的,。 比如,一個簡單的XML表示: <person> <name>A</name> <age>13</age> <class>aid1710</class> <gender>female</gender> </person> 或者 <person> <name>B</name> <gender>male</gender> </person> 結(jié)點中屬性的順序是不重要的,,不同的半結(jié)構(gòu)化數(shù)據(jù)的屬性的個數(shù)是不一定一樣的,。這樣的數(shù)據(jù)格式,可以自由地表達很多有用的信息,,包括自描述信息(元數(shù)據(jù)),。所以,半結(jié)構(gòu)化數(shù)據(jù)的擴展性很好,,特別適合于在互聯(lián)網(wǎng)中大規(guī)模傳播,。 3、非結(jié)構(gòu)化數(shù)據(jù)就是沒有固定結(jié)構(gòu)的數(shù)據(jù),。各種文檔,、圖片,、視頻/音頻等都屬于非結(jié)構(gòu)化數(shù)據(jù)。對于這類數(shù)據(jù),,我們一般直接整體進行存儲,,而且一般存儲為二進制的數(shù)據(jù)格式; 除了結(jié)構(gòu)化和半結(jié)構(gòu)數(shù)據(jù)之外的數(shù)據(jù)都是非結(jié)構(gòu)化數(shù)據(jù),。 二,、關(guān)于XML,HTML,DOM和JSON文件1、XML, HTML, DOMXML即Extentsible Markup Language(可擴展標記語言),,是用來定義其它語言的一種元語言,,其前身是SGML(標準通用標記語言)。它沒有標簽集(tagset),,也沒有語法規(guī)則(grammatical rule),,但是它有句法規(guī)則(syntax rule)。任何XML文檔對任何類型的應(yīng)用以及正確的解析都必須是良構(gòu)的(well-formed),,即每一個打開的標簽都必須有匹配的結(jié)束標簽,,不得含有次序顛倒的標簽,并且在語句構(gòu)成上應(yīng)符合技術(shù)規(guī)范的要求,。XML文檔可以是有效的(valid),,但并非一定要求有效,。所謂有效文檔是指其符合其文檔類型定義(DTD)的文檔,。如果一個文檔符合一個模式(schema)的規(guī)定,那么這個文檔是模式有效的(schema valid),。 HTML(Hyper Text Mark-up Language)即超文本標記語言,,是WWW的描述語言。HTML與XML的區(qū)別與聯(lián)系: XML和HTML都是用于操作數(shù)據(jù)或數(shù)據(jù)結(jié)構(gòu),,在結(jié)構(gòu)上大致是相同的,,但它們在本質(zhì)上卻存在著明顯的區(qū)別。綜合網(wǎng)上的各種資料總結(jié)如下,。 (一)語法要求不同: 1. 在HTML中不區(qū)分大小寫,,在XML中嚴格區(qū)分。 2. 在HTML中,,有時不嚴格,,如果上下文清楚地顯示出段落或者列表鍵在何處結(jié)尾,那么你可以省略</p>或者</li>之類的結(jié)束標記,。在XML中,,是嚴格的樹狀結(jié)構(gòu),絕對不能省略掉結(jié)束標記,。 3. 在XML中,,擁有單個標記而沒有匹配的結(jié)束標記的元素必須用一個/ 字符作為結(jié)尾,。這樣分析器就知道不用查找結(jié)束標記了。 4. 在XML中,,屬性值必須分裝在引號中,。在HTML中,引號是可用可不用的。 5. 在HTML中,,可以擁有不帶值的屬性名,。在XML中,所有的屬性都必須帶有相應(yīng)的值。 6. 在XML文檔中,,空白部分不會被解析器自動刪除; 但是html是過濾掉空格的,。 XML的語法要求比HTML嚴格。 (二)標記不同: 1. HTML使用固有的標記; 而XML沒有固有的標記,。 2. HTML標簽是預(yù)定義的; XML標簽是免費的,、自定義的、可擴展的,。 (三)作用不同: 1. HTML是用來顯示數(shù)據(jù)的; XML是用來描述數(shù)據(jù),、存放數(shù)據(jù)的,所以可以作為持久化的介質(zhì),。HTML將數(shù)據(jù)和顯示結(jié)合在一起,,在頁面中把這數(shù)據(jù)顯示出來;xml則將數(shù)據(jù)和顯示分開,。 XML被設(shè)計用來描述數(shù)據(jù),,其焦點是數(shù)據(jù)的內(nèi)容。HTML被設(shè)計用來顯示數(shù)據(jù),,其焦點是數(shù)據(jù)的外觀,。 2. XML不是HTML的替代品,XML和HTML是兩種不同用途的語言,。 XML 不是要替換 HTML,;實際上XML 可以視作對 HTML 的補充。XML 和HTML 的目標不同HTML 的設(shè)計目標是顯示數(shù)據(jù)并集中于數(shù)據(jù)外觀,,而XML的設(shè)計目標是描述數(shù)據(jù)并集中于數(shù)據(jù)的內(nèi)容,。 3. 沒有任何行為的XML, 與HTML 相似, XML不進行任何操作(共同點)。 4. 對于XML最好的形容可能是: XML是一種跨平臺的,,與軟,、硬件無關(guān)的,處理與傳輸信息的工具,。 5. XML未來將會無所不在,,XML將成為最普遍的數(shù)據(jù)處理和數(shù)據(jù)傳輸?shù)墓ぞ摺?/p> 關(guān)于DOM: 文檔對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴展標志語言的標準編程接口,。在網(wǎng)頁上,,組織頁面(或文檔)的對象被組織在一個樹形結(jié)構(gòu)中,用來表示文檔中對象的標準模型就稱為DOM,。Document Object Model的歷史可以追溯至1990年代后期微軟與Netscape的“瀏覽器大戰(zhàn)”,,雙方為了在JavaScript與JScript一決生死,于是大規(guī)模的賦予瀏覽器強大的功能,。微軟在網(wǎng)頁技術(shù)上加入了不少專屬事物,,既有VBScript、ActiveX,、以及微軟自家的DHTML格式等,,使不少網(wǎng)頁使用非微軟平臺及瀏覽器無法正常顯示。DOM即是當時蘊釀出來的杰作,。 DOM= Document Object Model,,文檔對象模型,DOM可以以一種獨立于平臺和語言的方式訪問和修改一個文檔的內(nèi)容和結(jié)構(gòu),。換句話說,,這是表示和處理一個HTML或XML文檔的常用方法。DOM很重要,,DOM的設(shè)計是以對象管理組織(OMG)的規(guī)約為基礎(chǔ)的,,因此可以用于任何編程語言。最初人們把它認為是一種讓JavaScript在瀏覽器間可移植的方法,,不過DOM的應(yīng)用已經(jīng)遠遠超出這個范圍,。DOM技術(shù)使得用戶頁面可以動態(tài)地變化,如可以動態(tài)地顯示或隱藏一個元素,,改變它們的屬性,,增加一個元素等,,DOM技術(shù)使得頁面的交互性大大地增強,。 DOM實際上是以面向?qū)ο蠓绞矫枋龅奈臋n模型。DOM定義了表示和修改文檔所需的對象,、這些對象的行為和屬性以及這些對象之間的關(guān)系,。可以把DOM認為是頁面上數(shù)據(jù)和結(jié)構(gòu)的一個樹形表示,,不過頁面當然可能并不是以這種樹的方式具體實現(xiàn),。 通過 JavaScript,您可以重構(gòu)整個 HTML 文檔,。您可以添加,、移除、改變或重排頁面上的項目。要改變頁面的某個東西,,JavaScript 就需要獲得對 HTML 文檔中所有元素進行訪問的入口,。這個入口,連同對 HTML 元素進行添加,、移動,、改變或移除的方法和屬性,都是通過文檔對象模型來獲得的(DOM),。 2,、JSON文件JSON(JavaScript Object Notation, JS對象標記) 是一種輕量級的數(shù)據(jù)交換格式。它基于 ECMAScript (w3c制定的JS規(guī)范)的一個子集,,采用完全獨立于編程語言的文本格式來存儲和表示數(shù)據(jù),。簡潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語言。 易于人閱讀和編寫,,同時也易于機器解析和生成,,并有效地提升網(wǎng)絡(luò)傳輸效率。 JSON 語法規(guī)則: 在JS 語言中,,一切都是對象,。因此,任何支持的類型都可以通過 JSON 來表示,,例如字符串,、數(shù)字、對象,、數(shù)組等,。 但是對象和數(shù)組是比較特殊且常用的兩種類型: 1.對象表示為鍵值對 2.數(shù)據(jù)由逗號分隔 3.花括號保存對象 4.方括號保存數(shù)組 JSON鍵值對是用來保存 JS 對象的一種方式,和 JS 對象的寫法也大同小異,, 鍵/值對組合中的鍵名寫在前面并用雙引號 "" 包裹,,使用冒號 : 分隔,然后緊接著值 {"firstName": "Json","class":"aid1710"} 這很容易理解,,等價于這條 JavaScript 語句: {firstName : "Json","class":"aid1710"} JSON與JS對象的關(guān)系: 很多人搞不清楚 JSON 和JS對象的關(guān)系,,甚至連誰是誰都不清楚。其實,,可以這么理解:JSON是 JS對象的字符串表示法,,它使用文本表示一個 JS 對象的信息,本質(zhì)是一個字符串,。 如: var obj = {a: 'Hello', b: 'World'}; //這是一個對象,,注意鍵名也是可以使用引號包裹的 var json = '{"a": "Hello", "b": "World"}'; //這是一個 JSON 字符串,本質(zhì)是一個字符串,。 Python中關(guān)于JSON的操作簡單演示: 代碼示例見 josnTest.py JSON和XML的比較: 1.可讀性: JSON和XML的可讀性可謂不相上下,,一邊是簡易的語法,一邊是規(guī)范的標簽形式,很難分出勝負,。 2.可擴展性: XML天生有很好的擴展性,,JSON當然也有,沒有什么是XML可以擴展而JSON卻不能擴展的,。不過JSON在Javascript主場作戰(zhàn),,可以存儲Javascript復(fù)合對象,有著xml不可比擬的優(yōu)勢,。 3.編碼難度: XML有豐富的編碼工具,,比如Dom4j、JDom等,,JSON也有提供的工具,。無工具的情況下,相信熟練的開發(fā)人員一樣能很快的寫出想要的xml文檔和JSON字符串,,不過,,xml文檔要多很多結(jié)構(gòu)上的字符。 4.解碼難度 XML的解析方式有兩種: 一是通過文檔模型解析,,也就是通過父標簽索引出一組標記,。例如:xmlData.getElementsByTagName("tagName"),但是這樣是要在預(yù)先知道文檔結(jié)構(gòu)的情況下使用,,無法進行通用的封裝,。 另外一種方法是遍歷節(jié)點(document 以及 childNodes)。這個可以通過遞歸來實現(xiàn),,不過解析出來的數(shù)據(jù)仍舊是形式各異,,往往也不能滿足預(yù)先的要求。凡是這樣可擴展的結(jié)構(gòu)數(shù)據(jù)解析起來一定都很困難,。JSON也同樣如此,。如果預(yù)先知道JSON結(jié)構(gòu)的情況下,使用JSON進行數(shù)據(jù)傳遞簡直是太美妙了,,可以寫出很實用美觀可讀性強的代碼,。 如果你是純粹的前臺開發(fā)人員,一定會非常喜歡JSON,。但是如果你是一個應(yīng)用開發(fā)人員,,就不是那么喜歡了,,畢竟xml才是真正的結(jié)構(gòu)化標記語言,,用于進行數(shù)據(jù)傳遞。而如果不知道JSON的結(jié)構(gòu)而去解析JSON的話,,那簡直是噩夢,。費時費力不說,代碼也會變得冗余拖沓,得到的結(jié)果也不盡人意,。 但是這樣也不影響眾多前臺開發(fā)人員選擇JSON,。因為json.js中的toJSONString()就可以看到JSON的字符串結(jié)構(gòu)。當然不是使用這個字符串,,這樣仍舊是噩夢,。常用JSON的人看到這個字符串之后,就對JSON的結(jié)構(gòu)很明了了,,就更容易的操作JSON,。以上是在Javascript中僅對于數(shù)據(jù)傳遞的xml與JSON的解析。 在Javascript地盤內(nèi),,JSON畢竟是主場作戰(zhàn),,其優(yōu)勢當然要遠遠優(yōu)越于xml。 如果JSON中存儲Javascript復(fù)合對象,,而且不知道其結(jié)構(gòu)的話,,相信很多程序員也一樣是哭著解析JSON的。除了上述之外,,JSON和XML還有另外一個很大的區(qū)別在于有效數(shù)據(jù)率,。JSON作為數(shù)據(jù)包格式傳輸?shù)臅r候具有更高的效率,這是因為JSON不像XML那樣需要有嚴格的閉合標簽,,這就讓有效數(shù)據(jù)量與總數(shù)據(jù)包比大大提升,,從而減少同等數(shù)據(jù)流量的情況下,網(wǎng)絡(luò)的傳輸壓力,。 實例比較: XML和JSON都使用結(jié)構(gòu)化方法來標記數(shù)據(jù),,下面來做一個簡單的比較。 用XML表示中國部分省市數(shù)據(jù)如下: <?xml version="1.0" encoding="utf-8"?> <country> <name>中國</name> <province> <name>黑龍江</name> <cities> <city>哈爾濱</city> <city>大慶</city> </cities> </province> <province> <name>廣東</name> <cities> <city>廣州</city> <city>深圳</city> <city>珠海</city> </cities> </province> <province> <name>臺灣</name> <cities> <city>臺北</city> <city>高雄</city> </cities> </province> <province> <name>新疆</name> <cities> <city>烏魯木齊</city> </cities> </province> </country> 用JSON表示如下: { "name": "中國", "province": [{ "name": "黑龍江", "cities": { "city": ["哈爾濱", "大慶"] } }, { "name": "廣東", "cities": { "city": ["廣州", "深圳", "珠海"] } }, { "name": "臺灣", "cities": { "city": ["臺北", "高雄"] } }, { "name": "新疆", "cities": { "city": ["烏魯木齊"] } }] } 可以看到:JSON簡單的語法格式和清晰的層次結(jié)構(gòu)明顯要比XML容易閱讀,,并且在數(shù)據(jù)交換方面,,由于JSON所使用的字符要比XML少得多,可以大大得節(jié)約傳輸數(shù)據(jù)所占用得帶寬,。 三,、 怎么提取網(wǎng)頁中的信息1、 XPath與lxmlXPath是一門在XML文檔中查找信息的語言,,對XPath的理解是很多高級XML應(yīng)用的基礎(chǔ),,XPath在XML中通過元素和屬性進行導航。 lxml是一個用來處理XML的第三方 Python 庫,,它在底層封裝了用 C 語言編寫的 libxml2和libxslt,,并以簡單強大的Python API,兼容并加強了著名的Element Tree API,。 安裝:pip install lxml 使用:from lxml import etree 1. XPath術(shù)語: 在XPath語境中,,XML 文檔被視作節(jié)點樹,,節(jié)點樹的根節(jié)點也被稱作文檔節(jié)點。 XPath 將節(jié)點樹中的節(jié)點(Node)分為七類:元素(Element),,屬性(Attribute),,文本(Text),命名空間(Namespace),,處理指令(Processing-instruction),,注釋(Comment)和文檔節(jié)點(Document nodes)。 看一下 XML 文檔例子: <?xml version="1.0" encoding="ISO-8859-1"?> <bookstore> <book> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore> 以上的XML文檔中: <bookstore> (這是一個“根”) <author>J K. Rowling</author> (這是一個“元素”) lang="en" (這是一個“屬性”) 從另一個視角來看它: bookstore (根) book (元素) title (元素) lang = en (屬性) text = Harry Potter (文本) author (元素) text = J K. Rowling (文本) year (元素) text = 2005 (文本) price (元素) text = 29.99 (文本) 2. 節(jié)點之間的關(guān)系 父(Parent):每個元素都肯定有一個父節(jié)點,,最頂層的元素父親是根節(jié)點,。同理每個屬性必然有一個父,它們的父是元素,。 上例XML文檔中,,根bookstore是元素 book 的父節(jié)點,book是元素title, author, year, price 的父節(jié)點,,title是lang 的父節(jié)點,。 子(Children):元素可以有零或多個子。上例XML文檔中,,title, author, year, price是book的子節(jié)點,。 同胞(Sibling):父節(jié)點相同的節(jié)點之間互為同胞,也稱彼此的兄弟節(jié)點,。上例XM文檔中,,title, author, year, price 彼此互為同胞。 先輩(Ancestor):某節(jié)點的父節(jié)點,、父的父,,以此類推一直追溯至根節(jié)點之間所有節(jié)點。上例XM文檔中,,title, author, year, price 的先輩就是 book, bookstore,。 后代(Descendant):某節(jié)點的子節(jié)點、子的子,,以此類推至最后一個子節(jié)點之間所有節(jié)點,。上例XM文檔中,bookstore 的后代就是 title, author, year, price ,。 3.選取節(jié)點 以下為基本路徑的表達方式,,記住XPath的路徑表達式都是基于某個節(jié)點之上的,例如最初的當前節(jié)點一般是根節(jié)點,,這與Linux下路徑切換原理是一樣的,。 表達式描述: nodename 選取已匹配節(jié)點下名為 nodename 的子元素節(jié)點 / 如果以 / 開頭,表示從根節(jié)點作為選取起點,。 // 在已匹配節(jié)點后代中選取節(jié)點,,不考慮目標節(jié)點的位置,。 . 選取當前節(jié)點,。 .. 選取當前節(jié)點的父元素節(jié)點,。 @ 選取屬性。 4.通配符 * 匹配任何元素,。 @* 匹配任何屬性,。 node() 匹配任何類型的節(jié)點。 5.預(yù)判(Predicates)或 條件選取 預(yù)判是用來查找某個特定的節(jié)點或者符合某種條件的節(jié)點,,預(yù)判表達式位于方括號中,。使用 “|” 運算符,你可以選取符合“或”條件的若干路徑,。 具體例子見下面代碼lxmlTest.py,。 6.坐標軸 XPath 坐標軸:坐標軸用于定義當對當前節(jié)點的節(jié)點集合。 坐標軸名稱 含義 ancestor 選取當前節(jié)點的所有先輩元素及根節(jié)點,。 ancestor-or-self 選取當前節(jié)點的所有先輩以及當前節(jié)點本身,。 attibute 選取當前節(jié)點的所有屬性。 child 選取當前節(jié)點的所有子元素,。 descendant 選取當前節(jié)點的所有后代元素,。 descendant-or-self 選取當前節(jié)點的所有后代元素以及當前節(jié)點本身。 following 選取文檔中當前節(jié)點的結(jié)束標簽之后的所有節(jié)點,。 following-sibling 選取當前節(jié)點之后的所有同級節(jié)點,。 namespace 選取當前節(jié)點的所有命名空間節(jié)點。 parent 選取當前節(jié)點的父節(jié)點,。 preceding 選取當前節(jié)點的開始標簽之前的所有節(jié)點,。 preceding-sibling 選取當前節(jié)點之前的所有同級節(jié)點。 self 選取當前節(jié)點,。 7.位置路徑的表達式 位置路徑可以是絕對路徑,,也可以是相對路徑。絕對路徑以 “/” 開頭,。每條路徑包括一個或多個步,,每步之間以“/”分隔。 絕對路徑:/step/step/… 相對路徑:step/step/… 每步根據(jù)當前節(jié)點集合中的節(jié)點計算,。 步(step)包括三部分: 坐標軸(axis): 定義所選節(jié)點與當前節(jié)點之間的關(guān)系,。 節(jié)點測試(node-test):識別某個坐標軸內(nèi)部的節(jié)點。 預(yù)判(predicate): 提出預(yù)判條件對節(jié)點集合進行篩選,。 步的語法:坐標軸::節(jié)點測試[預(yù)判] 2,、 BeautifulSoup4Beautiful Soup是用Python寫的一個HTML/XML的解析器,它可以很好的處理不規(guī)范標記并生成剖析樹(parse tree),。 它提供簡單又常用的導航(navigating),,搜索以及修改剖析樹的操作,。它可以大大節(jié)省你的編程時間。 安裝:(sudo) pip install beautifuilsoup4 使用: 在程序中導入 Beautiful Soup庫: from BeautifulSoup import BeautifulSoup # For processing HTML from BeautifulSoup import BeautifulStoneSoup # For processing XML import BeautifulSoup # To get everything # 代碼例子 from bs4 import BeautifulSoup import re doc = ['<html><head><title>Page title</title></head>', '<body><p id="firstpara" align="center">This is paragraph <b>one</b>.', '<p id="secondpara" align="blah">This is paragraph <b>two</b>.', '</html>'] soup = BeautifulSoup(''.join(doc)) print soup.prettify() 定位某些 soup元素很簡單,,比如上例: soup.contents[0].name # u'html' soup.contents[0].contents[0].name # u'head' head = soup.contents[0].contents[0] head.parent.name # u'html' head.next # <title>Page title</title> head.nextSibling.name # u'body' head.nextSibling.contents[0] # <p id="firstpara" align="center">This is paragraph <b>one</b>.</p> head.nextSibling.contents[0].nextSibling # <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p> 也可以利用soup,,獲得特定標簽或有著特定屬性的標簽,修改soup也很簡單,; BS4 與 lxml的比較: lxml C實現(xiàn),,只會局部遍歷,快; 復(fù)雜,,語法不太友好,; BS4 Python實現(xiàn),會加載整個文檔,慢,; 簡單,,API人性化; 3,、正則表達式re被用來檢索\替換那些符合某個模式(規(guī)則)的文本,對于文本過濾或規(guī)則匹配,最強大的就是正則表達式,是python爬蟲里必不可少的神兵利器,。 基本匹配規(guī)則: [0-9] 任意一個數(shù)字,等價\d [a-z] 任意一個小寫字母 [A-Z]任意一個大寫字母 [^0-9] 匹配非數(shù)字,,等價\D \w 等價[a-z0-9_],,字母數(shù)字下劃線 \W 等價對\w取非 . 任意字符 [] 匹配內(nèi)部任意字符或子表達式 [^] 對字符集合取非 * 匹配前面的字符或者子表達式0次或多次 + 匹配前一個字符至少1次 ? 匹配前一個字符0次或多次 ^ 匹配字符串開頭 $ 匹配字符串結(jié)束 Python使用正則表達式 Python的re模塊 pattern 編譯好的正則表達式 幾個重要的方法: match: 匹配一次從開頭; search: 匹配一次,,從某位置,; findall: 匹配所有; split: 分隔,; sub: 替換,; 需要注意的兩種模式: 貪婪模式:(.*) 懶惰模式:(.*?) 3. 用正則表達式實現(xiàn)下面的效果: 把 i=d%0A&from=AUTO&to=AUTO&smartresult=dict 轉(zhuǎn)換成下面的形式: i:d%0A from:AUTO to:AUTO smartresult:dict 總結(jié):正則,BS,,lxml的比較
|
|
來自: zhulin1028 > 《待分類》