數(shù)據(jù)采集與預(yù)處理PPT完整全套教學(xué)課件_第1頁
數(shù)據(jù)采集與預(yù)處理PPT完整全套教學(xué)課件_第2頁
數(shù)據(jù)采集與預(yù)處理PPT完整全套教學(xué)課件_第3頁
數(shù)據(jù)采集與預(yù)處理PPT完整全套教學(xué)課件_第4頁
數(shù)據(jù)采集與預(yù)處理PPT完整全套教學(xué)課件_第5頁
已閱讀5頁,還剩330頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第一章數(shù)據(jù)采集與預(yù)處理準(zhǔn)備

授課講師:XXX全套PPT課件目錄

Contents01認(rèn)識數(shù)據(jù)采集技術(shù)熟悉數(shù)據(jù)采集平臺02認(rèn)識數(shù)據(jù)預(yù)處理技術(shù)01學(xué)習(xí)目標(biāo)學(xué)習(xí)目標(biāo)識記數(shù)據(jù)采集與預(yù)處理的概念和目的領(lǐng)會數(shù)據(jù)采集與預(yù)處理的意義熟悉數(shù)據(jù)采集技術(shù)熟悉數(shù)據(jù)預(yù)處理技術(shù)學(xué)會數(shù)據(jù)采集與預(yù)處理環(huán)境搭建技能目標(biāo)知識目標(biāo)02任務(wù)1.1:認(rèn)識數(shù)據(jù)采集技術(shù),熟悉數(shù)據(jù)采集平臺(1)知道數(shù)據(jù)采集的來源和采集的方法。(2)學(xué)會數(shù)據(jù)采集平臺的搭建。(1)學(xué)習(xí)數(shù)據(jù)采集等相關(guān)知識內(nèi)容,熟悉大數(shù)據(jù)的定義、大數(shù)據(jù)的基本特征及數(shù)據(jù)采集的相關(guān)技術(shù)、工具或產(chǎn)品。(2)熟悉數(shù)據(jù)采集的來源和采集方法。(3)完成scrapy平臺搭建。(4)完成ApacheFlume平臺搭建。任務(wù)描述任務(wù)目標(biāo)任務(wù)描述任務(wù)目標(biāo)數(shù)據(jù)采集概念大數(shù)據(jù)(BigData),指無法在一定時(shí)間范圍內(nèi)用常規(guī)軟件工具進(jìn)行捕捉、管理和處理的數(shù)據(jù)集合,是需要新處理模式才能具有更強(qiáng)的決策力、洞察發(fā)現(xiàn)力和流程優(yōu)化能力的海量、高增長率和多樣化的信息資產(chǎn)。數(shù)據(jù)采集的ETL工具負(fù)責(zé)將分布的、異構(gòu)數(shù)據(jù)源中的不同種類和結(jié)構(gòu)的數(shù)據(jù)如文本數(shù)據(jù)、關(guān)系數(shù)據(jù)以及圖片、視頻等非結(jié)構(gòu)化數(shù)據(jù)等抽取到臨時(shí)中間層后進(jìn)行清洗、轉(zhuǎn)換、分類、集成,最后加載到對應(yīng)的數(shù)據(jù)存儲系統(tǒng)如數(shù)據(jù)倉庫中,成為聯(lián)機(jī)分析處理、數(shù)據(jù)挖掘的基礎(chǔ)。知識準(zhǔn)備根據(jù)MapReduce產(chǎn)生數(shù)據(jù)的應(yīng)用系統(tǒng)分類,大數(shù)據(jù)的采集主要有四種來源:管理信息系統(tǒng)、web信息系統(tǒng)、物理信息系統(tǒng)、科學(xué)實(shí)驗(yàn)系統(tǒng)。(1)管理信息系統(tǒng)管理信息系統(tǒng)是指企業(yè)、機(jī)關(guān)內(nèi)部的信息系統(tǒng),如事務(wù)處理系統(tǒng)、辦公自動(dòng)化系統(tǒng),主要用于經(jīng)營和管理,為特定用戶的工作和業(yè)務(wù)提供支持。數(shù)據(jù)的產(chǎn)生既有終端用戶的始輸人,也有系統(tǒng)的二次加工處理。系統(tǒng)的組織結(jié)構(gòu)上是專用的,數(shù)據(jù)通常是結(jié)構(gòu)化的。數(shù)據(jù)采集來源(2)Web信息系統(tǒng)web信息系統(tǒng)包括互聯(lián)網(wǎng)上的各種信息系統(tǒng),如社交網(wǎng)站、社會媒體、系統(tǒng)引擎等,主要用于構(gòu)造虛擬的信息空間,為廣大用戶提供信息服務(wù)和社交服務(wù)。系統(tǒng)的組織結(jié)構(gòu)是開放式的,大部分?jǐn)?shù)據(jù)是半結(jié)構(gòu)化或無結(jié)構(gòu)的。數(shù)據(jù)的產(chǎn)生者主要是在線用戶。(3)物理信息系統(tǒng)物理信息系統(tǒng)是指關(guān)于各種物理對象和物理過程的信息系統(tǒng),如實(shí)時(shí)監(jiān)控、實(shí)時(shí)檢測,主要用于生產(chǎn)調(diào)度、過程控制、現(xiàn)場指揮、環(huán)境保護(hù)等。系統(tǒng)的組織結(jié)構(gòu)上是封閉的,數(shù)據(jù)由各種嵌入式傳感設(shè)備產(chǎn)生,可以是關(guān)于物理、化學(xué)、生物等性質(zhì)和狀態(tài)的基本測量值,也可以是關(guān)于行為和狀態(tài)的音頻、視頻等多媒體數(shù)據(jù)。(4)科學(xué)實(shí)驗(yàn)系統(tǒng)科學(xué)實(shí)驗(yàn)系統(tǒng)實(shí)際上也屬于物理信息系統(tǒng),但其實(shí)驗(yàn)環(huán)境是預(yù)先設(shè)定的,主要用于研究和學(xué)術(shù),數(shù)據(jù)是有選擇的、可控的,有時(shí)可能是人工模擬生成的仿真數(shù)據(jù)。數(shù)據(jù)往往表現(xiàn)為具有不同形式的數(shù)據(jù)。數(shù)據(jù)采集方法①系統(tǒng)日志采集方法很多互聯(lián)網(wǎng)企業(yè)都有自己的海量數(shù)據(jù)采集工具,多用于系統(tǒng)日志采集,如Hadoop的Chukwa、Cloudera的Flume、Facebook的Scribe等這些工具均采用分布式架構(gòu),能滿足每秒數(shù)百M(fèi)B的日志數(shù)據(jù)采集和傳輸需求。②網(wǎng)絡(luò)數(shù)據(jù)采集方法:對非結(jié)構(gòu)化數(shù)據(jù)的采集網(wǎng)絡(luò)數(shù)據(jù)采集是指通過網(wǎng)絡(luò)爬蟲或網(wǎng)站公開API等方式從網(wǎng)站上獲取數(shù)據(jù)信息,該方法可以將非結(jié)構(gòu)化數(shù)據(jù)從網(wǎng)頁中抽取出來,將其存儲為統(tǒng)一的本地?cái)?shù)據(jù)文件,并以結(jié)構(gòu)化的方式存儲。它支持圖片、音頻、視頻等文件或附件的采集,附件與正文可以自動(dòng)關(guān)聯(lián)。除了網(wǎng)絡(luò)中包含的內(nèi)容之外,對于網(wǎng)絡(luò)流量的采集可以使用DPI或DFI等帶寬管理技術(shù)進(jìn)行處理。③其他數(shù)據(jù)采集方法對于企業(yè)生產(chǎn)經(jīng)營數(shù)據(jù)或?qū)W科研究數(shù)據(jù)等保密性要求較高的數(shù)據(jù),可以通過與企業(yè)、研究機(jī)構(gòu)合作或授權(quán)的方式,使用特定系統(tǒng)接口等相關(guān)方式采集數(shù)據(jù)。任務(wù)實(shí)施Scrapy是Python開發(fā)的一個(gè)快速、高層次的屏幕抓取和web抓取框架,任何人都可以根據(jù)需求方便的對它進(jìn)行修改,用于從web頁面中提取結(jié)構(gòu)化的數(shù)據(jù),它提供了多種類型爬蟲的基類,如BaseSpider、sitemap、web2.0爬蟲的支持。(1)安裝所需的環(huán)境右擊Ubuntu操作系統(tǒng)桌面,從彈出的菜單中選擇【openinTerminal】命令打開終端,在終端中輸入命令【sudoapt-getinstallpython-pip】安裝pip。如圖所示:scrapy系統(tǒng)環(huán)境搭建pip是一個(gè)現(xiàn)代的,通用的Python包管理工具,提供了對Python包的查找、下載、安裝、卸載的功能。我們需要將pip更新到最新版本。在命令行中執(zhí)行命令【pipinstall--upgradepip】如圖所示:pip更新完成后,就可以安裝Scrapy了。在命令行中執(zhí)行命令【pipinstallscrapy】如圖所示:(2)驗(yàn)證scrapy框架安裝是否成功在命令行中輸入命令【scrapy】,出現(xiàn)如圖所示內(nèi)容,即為安裝成功日志系統(tǒng)環(huán)境搭建Flume是Cloudera提供的一個(gè)高可用的,高可靠的,分布式的海量日志采集、聚合和傳輸?shù)南到y(tǒng),F(xiàn)lume支持在日志系統(tǒng)中定制各類數(shù)據(jù)發(fā)送方,用于收集數(shù)據(jù);同時(shí),F(xiàn)lume提供對數(shù)據(jù)進(jìn)行簡單處理,并寫到各種數(shù)據(jù)接受方(可定制)的能力。(1)安裝flumeFlume需要jdk環(huán)境支持,可以使用java-version查看系統(tǒng)是否配置了JDK環(huán)境,顯示如圖結(jié)果即為配置了jdk環(huán)境否則,需要先下載安裝JDK環(huán)境。①到官方網(wǎng)站下載apache-flume-1.8.0-bin.tar.gz。執(zhí)行以下命令,完成壓縮包的解壓與安裝。cd~/Downloadssudotar-zxvfapache-flume-1.8.0-bin.tar.gz-C/usr/local②修改權(quán)限和命名首先,使用id命令確定本機(jī)的用戶和組。如圖所示:其次,執(zhí)行以下命令更改用戶和組修改文件權(quán)限,效果如圖所示:cd/usr/localsudochown-Ra(用戶):a(組)apache-flume-1.7.0-bin修改名字,如圖所示:(2)配置環(huán)境變量。①配置環(huán)境變量執(zhí)行sudogedit/etc/profile命令,在profile文件中添加如圖語句。添加完成并保存后,需要使用如下命令使環(huán)境變量生效。source/etc/profile。②修改配置文件flume-env.sh。進(jìn)入/usr/local/flume/conf目錄下,進(jìn)行如下操作,如圖所示:在flume-env.sh文件開頭加入如圖語句:(3)驗(yàn)證Flume框架安裝是否成功。運(yùn)行下面語句cd/usr/local/flume./bin/flume-ngversion顯示如圖所示信息,則表示Flume安裝成功。任務(wù)1.2:認(rèn)識數(shù)據(jù)預(yù)處理技術(shù)03(1)了解原始數(shù)據(jù)存在的主要問題。(2)明白數(shù)據(jù)預(yù)處理的作用和工作任務(wù)。(3)學(xué)會數(shù)據(jù)處理工具平臺的搭建。(1)學(xué)習(xí)數(shù)據(jù)預(yù)處理技術(shù)等相關(guān)知識內(nèi)容,學(xué)會數(shù)據(jù)清洗的主要任務(wù)和常用方法;數(shù)據(jù)集成的主要任務(wù)和常用方法;數(shù)據(jù)變換的主要任務(wù)和常用方法;數(shù)據(jù)規(guī)約的主要任務(wù)和常用方法。(2)完成pig系統(tǒng)環(huán)境搭建。(3)完成kettle系統(tǒng)環(huán)境搭建。任務(wù)描述任務(wù)目標(biāo)知識準(zhǔn)備——數(shù)據(jù)預(yù)處理的概念數(shù)據(jù)預(yù)處理是指在對數(shù)據(jù)進(jìn)行數(shù)據(jù)挖掘的主要處理以前,先對原始數(shù)據(jù)進(jìn)行必要的清理、集成、轉(zhuǎn)換、離散、歸約、特征選擇和提取等一系列處理工作,達(dá)到挖掘算法進(jìn)行知識獲取研究所要求的最低規(guī)范和標(biāo)準(zhǔn)。數(shù)據(jù)挖掘的對象是從現(xiàn)實(shí)世界采集到的大量的各種各樣的數(shù)據(jù)。由于現(xiàn)實(shí)生產(chǎn)和實(shí)際生活以及科學(xué)研究的多樣性、不確定性、復(fù)雜性等,導(dǎo)致采集到的原始數(shù)據(jù)比較散亂,它們是不符合挖掘算法進(jìn)行知識獲取研究所要求的規(guī)范和標(biāo)準(zhǔn)的,主要具有以下特征。(1)不完整性。不完整性指的是數(shù)據(jù)記錄中可能會出現(xiàn)有些數(shù)據(jù)屬性的值丟失或不確定的情況,還有可能缺失必需的數(shù)據(jù)。這是由于系統(tǒng)設(shè)計(jì)時(shí)存在的缺陷或者使用過程中一些人為因素造成的,如有些數(shù)據(jù)缺失只是因?yàn)檩斎霑r(shí)認(rèn)為是不重要的,相關(guān)數(shù)據(jù)沒有記錄可能是由于理解錯(cuò)誤,或者因?yàn)樵O(shè)備故障,與其他記錄不一致的數(shù)據(jù)可能已經(jīng)刪除,歷史記錄或修改的數(shù)據(jù)可能被忽略等。(2)含噪聲。含噪聲指的是數(shù)據(jù)具有不正確的屬性值,包含錯(cuò)誤或存在偏離期望的離群值(指與其他數(shù)值比較差異較大的值)。產(chǎn)生的原因很多,例如收集數(shù)據(jù)的設(shè)備可能出故障,人或計(jì)算機(jī)的錯(cuò)誤可能在數(shù)據(jù)輸入時(shí)出現(xiàn),數(shù)據(jù)傳輸中也可能出現(xiàn)錯(cuò)誤等。不正確的數(shù)據(jù)也可能是由命名約定或所用的數(shù)據(jù)代碼不一致,或輸入字段(如時(shí)間)的格式不一致而導(dǎo)致的。實(shí)際使用的系統(tǒng)中,還可能存在大量的模糊信息,有些數(shù)據(jù)甚至還具有一定的隨機(jī)性。①數(shù)據(jù)采樣。數(shù)據(jù)采樣技術(shù)分為加權(quán)采樣、隨機(jī)采樣和分層采樣三類,其目的是從數(shù)據(jù)集中采集部分樣本進(jìn)行處理。加權(quán)采樣:其思想是通過對總體中的各個(gè)樣本設(shè)置不同的數(shù)值系數(shù)(即權(quán)重),使樣本呈現(xiàn)希望的相對重要性程度。

隨機(jī)采樣:其是最常用的方法。許多算法在初始化時(shí)計(jì)算數(shù)據(jù)的隨機(jī)樣本,隨機(jī)樣本可以利用事先準(zhǔn)備好的己排序的隨機(jī)數(shù)表來得到。但是,有時(shí)為了得到更高的性能,希望能夠隨時(shí)取得隨機(jī)的樣本,通過使用隨機(jī)函數(shù)可以實(shí)現(xiàn)這個(gè)目的。分層采樣:其思想是根據(jù)數(shù)據(jù)分布的不均衡控制采樣的頻率。在數(shù)據(jù)分布密度較高時(shí),采樣的頻率適當(dāng)降低;在數(shù)據(jù)分布密度較低時(shí),采樣的頻率適當(dāng)提高。②數(shù)據(jù)清理。數(shù)據(jù)清理技術(shù)通常包括填補(bǔ)遺漏的數(shù)據(jù)值、平滑有噪聲數(shù)據(jù)、識別或除去異常值,以及解決不一致問題。填補(bǔ)遺漏的數(shù)據(jù)值,處理不完備數(shù)據(jù)集的方法主要有以下三大類:a.刪除元組也就是將存在遺漏信息屬性值的對象(元組,記錄)刪除,從而得到一個(gè)完備的信息表。這種方法簡單易行,在對象有多個(gè)屬性缺失值、被刪除的含缺失值的對象與信息表中的數(shù)據(jù)量相比非常小的情況下是非常有效的。然而,這種方法卻有很大的局限性。它是以減少歷史數(shù)據(jù)來換取信息的完備,會造成資源的大量浪費(fèi),丟棄了大量隱藏在這些對象中的信息。在信息表中本來包含的對象很少的情況下,刪除少量對象就足以嚴(yán)重影響到信息表信息的客觀性和結(jié)果的正確性;當(dāng)每個(gè)屬性空值的百分比變化很大時(shí),它的性能非常差。b.數(shù)據(jù)補(bǔ)齊這類方法是用一定的值去填充空值,從而使信息表完備化。通?;诮y(tǒng)計(jì)學(xué)原理,根據(jù)決策表中其余對象取值的分布情況來對一個(gè)空值進(jìn)行填充,譬如用其余屬性的平均值來進(jìn)行補(bǔ)充等。數(shù)據(jù)挖掘中常用的有以下幾種補(bǔ)齊方法:人工填寫:由于最了解數(shù)據(jù)的還是用戶自己,因此這個(gè)方法產(chǎn)生數(shù)據(jù)偏離最小,可能是填充效果最好的一種。然而一般來說,該方法很費(fèi)時(shí),當(dāng)數(shù)據(jù)規(guī)模很大、空值很多的時(shí)候,該方法是不可行的。

特殊值填充:將空值作為一種特殊的屬性值來處理,它不同于其他的任何屬性值。如所有的空值都用“unknown”填充。這樣將形成另一個(gè)有趣的概念,可能導(dǎo)致嚴(yán)重的數(shù)據(jù)偏離,一般不推薦使用。熱卡填充(或就近補(bǔ)齊):對于一個(gè)包含空值的對象,熱卡填充法在完整數(shù)據(jù)中找到一個(gè)與它最相似的對象,然后用這個(gè)相似對象的值來進(jìn)行填充。不同的問題可能會選用不同的標(biāo)準(zhǔn)來對相似進(jìn)行判定。該方法概念上很簡單,且利用了數(shù)據(jù)間的關(guān)系來進(jìn)行空值估計(jì)。這個(gè)方法的缺點(diǎn)在于難以定義相似標(biāo)準(zhǔn),主觀因素較多。平均值填充:將信息表中的屬性分為數(shù)值屬性和非數(shù)值屬性來分別進(jìn)行處理。如果空值是數(shù)值型的,就根據(jù)該屬性在其他所有對象的取值的平均值來填充該缺失的屬性值;如果空值是非數(shù)值型的,就根據(jù)統(tǒng)計(jì)學(xué)中的眾數(shù)原理,用該屬性在其他所有對象的取值次數(shù)最多的值(即出現(xiàn)頻率最高的值)來補(bǔ)齊該缺失的屬性值。另外有一種與其相似的方法叫條件平均值填充法。在該方法中,缺失屬性值的補(bǔ)齊同樣是靠該屬性在其他對象中的取值求平均得到,但不同的是用于求平均的值并不是從信息表所有對象中取,而是從與該對象具有相同決策屬性值的對象中取得。組合完整化方法:這種方法是用空缺屬性值的所有可能的屬性取值來試,并從最終屬性的約簡結(jié)果中選擇最好的一個(gè)作為填補(bǔ)的屬性值。這是以約簡為目的的數(shù)據(jù)補(bǔ)齊方法,能夠得到好的約簡結(jié)果;但是,當(dāng)數(shù)據(jù)量很大或者遺漏的屬性值較多時(shí),其計(jì)算的代價(jià)很大。另一種稱為條件組合完整化方法,填補(bǔ)遺漏屬性值的原則是一樣的,不同的只是從決策相同的對象中嘗試所有的屬性值的可能情況,而不是根據(jù)信息表中所有對象進(jìn)行嘗試。條件組合完整化方法能夠在一定程度上減小組合完整化方法的代價(jià)。在信息表包含不完整數(shù)據(jù)較多的情況下,可能的測試方案將巨增?;貧w:基于完整的數(shù)據(jù)集,建立回歸方程(模型)。對于包含空值的對象,將已知屬性值代入方程來估計(jì)未知屬性值,以此估計(jì)值來進(jìn)行填充。當(dāng)變量不是線性相關(guān)或預(yù)測變量高度相關(guān)時(shí)會導(dǎo)致有偏差的估計(jì)。c.平滑有噪聲數(shù)據(jù)噪聲是一個(gè)測量變量中的隨機(jī)錯(cuò)誤或偏差,包括錯(cuò)誤值或偏離期望的孤立點(diǎn)值。數(shù)據(jù)平滑技術(shù)包含:分箱:分箱方法通過考察數(shù)據(jù)的“近鄰”(即,周圍的值)來光滑有序數(shù)據(jù)值。這些有序的值被分布到一些“桶”或箱中。由于分箱方法考察近鄰的值,因此它進(jìn)行的是局部光滑。用箱均值光滑:箱中每一個(gè)值被箱中的平均值替換。用箱中位數(shù)平滑:箱中的每一個(gè)值被箱中的中位數(shù)替換。用箱邊界平滑:箱中的最大和最小值同樣被視為邊界。箱中的每一個(gè)值被最近的邊界值替換。一般而言,寬度越大,光滑效果越明顯。箱也可以是等寬的,其中每個(gè)箱值的區(qū)間范圍是個(gè)常量。分箱也可以作為一種離散化技術(shù)使用?;貧w:也可以用一個(gè)函數(shù)擬合數(shù)據(jù)來光滑數(shù)據(jù)。線性回歸涉及找出擬合兩個(gè)屬性(或變量)的“最佳”直線,使得一個(gè)屬性能夠預(yù)測另一個(gè)。多線性回歸是線性回歸的擴(kuò)展,它涉及多于兩個(gè)屬性,并且數(shù)據(jù)擬合到一個(gè)多維面。使用回歸,找出適合數(shù)據(jù)的數(shù)學(xué)方程式,能夠幫助消除噪聲。聚類:可以通過聚類來檢測離群點(diǎn),將類似的值組織成群或“簇”。直觀地,落在簇集合之外的值被視為離群點(diǎn)。③數(shù)據(jù)集成。將來自多個(gè)數(shù)據(jù)源的數(shù)據(jù)合并,形成一致的數(shù)據(jù)存儲,如將不同數(shù)據(jù)庫中的數(shù)據(jù)集成到一個(gè)數(shù)據(jù)倉庫中存儲。有時(shí)數(shù)據(jù)集成之后還需要進(jìn)行數(shù)據(jù)清理,以便消除可能存在的數(shù)據(jù)冗余④數(shù)據(jù)變換。主要是將數(shù)據(jù)轉(zhuǎn)換成適合于挖掘的形式,如將屬性數(shù)據(jù)按比例縮放,使之落入一個(gè)比較小的特定區(qū)間,這一點(diǎn)對那些基于距離的挖掘算法尤為重要。數(shù)據(jù)變換的具體方法包括平滑處理、聚集處理、數(shù)據(jù)泛化處理、規(guī)格化、屬性構(gòu)造。⑤數(shù)據(jù)歸約(DataReduction)。在不影響挖掘結(jié)果的前提下,通過數(shù)值聚集、刪除冗余特性的辦法壓縮數(shù)據(jù),提高挖掘模式的質(zhì)量,降低時(shí)間復(fù)雜度。數(shù)據(jù)規(guī)約策略包括維歸約、數(shù)量規(guī)約和數(shù)據(jù)壓縮。維歸約減少所考慮的隨機(jī)變量或?qū)傩缘膫€(gè)數(shù)。用于分析的數(shù)據(jù)集可能包含數(shù)以百計(jì)的屬性,其中大部分屬性與挖掘任務(wù)不相關(guān)或冗余,例如,分析銀行客戶的信用度時(shí),諸如客戶的電話號碼、家庭住址等屬性就與該數(shù)據(jù)挖掘任務(wù)不相關(guān),或者說是冗余的。維歸約通過減少不相關(guān)的屬性(或維)達(dá)到減少數(shù)據(jù)集規(guī)模的目的。⑥特征選擇。將高維空間的樣本通過映射或者是變換的方式轉(zhuǎn)換到低維空間,達(dá)到降維的目的,然后通過特征選取刪選掉冗余和不相關(guān)的特征來進(jìn)一步降維。特征選擇是從原始特征中挑選出一些最優(yōu)代表性的特征,它分為過濾式、封裝式和嵌入式3種類型⑦特征提取。特征提取就是利用已有特征參數(shù)構(gòu)造一個(gè)較低維數(shù)的特征空間,將原始特征中蘊(yùn)含的有用信息映射到少數(shù)幾個(gè)特征上,忽略多余的不相干信息。簡單點(diǎn)說,特征提取是用映射(或變換)的方法把原始特征變換為較少的新特征。特征提取的方法有很多種,如傳統(tǒng)的特征提取的數(shù)據(jù)挖掘技術(shù)、統(tǒng)計(jì)特征提取技術(shù)、神經(jīng)網(wǎng)絡(luò)法等。任務(wù)實(shí)施——pig系統(tǒng)環(huán)境搭建(1)到官方網(wǎng)站下載pig-0.17.0-src.tar.gz,并解壓到/usr/local目錄,如圖所示:

解壓完成后進(jìn)入/usr/local中將文件進(jìn)行改名,方便后續(xù)使用。如圖所示:(2)配置環(huán)境變量打開終端,輸入sudovim~/.bashrc,配置相關(guān)環(huán)境變量。如圖所示:配置完成并保存后,執(zhí)行source~/.bashrc使配置的環(huán)境變量生效(3)驗(yàn)證Pig是否安裝成功。打開兩個(gè)終端,分別輸入pig-xlocal、pig-xmapreduce測試它的兩種運(yùn)行模式,顯示相關(guān)信息如圖所示,則表示安裝成功。任務(wù)實(shí)施——Kettle系統(tǒng)環(huán)境搭建(1)到官方網(wǎng)站下載pdi-ce--12.zip,并解壓到/usr/local目錄。如圖所示:解壓完成后進(jìn)入/usr/local中將文件進(jìn)行改名,方便后續(xù)使用。如圖所示:(2)配置環(huán)境變量打開終端,輸入sudovim~/.bashrc,配置相關(guān)環(huán)境變量。如圖所示:配置完成并保存后,執(zhí)行source~/.bashrc使配置的環(huán)境變量生效。(3)驗(yàn)證Kettle安裝是否成功。打開終端,切換到/usr/local/kettle路徑下,執(zhí)行./spoon.sh命令,顯示如圖所示,則表示安裝成功。THANKS!第二章網(wǎng)絡(luò)爬蟲實(shí)踐

授課講師:XXX目錄

Contents

使用urllib爬取北京公交線路信息

使用selenium爬取淘寶網(wǎng)站信息

使用scrapy爬取北京公交信息01020301學(xué)習(xí)目標(biāo)學(xué)習(xí)目標(biāo)識記網(wǎng)絡(luò)爬蟲的結(jié)構(gòu)。熟悉網(wǎng)絡(luò)爬蟲的基礎(chǔ)知識。熟悉爬蟲基本庫urllib和selenium的使用。熟悉BeautifulSoup和pyquery解析庫的使用。學(xué)會編寫網(wǎng)絡(luò)爬蟲采集“北京公交線路”相關(guān)信息技能目標(biāo)知識目標(biāo)02任務(wù)2.1:使用urllib爬取北京公交線路信息(1)知道urllib基本庫和BeautifulSoup解析庫的使用方法。(2)使用urllib基本庫和BeautifulSoup解析庫,學(xué)會北京公交線路相關(guān)信息的爬?。?)學(xué)習(xí)網(wǎng)絡(luò)爬蟲相關(guān)技術(shù),熟悉爬蟲基本庫urllib的使用。(2)熟悉網(wǎng)絡(luò)爬蟲相關(guān)基礎(chǔ)知識。(3)使用urllib基本庫,獲取北京公交線路信息的html源代碼。(4)使用BeautifulSoup解析庫,完成北京公交線路相關(guān)信息的獲取。任務(wù)描述任務(wù)目標(biāo)知識準(zhǔn)備網(wǎng)絡(luò)爬蟲(又被稱為網(wǎng)頁蜘蛛)其本質(zhì)上就是獲取網(wǎng)頁并提取和保存信息的自動(dòng)化程序。(1)獲取網(wǎng)頁爬蟲的首要工作就是獲取網(wǎng)頁源代碼,然后從中提取想要的數(shù)據(jù)。在python中,提供了許多庫來幫助實(shí)現(xiàn)這個(gè)操作,如Urllib、Requests等,使用這些庫可以幫助實(shí)現(xiàn)HTTP請求操作,Request和Response都可以用類庫提供的數(shù)據(jù)結(jié)構(gòu)來表示,得到Response之后只需要解析數(shù)據(jù)結(jié)構(gòu)中的Body部分即可,即得到網(wǎng)頁的源代碼,這樣便可以用程序來實(shí)現(xiàn)獲取網(wǎng)頁的過程了。爬蟲的基本原理(2)提取信息獲取網(wǎng)頁源代碼后,接下來的工作就是分析網(wǎng)頁源代碼,從中提取想要的數(shù)據(jù),最通用的方法就是使用正則表達(dá)式,但是使用正則表達(dá)式比較復(fù)雜。在Python中,使用BeautifulSoup、PyQuery、LXML等庫,可以幫助高效的從源代碼中提取網(wǎng)頁信息。(3)保存數(shù)據(jù)提取信息之后,可以將數(shù)據(jù)保存到本地,以便后續(xù)使用,保存方式有很多種,比如TXT,Json也可以保存到數(shù)據(jù)庫中,如Mysql,MangoDB等。(1)Urllib庫的使用Urllib庫是Python中的一個(gè)功能強(qiáng)大、用于操作URL,并在做爬蟲的時(shí)候經(jīng)常要用到的庫。同樣的庫還有requests、HTTPlib2。在Python2.X中,分urllib和urllib2,但在Python3.X中,都統(tǒng)一合并到urllib中。相對來說,Python3.X對中文的支持比Python2.X友好,所以該博客接下來通過Python3.X來介紹urllib庫的一些常見用法?;編斓氖褂芒?/p>

發(fā)送請求

importurllib.requestr=urllib.request.urlopen(<arel="externalnofollow"href="">HTTP:///</a>)首先導(dǎo)入urllib.request模塊,使用urlopen()對參數(shù)中的URL發(fā)送請求,返回一個(gè)HTTP.client.HTTPResponse對象。在urlopen()中,使用timeout字段,可設(shè)定相應(yīng)的秒數(shù)時(shí)間之后停止等待響應(yīng)。除此之外,還可使用()、r.getcode()、r.geturl()獲取相應(yīng)的當(dāng)前環(huán)境信息、狀態(tài)碼、當(dāng)前網(wǎng)頁URL。②讀取響應(yīng)內(nèi)容importurllib.requesturl=""withurllib.request.urlopen(url)asr:r.read()使用r.read()讀取響應(yīng)內(nèi)容到內(nèi)存,該內(nèi)容為網(wǎng)頁的源代碼(可用相應(yīng)的瀏覽器“查看網(wǎng)頁源代碼”功能看到),并可對返回的字符串進(jìn)行相應(yīng)解碼decode()。③傳遞URL參數(shù)

importurllib.requestimporturllib.parseparams=urllib.parse.urlencode({'q':'urllib','check_keywords':'yes','area':'default'})url="{}".format(params)r=urllib.request.urlopen(url)以字符串字典的形式,通過urlencode()編碼,為URL的查詢字符串傳遞數(shù)據(jù),編碼后的params為字符串,字典每項(xiàng)鍵值對以'&'連接:'q=urllib&check_keywords=yes&area=default',構(gòu)建后的URL:HTTPS:///3/search.html?q=urllib&check_keywords=yes&area=default當(dāng)然,urlopen()支持直接構(gòu)建的URL,簡單的get請求可以不通過urlencode()編碼,手動(dòng)構(gòu)建后直接請求。④傳遞中文參數(shù)

importurllib.requestsearchword=urllib.request.quote(input("請輸入要查詢的關(guān)鍵字:"))url="{}&first=0&mmasync=1".format(searchword)r=urllib.request.urlopen(url)該URL是利用bing圖片接口,查詢關(guān)鍵字q的圖片。如果直接將中文傳入U(xiǎn)RL中請求,會導(dǎo)致編碼錯(cuò)誤。需要使用quote(),對該中文關(guān)鍵字進(jìn)行URL編碼,相應(yīng)的可以使用unquote()進(jìn)行解碼。⑤定制請求頭importurllib.requesturl=''headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/61.0.3163.100Safari/537.36','Referer':''}req=urllib.request.Request(url,headers=headers)r=urllib.request.urlopen(req)有時(shí)爬取一些網(wǎng)頁時(shí),會出現(xiàn)403錯(cuò)誤(Forbidden),即禁止訪問。這是因?yàn)榫W(wǎng)站服務(wù)器對訪問者的Headers屬性進(jìn)行身份驗(yàn)證,例如:通過urllib庫發(fā)送的請求,默認(rèn)以“Python-urllib/X.Y”作為User-Agent,其中X為Python的主版本號,Y為副版本號。所以,需要通過urllib.request.Request()構(gòu)建Request對象,傳入字典形式的Headers屬性,模擬瀏覽器。相應(yīng)的Headers信息,可通過瀏覽器的開發(fā)者調(diào)試工具,“檢查”功能的“Network”標(biāo)簽查看相應(yīng)的網(wǎng)頁得到,或使用抓包分析軟件Fiddler、Wireshark。除上述方法外,還可以使用urllib.request.build_opener()或req.add_header()定制請求頭。在Python2.X中,urllib模塊和urllib2模塊通常一起使用,因?yàn)閡rllib.urlencode()可以對URL參數(shù)進(jìn)行編碼,而urllib2.Request()可以構(gòu)建Request對象,定制請求頭,然后統(tǒng)一使用urllib2.urlopen()發(fā)送請求。⑥傳遞POST請求importurllib.requestimporturllib.parseurl=''post={'username':'xxx','password':'xxxx'}postdata=urllib.parse.urlencode(post).encode('utf-8')req=urllib.request.Request(url,postdata)r=urllib.request.urlopen(req)

在進(jìn)行注冊、登錄等操作時(shí),會通過POST表單傳遞信息。這時(shí),需要分析頁面結(jié)構(gòu),構(gòu)建表單數(shù)據(jù)post,使用urlencode()進(jìn)行編碼處理,返回字符串,再指定‘utf-8’的編碼格式,這是因?yàn)镻OSTdata只能是bytes或著fileobject。最后通過Request()對象傳遞postdata,使用urlopen()發(fā)送請求。⑦下載遠(yuǎn)程數(shù)據(jù)到本地importurllib.requesturl=""urllib.request.urlretrieve(url,"python-logo.png")爬取圖片、視頻等遠(yuǎn)程數(shù)據(jù)時(shí),可使用urlretrieve()下載到本地。第一個(gè)參數(shù)為要下載的url,第二個(gè)參數(shù)為下載后的存放路徑。例如:下載python官網(wǎng)logo到當(dāng)前目錄下,返回元組(filename,headers)。⑧設(shè)置代理IPimporturllib.requesturl=""proxy_ip="32:8118"proxy=urllib.request.ProxyHandler({'HTTP':proxy_ip})opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)urllib.request.install_opener(opener)r=urllib.request.urlopen(url)有時(shí)頻繁的爬取一個(gè)網(wǎng)頁,會被網(wǎng)站服務(wù)器屏蔽IP。這時(shí),可通過上述方法設(shè)置代理IP。首先,通過網(wǎng)上代理IP的網(wǎng)站找一個(gè)可以用的IP,構(gòu)建ProxyHandler()對象,將'HTTP'和代理IP以字典形式作為參數(shù)傳入,設(shè)置代理服務(wù)器信息。再構(gòu)建opener對象,將proxy和HTTPHandler類傳入。通過installl_opener()將opener設(shè)置成全局,當(dāng)用urlopen()發(fā)送請求時(shí),會使用之前設(shè)置的信息來發(fā)送相應(yīng)的請求。⑨異常處理importurllib.requestimporturllib.errorurl=""try:r=urllib.request.urlopen(url)excepturllib.error.URLErrorase:ifhasattr(e,'code'):print(e.code)ifhasattr(e,'reason'):print(e.reason)可以使用URLError類,處理一些URL相關(guān)異常。導(dǎo)入urllib.error,捕獲URLError異常后,因?yàn)橹挥邪l(fā)生HTTPError異常(URLError子類)時(shí),才會有異常狀態(tài)碼e.code,所以需要判斷異常是否有屬性code。⑩Cookie的使用

importurllib.requestimportHTTP.cookiejarurl=""cjar=HTTP.cookiejar.CookieJar()opener=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar))urllib.request.install_opener(opener)r=urllib.request.urlopen(url)通過無狀態(tài)協(xié)議HTTP訪問網(wǎng)頁時(shí),Cookie維持會話間的狀態(tài)。例如:有些網(wǎng)站需要登錄操作,第一次可通過提交POST表單來登錄,當(dāng)爬取該網(wǎng)站下的其它站點(diǎn)時(shí),可以使用Cookie來保持登錄狀態(tài),而不用每次都通過提交表單來登錄。首先,構(gòu)建CookieJar()對象cjar,再使用HTTPCookieProcessor()處理器,處理cjar,并通過build_opener()構(gòu)建opener對象,設(shè)置成全局,通過urlopen()發(fā)送請求。BeautifulSoup提供一些簡單的、python式的函數(shù)用來處理導(dǎo)航、搜索、修改分析樹等功能。它是一個(gè)工具箱,通過解析文檔為用戶提供需要抓取的數(shù)據(jù)。BeautifulSoup自動(dòng)將輸入文檔轉(zhuǎn)換為Unicode編碼,輸出文檔轉(zhuǎn)換為utf-8編碼。一般在處理時(shí)不需要考慮編碼方式,除非文檔沒有指定一個(gè)編碼方式,這時(shí),BeautifulSoup就不能自動(dòng)識別編碼方式了。此時(shí)就需要說明一下原始編碼方式就可以。BeautifulSoup①創(chuàng)建BeautifulSoup對象首先必須要導(dǎo)入bs4庫frombs4importBeautifulSoup創(chuàng)建一個(gè)字符串html="""<html><head><title>hellohadoop</title></head><body><pclass="title"name="hadoop"><b>hellohadoop</b></p><pclass="story">therewerethreeElephant<ahref="HTTP:///test1"class="elephant"id="elephant1"><!--test1--></a>,<ahref="HTTP:///test2"class="elephant"id="elephant2">test2</a>and<ahref="HTTP:///test3"class="elephant"id="elephant3">test3</a>;andtheylivedinthezoo.</p><pclass="story">...</p>"""創(chuàng)建beautifulsoup對象

soup=BeautifulSoup(html)另外,還可以用本地HTML文件來創(chuàng)建對象1soup=BeautifulSoup(open('index.html'))

下面來打印一下soup對象的內(nèi)容,格式化輸出

printsoup.prettify()輸出結(jié)果如下:

<html><head><title>hellohadoop</title>

soup=BeautifulSoup(html)另外,還可以用本地HTML文件來創(chuàng)建對象②四大對象種類BeautifulSoup將復(fù)雜HTML文檔轉(zhuǎn)換成一個(gè)復(fù)雜的樹形結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都是Python對象,所有對象可以歸納為4種:Tag、NavigableString、BeautifulSoup、Comment。Tag就是HTML中的一個(gè)個(gè)標(biāo)簽,例如

<title>hellohadoop</title>

<aclass="elephant"href="HTTP:///test1"id="elephant1">test1</a>這里的title和a標(biāo)簽加上里面包括的內(nèi)容就是Tag,下面嘗試用BeautifulSoup來方便地獲取Tags。下面每一段代碼的注釋部分即為運(yùn)行結(jié)果。

printsoup.title#<title>hellohadoop</title>

printsoup.head#<head><title>hellohadoop</title></head>

printsoup.a#<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>

printsoup.p#<pclass="title"name="hadoop"><b>hellohadoop</b></p>可以利用soup加標(biāo)簽名輕松地獲取這些標(biāo)簽的內(nèi)容,這里需要注意,它查找的是在所有內(nèi)容中的第一個(gè)符合要求的標(biāo)簽(查詢所有標(biāo)簽的方法,稍后會進(jìn)行介紹)。下面來驗(yàn)證一下這些對象的類型

printtype(soup.a)#<class'bs4.element.Tag'>對于Tag,它有兩個(gè)重要的屬性,分別是name和attrs。

printprint#[document]#headsoup對象本身比較特殊,它的name即為[document],對于其它內(nèi)部標(biāo)簽,輸出的值便為標(biāo)簽本身的名稱。在這里,把p標(biāo)簽的所有屬性打印輸出了出來,得到的類型是一個(gè)字典。

printsoup.p.attrs#{'class':['title'],'name':'hadoop'}如果想要單獨(dú)獲取某個(gè)屬性,可以這樣來做,例如獲取它的class。

printsoup.p['class']#['title']還可以利用get方法,傳入屬性的名稱來獲取。

printsoup.p.get('class')#['title']此外,可以對這些屬性和內(nèi)容等等進(jìn)行修改,例如:

soup.p['class']="newClass"printsoup.p#<pclass="newClass"name="hadoop"><b>hellohadoop</b></p>uNavigableString不僅可以得到標(biāo)簽的內(nèi)容,而且還可以通過“.string”獲取標(biāo)簽內(nèi)部的文字。例如:

printsoup.p.string#hellohadoop這樣就輕松獲取到了標(biāo)簽里面的內(nèi)容,下面來檢查一下它的類型。

printtype(soup.p.string)#<class'bs4.element.NavigableString'>uBeautifulSoupBeautifulSoup對象表示的是一個(gè)文檔的全部內(nèi)容,大部分時(shí)候,可以把它當(dāng)作一個(gè)特殊的Tag對象,可以分別獲取它的類型,名稱和屬性。

printtype()#<type'unicode'>print#[document]printsoup.attrs#{}空字典uCommentComment對象是一個(gè)特殊類型的NavigableString對象,其實(shí)輸出的內(nèi)容仍然不包括注釋符號,但是如果不好好處理它,可能會對文本處理造成意想不到的麻煩。下面來查找一個(gè)帶注釋的標(biāo)簽。

printsoup.aprintsoup.a.stringprinttype(soup.a.string)運(yùn)行結(jié)果如下:

<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>test1<class'bs4.element.Comment'>a標(biāo)簽里的內(nèi)容實(shí)際上是注釋,但是如果利用.string來輸出它的內(nèi)容,將會發(fā)現(xiàn)它已經(jīng)把注釋符號去掉了,這樣做可能會帶來嚴(yán)重的問題。另外,打印輸出下它的類型,發(fā)現(xiàn)它是一個(gè)Comment類型,所以,在使用前最好做一下判斷,代碼如下:

iftype(soup.a.string)==bs4.element.Comment:printsoup.a.string上面的代碼中,首先判斷了它的類型,是否為Comment類型,然后再進(jìn)行其它操作,如打印輸出。③

遍歷文檔樹u直接子節(jié)點(diǎn)tag的.content屬性可以將tag的子節(jié)點(diǎn)以列表的方式輸出。printsoup.head.contents#[<title>hellohadoop</title>]輸出方式為列表,可以用列表索引來獲取它的某一個(gè)元素printsoup.head.contents[0]#<title>hellohadoop</title>.children它返回的不是一個(gè)list,而是一個(gè)list生成器對象,可以通過遍歷獲取所有子節(jié)點(diǎn)。forchildinsoup.body.children:printchildu所有子孫節(jié)點(diǎn).contents和.children屬性僅包含tag的直接子節(jié)點(diǎn),.descendants屬性可以對所有tag的子孫節(jié)點(diǎn)進(jìn)行遞歸循環(huán),其和children類似,需要遍歷獲取其中的內(nèi)容。

forchildinsoup.descendants:printchild運(yùn)行結(jié)果如下,可以發(fā)現(xiàn),所有的節(jié)點(diǎn)都被打印出來了,先是最外層的HTML標(biāo)簽,其次從head標(biāo)簽一個(gè)個(gè)剝離,以此類推。

#<html><head><title>hellohadoop</title></head>#<body>#<pclass="title"name="hadoop"><b>hellohadoop</b></p>#<pclass="story">therewerethreeElephants<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>,u節(jié)點(diǎn)內(nèi)容如果tag只有一個(gè)NavigableString類型子節(jié)點(diǎn),那么這個(gè)tag可以使用.string得到子節(jié)點(diǎn)。如果一個(gè)tag僅有一個(gè)子節(jié)點(diǎn),那么這個(gè)tag也可以使用.string方法,輸出結(jié)果與當(dāng)前唯一子節(jié)點(diǎn)的.string結(jié)果相同。簡單來講:如果一個(gè)標(biāo)簽里面沒有標(biāo)簽了,那么.string就會返回標(biāo)簽里面的內(nèi)容。如果標(biāo)簽里面只有唯一的一個(gè)標(biāo)簽了,那么.string也會返回最里面的內(nèi)容。例如

printsoup.head.string#hellohadoopprintsoup.title.string#hellohadoop如果tag包含了多個(gè)子節(jié)點(diǎn),tag就無法確定,.string方法應(yīng)該調(diào)用哪個(gè)子節(jié)點(diǎn)的內(nèi)容,.string的輸出結(jié)果是None。

printsoup.html.string#Noneu多個(gè)內(nèi)容.strings可以通過遍歷獲取多個(gè)內(nèi)容,例如:forstringinsoup.strings:

print(repr(string))

#u"hellohadoop"

#u'\n\n'

#u"hellohadoop"

#u'\n\n'

#u'therewerethreeElephants\n'

#u'test1'

#u',\n'

#u'test2'

#u'and\n'

#u'test3'

#u';\nandtheylivedinthezoo.'

#u'\n\n'

#u'...'

#u'\n'輸出的字符串中可能包含了很多空格或空行,使用.stripped_strings可以去除多余空白內(nèi)容。例如:orstringinsoup.stripped_strings:print(repr(string))#u"hellohadoop"#u"hellohadoop"

#u'therewerethreeElephants'#u'test1'#u','#u'test2'#u'and'#u'test3'#u';\nandtheylivedinthezoo.'#u'...'u父節(jié)點(diǎn)使用元素的.parent屬性,可以獲取父節(jié)點(diǎn),例如:

p=soup.pprint#body

content=soup.head.title.stringprint#titleu全部父節(jié)點(diǎn)通過元素的.parents屬性可以遞歸得到元素的所有父輩節(jié)點(diǎn),例如:

content=soup.head.title.stringforparentincontent.parents:print

#title#head#html#[document]u

兄弟節(jié)點(diǎn)兄弟節(jié)點(diǎn)可以理解為和本節(jié)點(diǎn)處在同一級的節(jié)點(diǎn),.next_sibling屬性獲取了該節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn),.previous_sibling則與之相反,如果節(jié)點(diǎn)不存在,則返回None。注意:實(shí)際文檔中的tag的.next_sibling和.previous_sibling屬性通常是字符串或空白,因?yàn)榭瞻谆蛘邠Q行也可以被視作一個(gè)節(jié)點(diǎn),所以得到的結(jié)果可能是空白或者換行。printsoup.p.next_sibling#

實(shí)際該處為空白printsoup.p.prev_sibling#None

沒有前一個(gè)兄弟節(jié)點(diǎn),返回Noneprintsoup.p.next_sibling.next_sibling#<pclass="story">therewerethreeElephants#<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>,#<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>and#<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>;#andtheylivedinthezoo.</p>#下一個(gè)節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)是我們可以看到的節(jié)點(diǎn)u全部兄弟節(jié)點(diǎn)通過.next_siblings和.previous_siblings屬性可以對當(dāng)前節(jié)點(diǎn)的兄弟節(jié)點(diǎn)迭代輸出forsiblinginsoup.a.next_siblings:print(repr(sibling))#u',\n'#<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>#u'and\n'#<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>#u';andtheylivedinthezoo.'#Noneu前后節(jié)點(diǎn)與.next_sibling和.previous_sibling不同,它并不是針對于兄弟節(jié)點(diǎn),而是針對所有節(jié)點(diǎn),不分層次,比如head節(jié)點(diǎn)為:

<head><title>hellohadoop</title></head>那么它的下一個(gè)節(jié)點(diǎn)便是title,它是不分層次關(guān)系的。

printsoup.head.next_element#<title>hellohadoop</title>u所有前后節(jié)點(diǎn)通過.next_elements和.previous_elements的迭代器就可以向前或向后訪問文檔的解析內(nèi)容,就好像文檔正在被解析一樣。

forelementinlast_a_tag.next_elements:print(repr(element))#u'test3'#u';\nandtheylivedinthezoo.'#u'\n\n'#<pclass="story">...</p>#u'...'#u'\n'#None④

搜索文檔樹find_all(name,attrs,recursive,text,limit,**kwargs)find_all()方法搜索當(dāng)前tag的所有tag子節(jié)點(diǎn),并判斷是否符合過濾器的條件1)name

參數(shù)name參數(shù)可以查找所有名字為name的tag,字符串對象會被自動(dòng)忽略掉。u傳字符串最簡單的過濾器是字符串。在搜索方法中傳入一個(gè)字符串參數(shù),BeautifulSoup會查找與字符串完整匹配的內(nèi)容,下面的例子用于查找文檔中所有的<b>標(biāo)簽。

soup.find_all('b')#[<b>hellohadoop</b>]

printsoup.find_all('a')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>,<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>,<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>]u傳正則表達(dá)式如果傳入正則表達(dá)式作為參數(shù),BeautifulSoup會通過正則表達(dá)式的match()來匹配內(nèi)容。下面例子中找出所有以b開頭的標(biāo)簽,這表示<body>和<b>標(biāo)簽都應(yīng)該被找到。

importrefortaginsoup.find_all(pile("^b")):print()#body#bu傳列表如果傳入列表參數(shù),BeautifulSoup會將與列表中任一元素匹配的內(nèi)容返回。下面代碼找到文檔中所有<a>標(biāo)簽和<b>標(biāo)簽。

soup.find_all(["a","b"])#[<b>hellohadoop</b>,#<aclass="elephant"href="HTTP:///test1"id="elephant1">test1</a>,#<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>,#<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>]u傳TrueTrue可以匹配任何值,下面代碼查找到所有的tag,但是不會返回字符串節(jié)點(diǎn)。

fortaginsoup.find_all(True):print()#html#head#title#body#p#b#p#a#au傳方法如果沒有合適過濾器,那么還可以定義一個(gè)方法,方法只接受一個(gè)元素參數(shù)(HTML文檔中的一個(gè)tag節(jié)點(diǎn),不能是文本節(jié)點(diǎn)),如果這個(gè)方法返回True表示當(dāng)前元素匹配并且被找到,如果不是則反回False。下面方法校驗(yàn)了當(dāng)前元素,如果包含class屬性卻不包含id屬性,那么將返回True:defhas_class_but_no_id(tag):returntag.has_attr('class')andnottag.has_attr('id')將這個(gè)方法作為參數(shù)傳入find_all()方法,將得到所有<p>標(biāo)簽:soup.find_all(has_class_but_no_id)#[<pclass="title"><b>hellohadoop</b></p>,#<pclass="story">therewere...</p>,#<pclass="story">...</p>]2)attrs參數(shù)有些tag屬性在搜索中不能使用,比如HTML5中的data-*屬性data_soup=BeautifulSoup('<divdata-foo="value">foo!</div>')data_soup.find_all(data-foo="value")#SyntaxError:keywordcan'tbeanexpression但是可以通過find_all()方法的attrs參數(shù)定義一個(gè)字典參數(shù)來搜索包含特殊屬性的tag。data_soup.find_all(attrs={"data-foo":"value"})#[<divdata-foo="value">foo!</div>]其定義一個(gè)字典參數(shù)來搜索包含特殊屬性的tag,表達(dá)式可以是字符串、布爾值、正則表達(dá)式。3)text參數(shù)通過text參數(shù)可以搜索文檔中的字符串內(nèi)容。與name參數(shù)的可選值一樣,text參數(shù)接受字符串、正則表達(dá)式、列表和True。soup.find_all(text="test1")#[u'test1']soup.find_all(text=["test3","test1","test2"])#[u'test1',u'test2',u'test3']soup.find_all(text=pile("hadoop"))#

[u"hellohadoop",u"hellohadoop"]4)limit參數(shù)find_all()方法返回全部的搜索結(jié)構(gòu),如果文檔樹很大那么搜索會很慢。如果不需要全部結(jié)果,可以使用limit參數(shù)限制返回結(jié)果的數(shù)量。當(dāng)搜索到的結(jié)果數(shù)量達(dá)到limit的限制時(shí),就停止搜索返回結(jié)果。文檔樹中有3個(gè)tag符合搜索條件,但結(jié)果只返回了2個(gè),因?yàn)閘imit=2限制了返回?cái)?shù)量。soup.find_all("a",limit=2)#[<aclass="elephant"href="HTTP:///test1"id="elephant1">test1</a>,#<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>]5)recursive參數(shù)調(diào)用tag的find_all()方法時(shí),BeautifulSoup會檢索當(dāng)前tag的所有子孫節(jié)點(diǎn),如果只想搜索tag的直接子節(jié)點(diǎn),可以使用參數(shù)recursive=False。一段簡單的文檔:<html><head><title>hellohadoop</title></head>...是否使用recursive參數(shù)的搜索結(jié)果對比如下:soup.html.find_all("title")#[<title>hellohadoop</title>]soup.html.find_all("title",recursive=False)#[]6)**kwargs參數(shù)注意:如果一個(gè)指定名字的參數(shù)不是搜索內(nèi)置的參數(shù)名,搜索時(shí)會把該參數(shù)當(dāng)作指定名字tag的屬性來搜索,如果包含一個(gè)名字為id的參數(shù),BeautifulSoup會搜索每個(gè)tag的“id”屬性。soup.find_all(id='elephant2')#[<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>]如果傳入href參數(shù),BeautifulSoup會搜索每個(gè)tag的“href”屬性。soup.find_all(href=pile("test1"))#[<aclass="elephant"href="HTTP:///test1"id="elephant1">test1</a>]使用多個(gè)指定名字的參數(shù)可以同時(shí)過濾tag的多個(gè)屬性。soup.find_all(href=pile("test1"),id='elephant1')#[<aclass="elephant"href="HTTP:///test1"id="elephant1">three</a>]如果想用class過濾,因?yàn)閏lass是python的關(guān)鍵詞,因此需要加個(gè)下劃線來解決沖突問題。soup.find_all("a",class_="elephant")#[<aclass="elephant"href="HTTP:///test1"id="elephant1">test1</a>,#<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>,#<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>]ufind_parents()find_parent()find_all()和find()只搜索當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn),孫子節(jié)點(diǎn)等。find_parents()和find_parent()用來搜索當(dāng)前節(jié)點(diǎn)的父輩節(jié)點(diǎn),搜索方法與普通tag的搜索方法相同,搜索文檔搜索文檔包含的內(nèi)容。ufind_next_siblings()find_next_sibling()這2個(gè)方法通過.next_siblings屬性對當(dāng)tag的所有后面解析的兄弟tag節(jié)點(diǎn)進(jìn)行迭代,find_next_siblings()方法返回所有符合條件的后面的兄弟節(jié)點(diǎn),find_next_sibling()只返回符合條件的后面的第一個(gè)tag節(jié)點(diǎn)。ufind_previous_siblings()find_previous_sibling()這2個(gè)方法通過.previous_siblings屬性對當(dāng)前tag的前面解析的兄弟tag節(jié)點(diǎn)進(jìn)行迭代,find_previous_siblings()方法返回所有符合條件的前面的兄弟節(jié)點(diǎn),find_previous_sibling()方法返回第一個(gè)符合條件的前面的兄弟節(jié)點(diǎn)。ufind_all_next()find_next()這2個(gè)方法通過.next_elements屬性對當(dāng)前tag的之后的tag和字符串進(jìn)行迭代,find_all_next()方法返回所有符合條件的節(jié)點(diǎn),find_next()方法返回第一個(gè)符合條件的節(jié)點(diǎn)。ufind_all_previous()和find_previous()這2個(gè)方法通過.previous_elements屬性對當(dāng)前節(jié)點(diǎn)前面的tag和字符串進(jìn)行迭代,find_all_previous()方法返回所有符合條件的節(jié)點(diǎn),find_previous()方法返回第一個(gè)符合條件的節(jié)點(diǎn)。⑤CSS選擇器寫CSS時(shí),標(biāo)簽名不加任何修飾,類名前加點(diǎn),id名前加#,在這里也可以利用類似的方法來篩選元素,用到的方法是soup.select(),返回類型是list。通過標(biāo)簽名查找

printsoup.select('title')#[<title>hellohadoop</title>]

printsoup.select('a')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>,<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>,<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>]

printsoup.select('b')#[<b>hellohadoop</b>]通過類名查找

printsoup.select('.elephant')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>,<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>,<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>]通過id名查找

printsoup.select('#elephant1')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>]組合查找組合查找即和寫class文件時(shí),標(biāo)簽名與類名、id名進(jìn)行的組合原理是一樣的,例如查找p標(biāo)簽中,id等于elephant1的內(nèi)容,二者需要用空格分開。

printsoup.select('p#elephant1')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>]直接子標(biāo)簽查找

printsoup.select("head>title")#[<title>hellohadoop</title>]u屬性查找查找時(shí)還可以加入屬性元素,屬性需要用中括號括起來,注意屬性和標(biāo)簽屬于同一節(jié)點(diǎn),所以中間不能加空格,否則會無法匹配到。

printsoup.select('a[class="elephant"]')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>,<aclass="elephant"href="HTTP:///test2"id="elephant2">test2</a>,<aclass="elephant"href="HTTP:///test3"id="elephant3">test3</a>]

printsoup.select('a[href="HTTP:///test1"]')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>]同樣,屬性仍然可以與上述查找方式組合,不在同一節(jié)點(diǎn)的空格隔開,同一節(jié)點(diǎn)的不加空格

printsoup.select('pa[href="HTTP:///test1"]')#[<aclass="elephant"href="HTTP:///test1"id="elephant1"><!--test1--></a>]以上的select方法返回的結(jié)果都是列表形式,可以遍歷形式輸出,然后用get_text()方法來獲取它的內(nèi)容。

soup=BeautifulSoup(html,'lxml')printtype(soup.select('title'))printsoup.select('title')[0].get_text()fortitleinsoup.select('title'):printtitle.get_text()

任務(wù)實(shí)施1)確定并分析目標(biāo)網(wǎng)頁架構(gòu)。①進(jìn)入HTTP://網(wǎng)頁如圖所示:②單擊以數(shù)字開頭行的“數(shù)字”,觀察url的變化,發(fā)現(xiàn)網(wǎng)頁url變化規(guī)律為HTTP:///list+數(shù)字。③單擊數(shù)字1進(jìn)入HTTP:///list1頁面,在右鍵彈出菜單中,單擊“檢查”菜單,頁面顯示如圖所示:由圖可以看出,這個(gè)頁面并沒有包含詳細(xì)的北京公交信息。需要進(jìn)一步找尋詳細(xì)信息所在頁面。④使用快捷鍵“Ctrl+Shift+C”,單擊“以漢字/字母開頭”行下面的1路超鏈接區(qū)域如圖所示:⑤單擊a標(biāo)簽里的href屬性,就會跳入詳細(xì)信息頁面如圖所示:此時(shí)仔細(xì)觀察url的變化,將會發(fā)現(xiàn)詳細(xì)信息頁面的url變化規(guī)律為:HTTP:///+(a標(biāo)簽里的href屬性)。因此在構(gòu)建URL時(shí),需要獲取對應(yīng)a標(biāo)簽的href屬性的內(nèi)容?,F(xiàn)在就可以開始構(gòu)建爬蟲程序了。

在pycharm中新建一個(gè)PythonFile,命名為beijinbus,導(dǎo)入需要的urllib請求庫如圖所示:(2)第二部分①

構(gòu)造一個(gè)url,以便獲取所有一級頁面的url,可以使用print輸出驗(yàn)證構(gòu)造結(jié)果如圖所示:②

創(chuàng)建一個(gè)get_page_url方法,并在for循環(huán)中調(diào)用如圖所示:圖中使用了urlib的reques

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論