《Python網(wǎng)絡(luò)爬蟲技術(shù)案例教程》(林忠會(huì)) 第3章.Python網(wǎng)絡(luò)爬蟲_第1頁(yè)
《Python網(wǎng)絡(luò)爬蟲技術(shù)案例教程》(林忠會(huì)) 第3章.Python網(wǎng)絡(luò)爬蟲_第2頁(yè)
《Python網(wǎng)絡(luò)爬蟲技術(shù)案例教程》(林忠會(huì)) 第3章.Python網(wǎng)絡(luò)爬蟲_第3頁(yè)
《Python網(wǎng)絡(luò)爬蟲技術(shù)案例教程》(林忠會(huì)) 第3章.Python網(wǎng)絡(luò)爬蟲_第4頁(yè)
《Python網(wǎng)絡(luò)爬蟲技術(shù)案例教程》(林忠會(huì)) 第3章.Python網(wǎng)絡(luò)爬蟲_第5頁(yè)
已閱讀5頁(yè),還剩135頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲Python網(wǎng)絡(luò)爬蟲技術(shù)案例教程PythonWangluoPachongJishuAnliJiaochengCOMMITTEDCOMMITTEDCOMMITTECOMMITTECONTENTS目錄COMMITTED第1章網(wǎng)絡(luò)爬蟲入門

第2章爬蟲基礎(chǔ)第3章網(wǎng)頁(yè)解析基礎(chǔ)第4章爬取動(dòng)態(tài)加載數(shù)據(jù)第5章反爬蟲策略第6章模擬登錄和處理驗(yàn)證碼

第7章爬取App和PC客戶端第8章爬蟲框架Scrapy第9章分布式爬蟲第10章項(xiàng)目實(shí)戰(zhàn)COMMITTEDCOMMITTEDCOMMITTECOMMITTECOMMITTED掃碼下載文旌課堂APP掃碼簽到(202X.XX.XXXX:XX至202X.XX.XXXX:XX)簽到方式教師通過“文旌課堂APP”生成簽到二維碼,并設(shè)置簽到時(shí)間,學(xué)生通過“文旌課堂APP”掃描“簽到二維碼”進(jìn)行簽到。簽到.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲第3章

網(wǎng)頁(yè)解析基礎(chǔ)本章導(dǎo)讀爬取網(wǎng)頁(yè)后,接下來就是解析網(wǎng)頁(yè)。解析網(wǎng)頁(yè)是用戶根據(jù)網(wǎng)頁(yè)結(jié)構(gòu)的一定規(guī)則,分析網(wǎng)頁(yè)源代碼,從中提取想要的數(shù)據(jù)。它可以使雜亂的數(shù)據(jù)變得條理清晰,以便用戶后續(xù)處理和分析。本章從網(wǎng)頁(yè)基礎(chǔ)入手,介紹網(wǎng)絡(luò)爬蟲解析網(wǎng)頁(yè)的基礎(chǔ)知識(shí),包括lxml庫(kù)、beautifulsoup4庫(kù)、正則表達(dá)式和存儲(chǔ)數(shù)據(jù)至JSON或CSV文件等內(nèi)容。學(xué)習(xí)目標(biāo)理解網(wǎng)頁(yè)基礎(chǔ)知識(shí)。掌握lxml庫(kù)的使用方法。掌握beautifulsoup4庫(kù)的使用方法。了解正則表達(dá)式的使用方法。掌握存儲(chǔ)數(shù)據(jù)至JSON或CSV文件的方法。能使用lxml庫(kù)和beautifulsoup4庫(kù)解析網(wǎng)頁(yè)并存儲(chǔ)提取的數(shù)據(jù)。3.1網(wǎng)頁(yè)基礎(chǔ)3.2lxml庫(kù)3.3beautifulsoup4庫(kù)第2章爬蟲基礎(chǔ)3.4正則表達(dá)式3.5存儲(chǔ)數(shù)據(jù)至文件.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲SectionTitle3.1網(wǎng)頁(yè)基礎(chǔ)3.1網(wǎng)頁(yè)基礎(chǔ)1.請(qǐng)求的網(wǎng)址網(wǎng)頁(yè)一般由HTML、CSS和JavaScript三部分組成,其中HTML用于定義網(wǎng)頁(yè)的結(jié)構(gòu)和內(nèi)容;CSS用于定義網(wǎng)頁(yè)的樣式;JavaScript用于定義網(wǎng)頁(yè)的行為。超文本標(biāo)記語言(HyperTextMarkedLanguage,HTML)是一種用來描述網(wǎng)頁(yè)的語言。它通過不同類型的標(biāo)簽來描述不同的元素,各種標(biāo)簽通過不同的排列和嵌套形成網(wǎng)頁(yè)的框架。有的標(biāo)簽還帶有屬性參數(shù),其語法格式如下:常用的標(biāo)簽如表3-1所示。<標(biāo)簽屬性="參數(shù)值">表3-1常用的標(biāo)簽標(biāo)簽說明<!DOCTYPE>定義文檔類型<html>定義HTML文檔,標(biāo)記符是<html></html><head>定義文檔的頭部,標(biāo)記符是<head></head><meta>定義關(guān)于HTML文檔的元信息,標(biāo)記符是<meta屬性="參數(shù)值"><title>定義文檔的標(biāo)題,標(biāo)記符是<title>文檔標(biāo)題</title><body>定義文檔的主體,標(biāo)記符是<body></body><div>定義文檔中的節(jié),標(biāo)記符是<div></div><ul>定義無序列表,標(biāo)記符是<ul></ul>3.1網(wǎng)頁(yè)基礎(chǔ)表3-1常用的標(biāo)簽(續(xù))標(biāo)簽說明<li>定義列表項(xiàng)目,標(biāo)記符是<li></li><h1>~<h6>定義HTML標(biāo)題,<h1>定義最大的標(biāo)題,<h6>定義最小的標(biāo)題,標(biāo)記符是<h1>我的標(biāo)題</h1><p>定義段落,標(biāo)記符是<p></p><a>定義超鏈接目標(biāo),標(biāo)記符是<ahref="地址">鏈接名稱</a><link>定義文檔與外部資源的關(guān)系,標(biāo)記符是<link屬性="參數(shù)值"><script>定義客戶端腳本,標(biāo)記符是<script></script>例如,百度首頁(yè)的HTML源代碼如圖3-1所示。3.1網(wǎng)頁(yè)基礎(chǔ)圖3-1百度首頁(yè)的HTML源代碼3.1網(wǎng)頁(yè)基礎(chǔ)圖3-1百度首頁(yè)的HTML源代碼(續(xù))3.1網(wǎng)頁(yè)基礎(chǔ)打開瀏覽器的開發(fā)者工具窗口,選擇“Elements”選項(xiàng),即可查看HTML源代碼。3.1網(wǎng)頁(yè)基礎(chǔ)2.HTMLDOM文檔對(duì)象模型(DocumentObjectModel,DOM)定義了訪問HTML和可擴(kuò)展標(biāo)記語言(ExtensibleMarkupLanguage,XML)文檔的標(biāo)準(zhǔn)。HTMLDOM將HTML文檔呈現(xiàn)為帶有元素、屬性和文本的樹結(jié)構(gòu)(也稱為節(jié)點(diǎn)樹),如圖3-2所示。圖3-2節(jié)點(diǎn)樹3.1網(wǎng)頁(yè)基礎(chǔ)在節(jié)點(diǎn)樹中,頂端節(jié)點(diǎn)稱為根(root),除了根節(jié)點(diǎn)外,其他每個(gè)節(jié)點(diǎn)都有父節(jié)點(diǎn)(parent),同時(shí)可擁有任意數(shù)量的子節(jié)點(diǎn)(child)和兄弟節(jié)點(diǎn)(sibling)。例如,根元素<html>、元素<head>和元素<body>相互之間的關(guān)系可用圖3-3表示。圖3-3根元素<html>、元素<head>和元素<body>相互之間的關(guān)系3.1網(wǎng)頁(yè)基礎(chǔ)3.CSS選擇器層疊樣式表(CascadingStyleSheets,CSS)選擇器可以定位節(jié)點(diǎn),常用的語法規(guī)則如表3-2所示。選擇器示例示例說明.class.intro選擇class="intro"的所有節(jié)點(diǎn)#id#firstname選擇id="firstname"的所有節(jié)點(diǎn)**選擇所有節(jié)點(diǎn)elementp選擇所有<p>節(jié)點(diǎn)element,elementdiv,p選擇所有<div>節(jié)點(diǎn)和所有<p>節(jié)點(diǎn)elementelementdivp選擇<div>節(jié)點(diǎn)內(nèi)部的所有<p>節(jié)點(diǎn)element>elementdiv>p選擇父節(jié)點(diǎn)為<div>節(jié)點(diǎn)的所有<p>節(jié)點(diǎn)表3-2CSS選擇器常用的語法規(guī)則3.1網(wǎng)頁(yè)基礎(chǔ)[attribute][target]選擇帶有target屬性的所有節(jié)點(diǎn)[attribute=value][target=blank]選擇target="blank"的所有節(jié)點(diǎn):linka:link選擇所有未訪問的鏈接:visiteda:visited選擇所有已訪問的鏈接:activea:active選擇活動(dòng)鏈接:first-linep:first-line選擇每個(gè)<p>節(jié)點(diǎn)的首行element1~element2p~ul選擇前面有<p>節(jié)點(diǎn)的所有<ul>節(jié)點(diǎn)[attribute^=value]a[src^="https"]選擇其src屬性值以“https”開頭的所有<a>節(jié)點(diǎn)[attribute$=value]a[src$=".pdf"]選擇其src屬性值以“.pdf”結(jié)尾的所有<a>節(jié)點(diǎn)[attribute*=value]a[src*="abc"]選擇其src屬性值中包含“abc”子串的所有<a>節(jié)點(diǎn):enabledinput:enabled選擇每個(gè)啟用的<input>節(jié)點(diǎn):disabledinput:disabled選擇每個(gè)禁用的<input>節(jié)點(diǎn):checkedinput:checked選擇每個(gè)被選中的<input>節(jié)點(diǎn)表3-2CSS選擇器常用的語法規(guī)則(續(xù))3.1網(wǎng)頁(yè)基礎(chǔ).Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲SectionTitle3.2lxml庫(kù)3.2lxml庫(kù)3.2.1案例引入——爬取小說《三國(guó)演義》章節(jié)信息【例3-1】

爬取小說《三國(guó)演義》章節(jié)列表網(wǎng)頁(yè)的內(nèi)容(網(wǎng)址/50_50096/),使用lxml庫(kù)解析網(wǎng)頁(yè)后,輸出爬取到的小說章節(jié)列表鏈接。【問題分析】在GoogleChrome瀏覽器中訪問/50_50096/,打開瀏覽器的開發(fā)者工具窗口,選擇“Elements”選項(xiàng)后單擊左上角“”按鈕,然后使用鼠標(biāo)選擇網(wǎng)頁(yè)中的某處,即可直接定位到HTML中對(duì)應(yīng)的節(jié)點(diǎn),如圖3-4所示??梢钥闯?,所有小說章節(jié)標(biāo)題都在dd節(jié)點(diǎn)下,且其鏈接的值包含在a節(jié)點(diǎn)的href屬性中。圖3-4《三國(guó)演義》章節(jié)列表網(wǎng)頁(yè)HTML的源代碼3.2lxml庫(kù)【參考代碼】

importrequests #導(dǎo)入requests模塊importurllib.parse

#導(dǎo)入parse模塊fromlxmlimportetree #導(dǎo)入etree模塊#定義字符串novel_base_urlnovel_base_url=''#將合并的url賦值給novel_urlnovel_url=urllib.parse.urljoin(novel_base_url,'/50_50096/')r=requests.get(novel_url)

#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rhtml=etree.HTML(r.text) #創(chuàng)建HTML對(duì)象html3.2lxml庫(kù)#選擇節(jié)點(diǎn)并提取href屬性值hrefs=html.xpath('//div/dl/dd/a/@href')forhrefinhrefs: #遍歷#將novel_base_url和提取的屬性值合并成章節(jié)鏈接chapter_url=urllib.parse.urljoin(novel_base_url,href)print(chapter_url) #輸出每個(gè)章節(jié)鏈接3.2lxml庫(kù)【運(yùn)行結(jié)果】程序的運(yùn)行結(jié)果如圖3-5所示。圖3-5例3-1程序的運(yùn)行結(jié)果3.2lxml庫(kù)3.2.2lxml庫(kù)簡(jiǎn)介lxml庫(kù)是Python的一個(gè)網(wǎng)頁(yè)解析庫(kù),支持HTML和XML的解析,支持XPath解析方式,解析效率非常高。lxml庫(kù)不是Python內(nèi)置的標(biāo)準(zhǔn)庫(kù),使用之前需要安裝,其安裝方法與requests庫(kù)的安裝類似(請(qǐng)參考2.3.2節(jié)),此處不再贅述。3.2lxml庫(kù)XML路徑語言(XMLpathlanguage,XPath)用于在XML文檔中查找信息,同樣適用于HTML文檔。3.2lxml庫(kù)lxml庫(kù)的大部分功能是由etree模塊提供的。使用XPath解析網(wǎng)頁(yè)時(shí),首先需要調(diào)用etree模塊下的HTML類對(duì)HTTP響應(yīng)的網(wǎng)頁(yè)進(jìn)行初始化(etree.HTML()),從而構(gòu)造一個(gè)Element類型的XPath解析對(duì)象;然后使用XPath對(duì)Element對(duì)象進(jìn)行節(jié)點(diǎn)選擇,最后返回一個(gè)列表。若HTML中的節(jié)點(diǎn)沒有閉合,etree模塊還可提供自動(dòng)補(bǔ)全功能。3.2lxml庫(kù)3.2.3XPath語法XPath的選擇功能十分強(qiáng)大,它提供了非常簡(jiǎn)明的路徑選擇表達(dá)式。另外,它還提供了超過100個(gè)內(nèi)建函數(shù),用于字符串、數(shù)值、時(shí)間的匹配及節(jié)點(diǎn)、序列的處理等。可以說,幾乎所有想要定位的節(jié)點(diǎn),都可以用XPath來選擇。XPath語法3.2lxml庫(kù)HTML源代碼是層次結(jié)構(gòu)的,如果想要選擇一個(gè)節(jié)點(diǎn),可以一層一層往下查找。XPath實(shí)際上就是使用這種層次結(jié)構(gòu)的路徑來找到相應(yīng)的節(jié)點(diǎn),它類似于人們?nèi)粘J褂玫牡刂?,它們都是從大的范圍一直縮小到具體的某個(gè)地址。XPath通過路徑選擇節(jié)點(diǎn)常用的語法如表3-3所示。1.通過路徑選擇節(jié)點(diǎn)3.2lxml庫(kù)語法示例示例說明/body/div選取body節(jié)點(diǎn)下的所有div子節(jié)點(diǎn)//body//div選取body節(jié)點(diǎn)下的所有div子孫節(jié)點(diǎn)*body/*選取body節(jié)點(diǎn)下的所有子節(jié)點(diǎn).body/.選取當(dāng)前body節(jié)點(diǎn)..body/..選取當(dāng)前body節(jié)點(diǎn)的父節(jié)點(diǎn)[]body/div[1]選取body節(jié)點(diǎn)下的第一個(gè)div子節(jié)點(diǎn),下標(biāo)從1開始表3-3XPath通過路徑選擇節(jié)點(diǎn)常用的語法3.2lxml庫(kù)【例3-2】

爬取小說《三國(guó)演義》章節(jié)列表網(wǎng)頁(yè)的內(nèi)容(網(wǎng)址/50_50096/),通過路徑選擇節(jié)點(diǎn)后輸出?!緟⒖即a】

importrequests #導(dǎo)入requests模塊fromlxmlimportetree #導(dǎo)入etree模塊url='/50_50096/' #定義url字符串r=requests.get(url) #發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rhtml=etree.HTML(r.text) #創(chuàng)建HTML對(duì)象htmlprint('HTML對(duì)象類型:',type(html)) #輸出html的類型3.2lxml庫(kù)#輸出body節(jié)點(diǎn)下的所有div子節(jié)點(diǎn)print('body節(jié)點(diǎn)下的所有div子節(jié)點(diǎn):',html.xpath('/html/body/div'))#輸出body節(jié)點(diǎn)下的所有div子孫節(jié)點(diǎn)print('body節(jié)點(diǎn)下的所有div子孫節(jié)點(diǎn):',html.xpath('body//div'))#輸出body節(jié)點(diǎn)下的所有子節(jié)點(diǎn)print('body節(jié)點(diǎn)下的所有子節(jié)點(diǎn):',html.xpath('body/*'))#輸出當(dāng)前body節(jié)點(diǎn)print('當(dāng)前body節(jié)點(diǎn):',html.xpath('body/.'))#輸出當(dāng)前body節(jié)點(diǎn)的父節(jié)點(diǎn)print('當(dāng)前body節(jié)點(diǎn)的父節(jié)點(diǎn):',html.xpath('body/..'))3.2lxml庫(kù)【運(yùn)行結(jié)果】程序的運(yùn)行結(jié)果如圖3-6所示。圖3-6例3-2程序的運(yùn)行結(jié)果3.2lxml庫(kù)XPath可以通過節(jié)點(diǎn)的屬性來選擇包含某個(gè)指定屬性值的節(jié)點(diǎn)。它可在僅掌握節(jié)點(diǎn)部分特征的情況下,利用模糊搜索函數(shù)選擇節(jié)點(diǎn)。XPath通過屬性選擇節(jié)點(diǎn)常用的語法如表3-4所示。2.通過屬性選擇節(jié)點(diǎn)語法示例示例說明@//div[@class="content"]選取class屬性值為“content”的div節(jié)點(diǎn)starts-with()//div[starts-with(@class,"con")]選取class屬性值以“con”開頭的div節(jié)點(diǎn)contains()//div[contains(@class,"tent")]選取class屬性值包含“tent”的div節(jié)點(diǎn)and//div[@id="content"and@class="showtxt"]選取id屬性值為“content”和class屬性值為“showtxt”的div節(jié)點(diǎn)表3-4XPath通過屬性選擇節(jié)點(diǎn)常用的語法3.2lxml庫(kù)@也可以用于提取節(jié)點(diǎn)的屬性值。例如,//div[@id="content"]/@class表示提取id屬性值為“content”的div節(jié)點(diǎn)的class屬性值。3.2lxml庫(kù)【例3-3】

爬取小說《三國(guó)演義》第一章節(jié)網(wǎng)頁(yè)內(nèi)容(網(wǎng)址/50_50096/18520412.html),通過屬性選擇節(jié)點(diǎn)后輸出?!緟⒖即a】

importrequests #導(dǎo)入requests模塊fromlxmlimportetree #導(dǎo)入etree模塊#定義url字符串url='/50_50096/18520412.html'r=requests.get(url) #發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rhtml=etree.HTML(r.text) #創(chuàng)建HTML對(duì)象html#輸出class屬性值為“content”的div節(jié)點(diǎn)3.2lxml庫(kù)print('class屬性值為“content”的div節(jié)點(diǎn):',html.xpath('//div[@class="content"]'))#輸出id屬性值以“con”開頭的div節(jié)點(diǎn)print('id屬性值以“con”開頭的div節(jié)點(diǎn):',html.xpath('//div[starts-with(@id,"con")]'))#輸出id屬性值包含“tent”的div節(jié)點(diǎn)print('id屬性值包含“tent”的div節(jié)點(diǎn):',html.xpath('//div[contains(@id,"tent")]'))3.2lxml庫(kù)#輸出id屬性值為“content”和class屬性值為“showtxt”的div節(jié)點(diǎn)print('id屬性值為“content”和class屬性值為“showtxt”的div節(jié)點(diǎn):',html.xpath('//div[@id="content"and@class="showtxt"]'))#輸出id屬性值為“content”的div節(jié)點(diǎn)的class屬性值print('id屬性值為“content”的div節(jié)點(diǎn)的class屬性值:',html.xpath('//div[@id="content"]/@class'))3.2lxml庫(kù)【運(yùn)行結(jié)果】程序的運(yùn)行結(jié)果如圖3-7所示。圖3-7例3-3程序的運(yùn)行結(jié)果3.2lxml庫(kù)解析網(wǎng)頁(yè)的目的是通過選擇節(jié)點(diǎn)來提取節(jié)點(diǎn)文本或?qū)傩灾?,從而獲取所需的信息。XPath提取文本的方法如表3-5所示。3.提取文本方法示例示例說明text()//a/text()提取所有a節(jié)點(diǎn)的文本,返回一個(gè)列表()string(//a)提取a節(jié)點(diǎn)下所有節(jié)點(diǎn)的文本,返回一個(gè)字符串表3-5XPath提取文本的方法3.2lxml庫(kù)text()方法也可用于選取節(jié)點(diǎn)文本包含指定值的節(jié)點(diǎn),如//a[contains(text(),'Python']表示選取文本包含“Python”的a節(jié)點(diǎn)。3.2lxml庫(kù)3.2.4典型案例【例3-4】

爬取小說《三國(guó)演義》第一章節(jié)網(wǎng)頁(yè)內(nèi)容(網(wǎng)址/50_50096/18520412.html),輸出爬取到的第一章節(jié)的標(biāo)題和正文。【問題分析】

在GoogleChrome瀏覽器中訪問/50_50096/18520412.html,查看并分析HTML的源代碼,可以看出標(biāo)題包含在h1節(jié)點(diǎn)中,正文包含在id屬性值為“content”的div節(jié)點(diǎn)中,如圖3-8所示。3.2lxml庫(kù)圖3-8《三國(guó)演義》第一章節(jié)網(wǎng)頁(yè)的HTML源代碼3.2lxml庫(kù)【參考代碼】

importrequests #導(dǎo)入requests模塊importchardet #導(dǎo)入chardet模塊fromlxmlimportetree #導(dǎo)入etree模塊#定義字符串chapter_urlchapter_url='/50_50096/18520412.html'r=requests.get(chapter_url) #發(fā)送請(qǐng)求,并將返回結(jié)果賦值給r#獲取返回內(nèi)容編碼類型code_type=r.apparent_encoding#判編碼類型是否是GB2312,如果是,改變編碼類型為GBKifcode_type=='GB2312':code_type='GBK'3.2lxml庫(kù)r.encoding=code_type #重定義返回內(nèi)容編碼類型html=etree.HTML(r.text) #創(chuàng)建HTML對(duì)象html#選擇h1節(jié)點(diǎn)并提取文本,將返回的列表第一項(xiàng)賦值給titletitle=html.xpath('//h1/text()')[0]print(title) #輸出第一章節(jié)的標(biāo)題#選擇id屬性值為“content”的div節(jié)點(diǎn)并提取文本contents=html.xpath('//div[@id="content"]/text()')foriincontents: #遍歷列表#移除字符串頭尾的空格,并賦值給contentcontent=i.strip()print(content) #輸出第一章節(jié)的正文3.2lxml庫(kù)GB2312編碼支持的漢字比較少,使用這種編碼類型時(shí),中文內(nèi)容會(huì)出現(xiàn)小部分亂碼,而GBK編碼向下兼容GB2312編碼,因此如果檢測(cè)到的編碼類型是GB2312,可直接將編碼類型改為GBK。3.2lxml庫(kù)【運(yùn)行結(jié)果】程序的運(yùn)行結(jié)果如圖3-9所示。圖3-9例3-4程序的運(yùn)行結(jié)果3.2lxml庫(kù).Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲SectionTitle3.3beautifulsoup4庫(kù)3.3beautifulsoup4庫(kù)3.3.1案例引入——爬取Q房租房網(wǎng)站的數(shù)據(jù)【例3-5】

爬取Q房租房網(wǎng)站的內(nèi)容(網(wǎng)址/rent),利用beautifulsoup4庫(kù)解析網(wǎng)頁(yè)后,輸出爬取到的第一個(gè)房源標(biāo)題?!緟⒖即a】importrequests #導(dǎo)入requests模塊frombs4importBeautifulSoup #導(dǎo)入BeautifulSoup模塊url='/rent' #定義url字符串#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(url)#創(chuàng)建BeautifulSoup對(duì)象,并設(shè)置使用lxml解析器soup=BeautifulSoup(r.text,'lxml')#獲取第一個(gè)房源標(biāo)題,并賦值給titletitle=soup.find('div',class_='list-main-headerclearfix').a.string.strip()print('第一個(gè)房源標(biāo)題:',title) #輸出title3.3beautifulsoup4庫(kù)【運(yùn)行結(jié)果】程序的運(yùn)行結(jié)果如圖3-9所示。圖3-9例3-4程序的運(yùn)行結(jié)果3.3beautifulsoup4庫(kù)【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-10所示。圖3-10例3-5程序的運(yùn)行結(jié)果3.3beautifulsoup4庫(kù)3.3.2beautifulsoup4庫(kù)簡(jiǎn)介beautifulsoup4庫(kù)也稱為BeautifulSoup庫(kù)或bs4庫(kù),用于解析HTML或XML文檔。beautifulsoup4庫(kù)不是Python內(nèi)置的標(biāo)準(zhǔn)庫(kù),使用之前需要安裝,安裝方法與requests庫(kù)的安裝類似(請(qǐng)參考2.3.2小節(jié)),此處不再贅述。beautifulsoup4庫(kù)在解析網(wǎng)頁(yè)時(shí)需要依賴解析器,它支持Python標(biāo)準(zhǔn)庫(kù)中的HTML解析器,還支持一些其他的第三方解析器,具體如表3-6所示。3.3beautifulsoup4庫(kù)beautifulsoup4庫(kù)可以自動(dòng)將輸入文檔轉(zhuǎn)換為Unicode編碼,將輸出文檔轉(zhuǎn)換為UTF-8編碼,故不需要考慮編碼方式。3.3beautifulsoup4庫(kù)表3-6beautifulsoup4庫(kù)支持的解析器解析器使用方法優(yōu)點(diǎn)缺點(diǎn)Python標(biāo)準(zhǔn)庫(kù)中的HTML解析器BeautifulSoup(markup,"html.parser")Python的內(nèi)置標(biāo)準(zhǔn)庫(kù),執(zhí)行速度適中,文檔容錯(cuò)能力強(qiáng)Python2.7.3或3.2.2前的版本文檔容錯(cuò)能力差lxmlHTML解析器BeautifulSoup(markup,"lxml")速度快,文檔容錯(cuò)能力強(qiáng)需要安裝C語言庫(kù)lxmlXML解析器BeautifulSoup(markup,"xml")速度快,唯一支持XML的解析器需要安裝C語言庫(kù)html5libBeautifulSoup(markup,"html5lib")容錯(cuò)性最好,以瀏覽器的方式解析文檔,生成HTML5格式的文檔速度慢,不依賴外部擴(kuò)展3.3beautifulsoup4庫(kù)3.3.3beautifulsoup4基本用法beautifulsoup4庫(kù)中最重要的是BeautifulSoup類,它的實(shí)例化對(duì)象相當(dāng)于一個(gè)頁(yè)面。解析網(wǎng)頁(yè)時(shí),需要使用BeautifulSoup()創(chuàng)建一個(gè)BeautifulSoup對(duì)象,該對(duì)象是一個(gè)樹形結(jié)構(gòu),包含了HTML頁(yè)面中的標(biāo)簽元素,如<head>、<body>等。也就是說,HTML中的主要結(jié)構(gòu)都變成了BeautifulSoup對(duì)象的一個(gè)個(gè)屬性,然后可通過“對(duì)象名.屬性名”形式獲取該對(duì)象的第一個(gè)屬性值(即節(jié)點(diǎn))。Beautifulsoup4基本用法3.3beautifulsoup4庫(kù)BeautifulSoup對(duì)象的屬性名與HTML的標(biāo)簽名相同,HTML常用的標(biāo)簽見表3-1。3.3beautifulsoup4庫(kù)表3-7Tag對(duì)象的常用屬性屬性說明name標(biāo)簽的名字,如head、title等,返回一個(gè)字符串string標(biāo)簽所包圍的文字,網(wǎng)頁(yè)中真實(shí)的文字(尖括號(hào)之間的內(nèi)容),返回一個(gè)字符串a(chǎn)ttrs字典,包含了頁(yè)面標(biāo)簽的所有屬性(尖括號(hào)內(nèi)的所有項(xiàng)),如href,返回一個(gè)字典contents這個(gè)標(biāo)簽下所有子標(biāo)簽的內(nèi)容,返回一個(gè)列表其中,attrs返回的是標(biāo)簽的所有屬性組成的字典類型的數(shù)據(jù),可通過“atrrs['屬性名']”形式獲取屬性值。3.3beautifulsoup4庫(kù)【例3-4】爬取Q房租房網(wǎng)站的內(nèi)容(網(wǎng)址/rent),通過beautifulsoup4庫(kù)解析網(wǎng)頁(yè),輸出第一個(gè)li節(jié)點(diǎn)類型、內(nèi)容及其屬性等信息?!締栴}分析】

在GoogleChrome瀏覽器中訪問/rent,查看并分析HTML的源代碼,可以看到第一個(gè)li節(jié)點(diǎn)的源代碼,如圖3-11所示。3.3beautifulsoup4庫(kù)圖3-11Q房租房網(wǎng)站的HTML源代碼3.3beautifulsoup4庫(kù)【參考代碼】

importrequests #導(dǎo)入requests模塊frombs4importBeautifulSoup #導(dǎo)入BeautifulSoup模塊url='/rent' #定義url字符串#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(url)#創(chuàng)建BeautifulSoup對(duì)象,并設(shè)置使用lxml解析器soup=BeautifulSoup(r.text,'lxml')print('soup類型:',type(soup)) #輸出soup類型print('“soup.li”類型:',type(soup.li)) #輸出“soup.li”類型print('li節(jié)點(diǎn):\n',soup.li) #輸出li節(jié)點(diǎn)print('li節(jié)點(diǎn)的name屬性:',)#輸出li節(jié)點(diǎn)的name屬性3.3beautifulsoup4庫(kù)#輸出li節(jié)點(diǎn)的contents屬性print('li節(jié)點(diǎn)的contents屬性:',soup.li.contents)#輸出li節(jié)點(diǎn)的string屬性print('li節(jié)點(diǎn)的string屬性:',soup.li.string)#輸出li節(jié)點(diǎn)的attrs屬性print('li節(jié)點(diǎn)的attrs屬性:',soup.li.attrs)#輸出li節(jié)點(diǎn)的attrs屬性的“class”屬性值print('li節(jié)點(diǎn)的attrs屬性的“class”屬性值:',soup.li.attrs['class'])#輸出li節(jié)點(diǎn)下a節(jié)點(diǎn)的string屬性print('li節(jié)點(diǎn)下a節(jié)點(diǎn)的string屬性:',soup.li.a.string)3.3beautifulsoup4庫(kù)【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-12所示。圖3-10例3-5程序的運(yùn)行結(jié)果3.3beautifulsoup4庫(kù)按照HTML語法,可以在標(biāo)簽中嵌套其他標(biāo)簽,因此string屬性的返回值遵循如下原則。(1)如果標(biāo)簽內(nèi)部沒有其他標(biāo)簽,string屬性返回其中的內(nèi)容。(2)如果標(biāo)簽內(nèi)部還有其他標(biāo)簽,但只有一個(gè)標(biāo)簽,string屬性返回最里面標(biāo)簽的內(nèi)容。(3)如果標(biāo)簽內(nèi)部還有其他標(biāo)簽,且不止一個(gè)標(biāo)簽,string屬性返回None。3.3beautifulsoup4庫(kù)3.3.4方法選擇器beautifulsoup4庫(kù)還提供了一些查詢方法,如find_all()和find()等。find_all()方法會(huì)遍歷整個(gè)HTML文件,按照條件返回所有匹配的節(jié)點(diǎn),其方法原型如下:find_all(name,attrs,recursive,string,limit)(1)name:通過HTML標(biāo)簽名直接查找節(jié)點(diǎn)。(2)attrs:通過HTML標(biāo)簽的屬性查找節(jié)點(diǎn)(需列出屬性名和值),可以同時(shí)設(shè)置多個(gè)屬性。3.3beautifulsoup4庫(kù)(3)recursive:搜索層次,默認(rèn)查找當(dāng)前標(biāo)簽的所有子孫節(jié)點(diǎn),如果只查找標(biāo)簽的子節(jié)點(diǎn),可以使用參數(shù)recursive=False。(4)string:通過關(guān)鍵字檢索string屬性內(nèi)容,傳入的形式可以是字符串,也可以是正則表達(dá)式對(duì)象。(5)limit:返回結(jié)果的個(gè)數(shù),默認(rèn)返回全部結(jié)果。簡(jiǎn)單地說,BeautifulSoup對(duì)象的find_all()方法可以根據(jù)標(biāo)簽名、標(biāo)簽屬性和內(nèi)容,查找并返回節(jié)點(diǎn)列表。3.3beautifulsoup4庫(kù)【例3-7】

爬取Q房租房網(wǎng)站的內(nèi)容(網(wǎng)址/rent),通過beautifulsoup4庫(kù)解析網(wǎng)頁(yè),輸出第一個(gè)li節(jié)點(diǎn)類型、內(nèi)容及其屬性等信息?!緟⒖即a】importrequests #導(dǎo)入requests模塊frombs4importBeautifulSoup #導(dǎo)入BeautifulSoup模塊importre #導(dǎo)入re模塊url='/rent/' #定義url字符串#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給r3.3beautifulsoup4庫(kù)r=requests.get(url)#創(chuàng)建BeautifulSoup對(duì)象,并設(shè)置使用lxml解析器soup=BeautifulSoup(r.text,'lxml')#輸出所有span節(jié)點(diǎn)個(gè)數(shù)print('所有span節(jié)點(diǎn)個(gè)數(shù):',len(soup.find_all('span')))#輸出class屬性值為“amount”的所有span節(jié)點(diǎn)個(gè)數(shù)print('class屬性值為“amount”的所有span節(jié)點(diǎn)個(gè)數(shù):',len(soup.find_all('span',attrs={'class':'amount'})))#輸出class屬性值為“amount”的所有span節(jié)點(diǎn)print('class屬性值為“amount”的所有span節(jié)點(diǎn):')i=0 #初始化i#遍歷并每行輸出3個(gè)span節(jié)點(diǎn)3.3beautifulsoup4庫(kù)fornodeinsoup.find_all('span',attrs={'class':'amount'}):i+=1ifi%3==0:print(node)else:print(node,end='')#輸出前3個(gè)class屬性值為“amount”的span節(jié)點(diǎn)print('前3個(gè)class屬性值為“amount”的span節(jié)點(diǎn):\n',soup.find_all('span',attrs={'class':'amount'},limit=3))#輸出string屬性包含“2室1廳”的前3個(gè)節(jié)點(diǎn)的文本print('string屬性包含“2室1廳”的前3個(gè)節(jié)點(diǎn)的文本:',soup.find_all(string=pile('2室1廳'),limit=3))3.3beautifulsoup4庫(kù)【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-13所示。圖3-13例3-7程序的運(yùn)行結(jié)果3.3beautifulsoup4庫(kù)find_all()方法通過屬性查找節(jié)點(diǎn)時(shí),對(duì)于一些常用的屬性(如id和class等),可以不用attrs字典形式來傳遞,而用賦值的形式直接傳入?yún)?shù)(如find_all(class_='hotnews'),由于class在Python中是一個(gè)關(guān)鍵字,所以后面需要加一個(gè)下劃線)。find()方法的用法與find_all()方法類似,但其返回結(jié)果是第一個(gè)匹配的節(jié)點(diǎn)。3.3beautifulsoup4庫(kù)beautifulsoup4庫(kù)還提供了如下其他查詢方法。find_parents()和find_parent():前者返回所有祖先節(jié)點(diǎn),后者返回直接父節(jié)點(diǎn)。find_next_siblings()和find_next_sibling():前者返回后面所有的兄弟節(jié)點(diǎn),后者返回后面的第一個(gè)兄弟節(jié)點(diǎn)。find_previous_siblings()和find_previous_sibling():前者返回前面所有的兄弟節(jié)點(diǎn),后者返回前面的第一個(gè)兄弟節(jié)點(diǎn)。find_all_previous()和find_previous():前者返回節(jié)點(diǎn)前所有符合條件的節(jié)點(diǎn),后者返回節(jié)點(diǎn)前第一個(gè)符合條件的節(jié)點(diǎn)。3.3beautifulsoup4庫(kù)3.3.5CSS選擇器beautifulsoup4庫(kù)還提供了使用CSS選擇器來選擇節(jié)點(diǎn)的方法(只需要調(diào)用select()方法傳入相應(yīng)的CSS選擇器即可),CSS常用的選擇器見表3-2。CSS選擇器【例3-8】

爬取Q房租房網(wǎng)站的內(nèi)容(網(wǎng)址/rent),使用CSS選擇器選擇節(jié)點(diǎn),輸出節(jié)點(diǎn)屬性和文本。3.3beautifulsoup4庫(kù)【參考代碼】importrequests #導(dǎo)入requests模塊frombs4importBeautifulSoup #導(dǎo)入BeautifulSoup模塊url='/rent/' #定義url字符串#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(url)#創(chuàng)建BeautifulSoup對(duì)象,并設(shè)置使用lxml解析器soup=BeautifulSoup(r.text,'lxml')#輸出div節(jié)點(diǎn)下所有a節(jié)點(diǎn)個(gè)數(shù)print('div節(jié)點(diǎn)下所有a節(jié)點(diǎn)個(gè)數(shù):',len(soup.select('diva')))3.3beautifulsoup4庫(kù)#獲取第一個(gè)class屬性值為“l(fā)ist-main-header”的節(jié)點(diǎn)下所有a節(jié)點(diǎn)node_a=soup.select('.list-main-header')[0].select('a')#輸出node_a列表中第一個(gè)a節(jié)點(diǎn)的href屬性值print('第一個(gè)a節(jié)點(diǎn)的href屬性值:',node_a[0]['href'])#輸出node_a列表中第一個(gè)a節(jié)點(diǎn)的文本print('第一個(gè)a節(jié)點(diǎn)的文本:',node_a[0].string)3.3beautifulsoup4庫(kù)【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-14所示。圖3-14例3-8程序的運(yùn)行結(jié)果3.3beautifulsoup4庫(kù)3.3.6典型案例【問題分析】通過查看和分析HTML源代碼,可以看到第一個(gè)房源信息包含在第一個(gè)class屬性值為“itemsclearfix”的li節(jié)點(diǎn)中;戶型、面積、裝修、樓層、出租方式包含在li節(jié)點(diǎn)下class屬性值為“house-metasclearfix”的div節(jié)點(diǎn)下的p節(jié)點(diǎn)中;租金包含在li節(jié)點(diǎn)下class屬性值為“l(fā)ist-price”的div節(jié)點(diǎn)下的span節(jié)點(diǎn)中;小區(qū)信息包含在li節(jié)點(diǎn)下class屬性值為“house-locationclearfix”的div節(jié)點(diǎn)下的div節(jié)點(diǎn)中,如圖3-15所示?!纠?-9】爬取Q房租房網(wǎng)站的內(nèi)容(網(wǎng)址/rent),解析網(wǎng)頁(yè)后,輸出爬取到的第一個(gè)房源的戶型、面積、裝修、樓層、出租方式、租金和小區(qū)信息。3.3beautifulsoup4庫(kù)圖3-15Q房租房網(wǎng)站的HTML源代碼3.3beautifulsoup4庫(kù)【參考代碼】importrequests #導(dǎo)入requests模塊frombs4importBeautifulSoup #導(dǎo)入BeautifulSoup模塊url='/rent' #定義url字符串#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(url)#創(chuàng)建BeautifulSoup對(duì)象,并設(shè)置使用lxml解析器soup=BeautifulSoup(r.text,'lxml')#獲取第一個(gè)class屬性值為'itemsclearfix'的li節(jié)點(diǎn),包含第一個(gè)租房信息house=soup.select('.list-resultli')[0]#獲取第一個(gè)房源信息,包括戶型、面積、裝修、樓層和出租方式3.3beautifulsoup4庫(kù)#賦值給house_metashouse_metas=house.select('[class="house-metasclearfix"]p')foriteminhouse_metas: #遍歷print(item.string.strip()) #輸出第一個(gè)房源信息#獲取第一個(gè)房源租金,并賦值給list_pricelist_price=house.select('[class="list-price"]span')#輸出第一個(gè)房源租金print(list_price[0].string+list_price[1].string)#獲取第一個(gè)房源小區(qū)信息,并賦值給locationlocation=house.select('[class="house-locationclearfix"]div')[0].text.strip()print(location) #輸出第一個(gè)房源小區(qū)信息3.3beautifulsoup4庫(kù)Tag對(duì)象的string屬性返回標(biāo)簽的文本信息,而text屬性返回標(biāo)簽下所有標(biāo)簽的文本信息。3.3beautifulsoup4庫(kù)【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-16所示。圖3-16例3-9程序的運(yùn)行結(jié)果3.3beautifulsoup4庫(kù).Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲SectionTitle3.4正則表達(dá)式3.4正則表達(dá)式3.4.1案例引入——爬取百度搜索首頁(yè)的數(shù)據(jù)【問題分析】

通過分析百度搜索首頁(yè)的HTML源代碼可以看到,“新聞”對(duì)應(yīng)的節(jié)點(diǎn)為id屬性值為“s-top-left”的div節(jié)點(diǎn)下的第一個(gè)a節(jié)點(diǎn),如圖3-17所示?!纠?-9】

爬取百度搜索首頁(yè)的內(nèi)容(網(wǎng)址/),輸出爬取到的“新聞”對(duì)應(yīng)的節(jié)點(diǎn)的屬性和文本。圖3-17百度搜索首頁(yè)的HTML源代碼3.4正則表達(dá)式【參考代碼】importrequests #導(dǎo)入requests模塊importre #導(dǎo)入re模塊url='/' #定義字符串urlheadersvalue={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/83.0.4103.97Safari/537.36'} #設(shè)置請(qǐng)求頭User-Agent信息#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(url,headers=headersvalue)html=r.text #將響應(yīng)內(nèi)容賦值給html3.4正則表達(dá)式#使用re模塊的search函數(shù)查詢“新聞”對(duì)應(yīng)的節(jié)點(diǎn)item=re.search('<div.*?s-top-left.*?a.*?href="(.*?)".*?>(.*?)</a>',html,re.S)print(item.group(1),item.group(2)) #輸出節(jié)點(diǎn)的屬性和文本3.4正則表達(dá)式search()方法返回Match對(duì)象,它的group()方法可以返回Match對(duì)象的一個(gè)或多個(gè)子組,而group(1)為第一個(gè)子組值。3.4正則表達(dá)式【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-18所示。圖3-18例3-10程序的運(yùn)行結(jié)果3.4正則表達(dá)式3.4.2正則表達(dá)式基礎(chǔ)正則表達(dá)式是用于處理字符串的強(qiáng)大工具,它使用預(yù)定義的特定模式去匹配一類具有共同特征的字符串,主要用于快速、準(zhǔn)確地完成復(fù)雜字符串的查找、替換等。Python支持的正則表達(dá)式常用元字符和語法如表3-8所示。3.4正則表達(dá)式表5-2-4pstree命令中常用選項(xiàng)的含義元字符和語法說明表達(dá)式實(shí)例字符一般字符匹配自身python匹配python.匹配除換行符外的任意單個(gè)字符a.c匹配abc、acc等\轉(zhuǎn)義字符a\.c匹配a.c;a\\c匹配a\c[]表示一組字符a[bcd]e(同a[b-d]e)匹配abe、ace和ade[^]不在[]中的字符[^abc]匹配除a,b,c之外的字符表3-8正則表達(dá)式常用元字符和語法3.4正則表達(dá)式表5-2-4pstree命令中常用選項(xiàng)的含義預(yù)定義字符集(可用在字符集[]中)\d匹配任意數(shù)字,等價(jià)于[0-9]a\dc匹配a1c、a2c等\D匹配任意非數(shù)字a\Dc匹配abc、asc等\s匹配任意空白字符,等價(jià)于[\t\n\r\f]a\sc匹配ac\S匹配任意非空字符a\Sc匹配abc等\w匹配數(shù)字、字母、下劃線a\wc匹配a1c、abc等\W匹配非數(shù)字、字母、下劃線a\Wc匹配ac表3-8正則表達(dá)式常用元字符和語法(續(xù))3.4正則表達(dá)式表5-2-4pstree命令中常用選項(xiàng)的含義元字符和語法說明表達(dá)式實(shí)例數(shù)量詞(可用在字符或()之后)*匹配位于*之前的字符0次或多次abc*匹配ab、abccc等+匹配位于+之前的字符1次或多次abc+匹配abc、abccc等?匹配位于?之前的字符0次或1次,當(dāng)此字符緊隨任何其他限定符(*、+、?、{m}、{m,n})之后時(shí),匹配模式為“非貪婪”abc?匹配ab和abc{m}匹配前一個(gè)字符m次ab{2}c匹配abbc{m,n}匹配前一個(gè)字符m至n次,省略m則匹配0至n次;省略n則匹配m至無限次ab{1,2}c匹配abc和abbc表3-8正則表達(dá)式常用元字符和語法(續(xù))3.4正則表達(dá)式邊界匹配^匹配行首^abc匹配以abc開始的行$匹配行尾abc$匹配以abc結(jié)尾的行表3-8正則表達(dá)式常用元字符和語法(續(xù))邏輯、分組|匹配位于|之前或之后的字符a|b匹配a或b()將位于()內(nèi)的內(nèi)容作為一個(gè)整體(abc){2}匹配abcabc3.4正則表達(dá)式正則表達(dá)式通常用于在文本中查找匹配的字符串。Python中數(shù)量詞默認(rèn)是貪婪的,即總是嘗試匹配盡可能多的字符;相反,非貪婪總是嘗試匹配盡可能少的字符。例如,正則表達(dá)式“ab*”如果用于查找字符串“abbbc”,將找到“abbb”;而如果使用表達(dá)式“ab*?”,將找到“a”。3.4正則表達(dá)式具體應(yīng)用時(shí),可以單獨(dú)使用某種類型的元字符,但處理復(fù)雜字符串時(shí),經(jīng)常需要將多個(gè)正則表達(dá)式元字符進(jìn)行組合。下面給出了幾個(gè)示例。(1)'[a-zA-Z0-9]'可以匹配一個(gè)任意大小寫字母或數(shù)字。(2)'^(\w){6,15}$'匹配長(zhǎng)度為6~15的字符串,可以包含數(shù)字、字母和下劃線。(3)'^\w+@(\w+\.)+\w+$'檢查給定字符串是否為合法電子郵件地址。(4)'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'檢查給定字符串是否為合法IP地址。3.4正則表達(dá)式3.4.3re模塊在Python中,主要使用re模塊來實(shí)現(xiàn)正則表達(dá)式的操作,該模塊的常用方法如表3-9所示。其中,函數(shù)參數(shù)pattern為正則表達(dá)式;參數(shù)string為字符串;參數(shù)flags的值可以是re.I(忽略大小寫)、re.M(多行匹配模式)和re.S(匹配包含換行符在內(nèi)的所有字符)等。3.4正則表達(dá)式方法描述pile(pattern[,flags])用于編譯正則表達(dá)式,生成一個(gè)正則表達(dá)式(Pattern)對(duì)象re.search(pattern,string[,flags])或search(string[,pos[,endpos]])掃描整個(gè)字符串并返回第一個(gè)成功的匹配re.match(pattern,string[,flags])或match(string[,pos[,endpos]])嘗試從字符串的起始位置匹配一個(gè)模式,返回Match對(duì)象或Nonere.findall(pattern,string[,flags])或findall(string[,pos[,endpos]])在字符串中找到正則表達(dá)式所匹配的所有子串,并返回一個(gè)列表,如果沒有找到匹配的,則返回空列表re.sub(pattern,repl,string[,count=0])或sub(repl,string[,count])用于替換字符串中的匹配項(xiàng)re.split(pattern,string[,maxsplit=0])或split(string[,maxsplit])按照能夠匹配的子串將字符串分割后返回列表表3-9re模塊常用方法3.4正則表達(dá)式【問題分析】

通過分析百度搜索首頁(yè)的HTML源代碼(見圖3-19),可以看到,百度熱榜新聞的排名信息包含在class屬性值包含“title-content-index”的span節(jié)點(diǎn)的文本中,利用非貪婪匹配來提取span節(jié)點(diǎn)內(nèi)的文本信息,正則表達(dá)式為“<span.*?title-content-index.*?>(.*?)</span>”;標(biāo)題信息包含在class屬性值包含“title-content-title”的span節(jié)點(diǎn)的文本中,則正則表達(dá)式可為“<span.*?title-content-index.*?>(.*?)</span>.*?title-content-title.*?>(.*?)</span>”?!纠?-9】爬取百度搜索首頁(yè)的內(nèi)容(網(wǎng)址/),輸出爬取到的百度熱榜新聞。3.4正則表達(dá)式圖3-19百度搜索首頁(yè)的HTML源代碼3.4正則表達(dá)式【參考代碼】importrequests #導(dǎo)入requests模塊importre #導(dǎo)入re模塊url='/' #定義字符串urlheadersvalue={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/83.0.4103.97Safari/537.36'} #設(shè)置請(qǐng)求頭User-Agent信息#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(url,headers=headersvalue)html=r.text #將響應(yīng)內(nèi)容賦值給html3.4正則表達(dá)式#編譯正則表達(dá)式,并將返回的正則表達(dá)式對(duì)象賦值給patternpattern=pile('<span.*?title-content-index.*?>(.*?)</span>.*?title-content-title.*?>(.*?)</span>')#查找頁(yè)面中所有符合條件的字符串items=re.findall(pattern,html)foriteminitems: #遍歷列表print(item) #輸出列表每一項(xiàng)3.4正則表達(dá)式【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-20所示。圖3-20例3-11程序的運(yùn)行結(jié)果3.4正則表達(dá)式.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲SectionTitle3.5存儲(chǔ)數(shù)據(jù)至文件3.5存儲(chǔ)數(shù)據(jù)至文件3.5.1存儲(chǔ)數(shù)據(jù)至JSON文件JavaScript對(duì)象標(biāo)記(JavascriptObjectNotation,JSON)是一種輕量級(jí)的文本數(shù)據(jù)交換格式。它通過對(duì)象和數(shù)組的組合來表示數(shù)據(jù),構(gòu)造簡(jiǎn)潔但是結(jié)構(gòu)化程度非常高。Python提供了json庫(kù)來實(shí)現(xiàn)對(duì)JSON文件的讀寫操作。json庫(kù)是Python內(nèi)置的標(biāo)準(zhǔn)庫(kù),不需要額外安裝即可使用。JSON數(shù)據(jù)的書寫格式是:鍵-值對(duì),如{"age":18}。鍵是字符串,值可以是對(duì)象、數(shù)組、數(shù)字(整數(shù)或浮點(diǎn)數(shù))、布爾值、null和字符串,此處字符串必須要用雙引號(hào)引起來,不能用單引號(hào)。3.5存儲(chǔ)數(shù)據(jù)至文件利用dumps()方法可以將Python數(shù)據(jù)類型轉(zhuǎn)化為JSON格式的字符串,然后調(diào)用文件的write()方法寫入文本。dumps()方法原型如下:1.寫入JSON文件dumps(obj,skipkeys=False,ensure_ascii=True,check_circular=True,allow_nan=True,cls=None,indent=None,separators=None,default=None,sort_keys=False,**kw)3.5存儲(chǔ)數(shù)據(jù)至文件(1)obj:Python數(shù)據(jù)序列。(2)skipkeys:表示是否跳過非Python基本類型的鍵,默認(rèn)值為False,設(shè)置為True時(shí),表示跳過此類鍵。(3)ensure_ascii:表示顯示格式,默認(rèn)為True,如果需要輸出中文字符,需要將這個(gè)參數(shù)設(shè)置為False,并在寫入文件時(shí)規(guī)定文件輸出的編碼。(4)indent:表示輸出時(shí)縮進(jìn)字符的個(gè)數(shù)。(5)sort_keys:表示是否根據(jù)鍵的值進(jìn)行排序,默認(rèn)為False,設(shè)置為True時(shí)數(shù)據(jù)將根據(jù)鍵的值進(jìn)行排序?!纠?-12】定義數(shù)據(jù),輸出轉(zhuǎn)化為JSON格式的字符串,并保存至JSON文件中。3.5存儲(chǔ)數(shù)據(jù)至文件【參考代碼】

importjson #導(dǎo)入json模塊#定義datadata=[{'姓名':'小明','性別':'男','生日':'2016-06-06'},{'姓名':'小紅','性別':'女','生日':'2017-07-07'}]#將data轉(zhuǎn)化為JSON格式的字符串,并賦值給json_datajson_data=json.dumps(data,indent=2,ensure_ascii=False)print(json_data) #輸出json_data#打開data.json文件withopen('data.json','w',encoding='utf-8')asfile:file.write(json_data) #將json_data寫入data.json文件3.5存儲(chǔ)數(shù)據(jù)至文件【運(yùn)行結(jié)果】

輸出的JSON格式的字符串和保存的“data.json”文件內(nèi)容如圖3-21所示。圖3-21例3-12程序的運(yùn)行結(jié)果3.5存儲(chǔ)數(shù)據(jù)至文件利用loads()方法可以將JSON格式的字符串轉(zhuǎn)化為Python數(shù)據(jù)類型,如果從JSON文件中讀取內(nèi)容,可以先調(diào)用文件的read()方法讀取文本內(nèi)容,然后再進(jìn)行轉(zhuǎn)換。2.讀取JSON文件【例3-12】從JSON文件讀取數(shù)據(jù),并將其轉(zhuǎn)化為Python數(shù)據(jù)類型。3.5存儲(chǔ)數(shù)據(jù)至文件importjson #導(dǎo)入json模塊#打開data.json文件withopen('data.json','r',encoding='utf-8')asfile:str=file.read() #讀取文件,并將讀取的內(nèi)容賦值給字符串str#將JSON格式的字符串轉(zhuǎn)化為Python數(shù)據(jù)類型,并賦值給datadata=json.loads(str)print(data) #輸出data【參考代碼】3.5存儲(chǔ)數(shù)據(jù)至文件【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-22所示。圖3-22例3-13程序的運(yùn)行結(jié)果3.5存儲(chǔ)數(shù)據(jù)至文件3.5.2

存儲(chǔ)數(shù)據(jù)至CSV文件字符分隔符(Comma-SeparatedValues,CSV)也稱逗號(hào)分隔符,其文件以純文本形式存儲(chǔ)表格數(shù)據(jù)。CSV文件由任意數(shù)目的記錄組成,記錄間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其他字符或字符串,最常見的是逗號(hào)或制表符。通常,所有記錄都有完全相同的字段序列,結(jié)構(gòu)簡(jiǎn)單清晰。Python提供了csv庫(kù)來實(shí)現(xiàn)CSV文件的讀寫操作。csv庫(kù)是Python內(nèi)置的標(biāo)準(zhǔn)庫(kù),不需要額外安裝即可使用。3.5存儲(chǔ)數(shù)據(jù)至文件csv庫(kù)提供了初始化寫入對(duì)象的writer()方法,還提供了writerow()方法(寫入一行)和writerows()方法(寫入多行)用于寫入文件。1.寫入CSV文件【例3-14】定義列表數(shù)據(jù),將數(shù)據(jù)保存至CSV文件中。3.5存儲(chǔ)數(shù)據(jù)至文件importcsv #導(dǎo)入csv模塊#定義列表形式數(shù)據(jù)datadata=[['姓名','性別','生日'],['小明','男','2016-06-06']]#打開data.csv文件寫入數(shù)據(jù)withopen('data.csv','w',newline='')asfile:writer=csv.writer(file) #初始化writer對(duì)象writer.writerows(data) #寫入多行writer.writerow(['小紅','女','2016-08-08'])#寫入一行【參考代碼】3.5存儲(chǔ)數(shù)據(jù)至文件在打開文件寫入時(shí),需要設(shè)置newline參數(shù)為“newline=”,如果不設(shè)置,則每寫入一行后將會(huì)寫入一個(gè)空行。3.5存儲(chǔ)數(shù)據(jù)至文件【運(yùn)行結(jié)果】

保存的“data.csv”文件的內(nèi)容如圖3-23所示。圖3-23例3-14程序的運(yùn)行結(jié)果3.5存儲(chǔ)數(shù)據(jù)至文件讀取CSV文件時(shí),可通過調(diào)用reader()方法返回一個(gè)可迭代對(duì)象,此對(duì)象只能迭代一次,不能直接輸出,須調(diào)用list()方法將其轉(zhuǎn)換為列表輸出。2.讀取CSV文件【例3-15】

從CSV文件中讀取數(shù)據(jù),并將數(shù)據(jù)轉(zhuǎn)換成列表后輸出。3.5存儲(chǔ)數(shù)據(jù)至文件importcsv #導(dǎo)入csv模塊#打開data.csv文件讀取數(shù)據(jù)withopen('data.csv','r')asfile:reader=csv.reader(file) #初始化reader對(duì)象#將reader對(duì)象轉(zhuǎn)換為列表,并賦值給list1list1=list(reader)print(list1) #輸出list1【參考代碼】3.5存儲(chǔ)數(shù)據(jù)至文件【運(yùn)行結(jié)果】

程序的運(yùn)行結(jié)果如圖3-24所示。圖3-24例3-15程序的運(yùn)行結(jié)果3.5存儲(chǔ)數(shù)據(jù)至文件csv庫(kù)還提供了DictWriter()方法用于初始化一個(gè)字典寫入對(duì)象,writeheader()方法用于寫入表頭,DictReader()方法用于將讀取的數(shù)據(jù)轉(zhuǎn)化成字典形式。3.5存儲(chǔ)數(shù)據(jù)至文件.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲.Python網(wǎng)絡(luò)爬蟲SectionTitle實(shí)戰(zhàn)演練爬取Q房租房網(wǎng)站房源信息實(shí)戰(zhàn)演練——爬取Q房租房網(wǎng)站房源信息1.實(shí)戰(zhàn)目的(1)練習(xí)使用beautifulsoup4庫(kù)解析爬取的網(wǎng)頁(yè)內(nèi)容。(2)練習(xí)將獲取的數(shù)據(jù)保存至CSV文件中。2.實(shí)戰(zhàn)內(nèi)容爬取Q房租房網(wǎng)站的內(nèi)容(網(wǎng)址/rent),解析網(wǎng)頁(yè),獲取所有房源信息,包括標(biāo)題、戶型、面積、裝修、樓層、出租方式、租金和小區(qū)信息,并將爬取到的房源信息保存到CSV文件中。3.實(shí)戰(zhàn)分析使用GoogleChrome瀏覽器打開Q房租房網(wǎng)站(網(wǎng)址/rent),可以看到每一頁(yè)只顯示30個(gè)房源信息,翻頁(yè)查看每一頁(yè)的網(wǎng)址(如https://beijing.qfang.com/rent/f9),發(fā)現(xiàn)網(wǎng)址中的數(shù)字隨著頁(yè)數(shù)的變化而變化(如第9頁(yè)為f9)。由于房源總數(shù)會(huì)發(fā)生變化,故房源頁(yè)面數(shù)也會(huì)發(fā)生變化(房源總數(shù)除以30后向上取整即為房源頁(yè)面數(shù))。分析HTML源代碼,可以看出,房源總數(shù)包含在class屬性值為“l(fā)ist-total”的div節(jié)點(diǎn)下的span節(jié)點(diǎn)中;房源信息都包含在class屬性值為“l(fā)ist-result”的節(jié)點(diǎn)下的li節(jié)點(diǎn)中,每一個(gè)li節(jié)點(diǎn)包含一個(gè)房源的信息,如圖3-25所示。實(shí)戰(zhàn)演練——爬取Q房租房網(wǎng)站房源信息圖3-25Q房租房網(wǎng)站的HTML源代碼實(shí)戰(zhàn)演練——爬取Q房租房網(wǎng)站房源信息importrequests #導(dǎo)入requests模塊importmath #導(dǎo)入math模塊frombs4importBeautifulSoup #導(dǎo)入BeautifulSoup模塊importcsv #導(dǎo)入csv模塊importtime #導(dǎo)入time模塊#定義url字符串base_url='/rent'headersvalue={'Cookie':'qchatid=5f7438c6-663d-492a-95e9-7dba5a168d34;cookieId=f1e88d86-ce01-4d12-981a-1b214fec4025;language=SIMPLIFIE【參考代碼】

實(shí)戰(zhàn)演練——爬取Q房租房網(wǎng)站房源信息

D;sid=79298dad-c93d-4469-95ed-bc641abb9e6c;CITY_NAME=BEIJING;_ga=GA1.3.32432938.1594014100;RENTROOMREADRECORDCOOKIE=100004247%23100004130%23100003925%23100004090;WINDOW_DEVICE_PIXEL_RATIO=1;_jzqx=1.1594014108.1594172169.1.jzqsr=beijing%2Eqfang%2Ecom|jzqct=/.-;historyKeywords_BEIJING_RENT=%E5%90%8D%E9%83%BD%E5%9B%AD;ROOM_RENT=%2Frent%3Fkeyword%3D%E5%90%8D%E9%83%BD%E5%9B%AD%5E%20%E5%90%8D%E9%83%BD%E5%9B%AD;_gid=GA1.3.2014311171.1594266079;_jzqckmp=1;JSESSIONID=aaa0-You9OGBuhoxj9Umx;Hm_lvt_36d249c63ef3be717ee3ed4f1ef326e2=1594110569,1594172167,1594266079,1594345505;Hm_lvt_de678bd934b065f76f05705d4e7b662c=1594110570,1594172167,1594266079,1594345505;_jzqa=1.3738804563838907000.1590218978.1594282706.1594345505.13;_jzqc=1;_qzjc=1;_dc_gtm_UA-47416713-實(shí)戰(zhàn)演練——爬取Q房租房網(wǎng)站房源信息

1=1;Hm_lpvt_36d249c63ef3be717ee3ed4f1ef326e2=1594346716;Hm_lpvt_de678bd934b065f76f05705d4e7b662c=1594346716;_qzjb=10;_qzjto=7.1.0;_qzja=1.1144910862.1594014107788.1594282706365.1594345504744.1594346673733.159434671590.50.11;_jzqb=594345505.1'} #設(shè)置請(qǐng)求頭User-Agent和Cookie信息#定義函數(shù),獲取所有頁(yè)面房源信息defget_allpage_info():#發(fā)送請(qǐng)求,并將返回結(jié)果賦值給rr=requests.get(base_url,headers=headersvalue)#創(chuàng)建BeautifulSoup對(duì)象,并設(shè)置使

溫馨提示

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

評(píng)論

0/150

提交評(píng)論