《Python網絡爬蟲技術案例教程》(林忠會) 第3章.Python網絡爬蟲_第1頁
《Python網絡爬蟲技術案例教程》(林忠會) 第3章.Python網絡爬蟲_第2頁
《Python網絡爬蟲技術案例教程》(林忠會) 第3章.Python網絡爬蟲_第3頁
《Python網絡爬蟲技術案例教程》(林忠會) 第3章.Python網絡爬蟲_第4頁
《Python網絡爬蟲技術案例教程》(林忠會) 第3章.Python網絡爬蟲_第5頁
已閱讀5頁,還剩135頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲Python網絡爬蟲技術案例教程PythonWangluoPachongJishuAnliJiaochengCOMMITTEDCOMMITTEDCOMMITTECOMMITTECONTENTS目錄COMMITTED第1章網絡爬蟲入門

第2章爬蟲基礎第3章網頁解析基礎第4章爬取動態加載數據第5章反爬蟲策略第6章模擬登錄和處理驗證碼

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

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

爬取小說《三國演義》章節列表網頁的內容(網址/50_50096/),使用lxml庫解析網頁后,輸出爬取到的小說章節列表鏈接。【問題分析】在GoogleChrome瀏覽器中訪問/50_50096/,打開瀏覽器的開發者工具窗口,選擇“Elements”選項后單擊左上角“”按鈕,然后使用鼠標選擇網頁中的某處,即可直接定位到HTML中對應的節點,如圖3-4所示。可以看出,所有小說章節標題都在dd節點下,且其鏈接的值包含在a節點的href屬性中。圖3-4《三國演義》章節列表網頁HTML的源代碼3.2lxml庫【參考代碼】

importrequests #導入requests模塊importurllib.parse

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

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

爬取小說《三國演義》章節列表網頁的內容(網址/50_50096/),通過路徑選擇節點后輸出。【參考代碼】

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

爬取小說《三國演義》第一章節網頁內容(網址/50_50096/18520412.html),通過屬性選擇節點后輸出。【參考代碼】

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

爬取小說《三國演義》第一章節網頁內容(網址/50_50096/18520412.html),輸出爬取到的第一章節的標題和正文。【問題分析】

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

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

爬取Q房租房網站的內容(網址/rent),利用beautifulsoup4庫解析網頁后,輸出爬取到的第一個房源標題。【參考代碼】importrequests #導入requests模塊frombs4importBeautifulSoup #導入BeautifulSoup模塊url='/rent' #定義url字符串#發送請求,并將返回結果賦值給rr=requests.get(url)#創建BeautifulSoup對象,并設置使用lxml解析器soup=BeautifulSoup(r.text,'lxml')#獲取第一個房源標題,并賦值給titletitle=soup.find('div',class_='list-main-headerclearfix').a.string.strip()print('第一個房源標題:',title) #輸出title3.3beautifulsoup4庫【運行結果】程序的運行結果如圖3-9所示。圖3-9例3-4程序的運行結果3.3beautifulsoup4庫【運行結果】

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

在GoogleChrome瀏覽器中訪問/rent,查看并分析HTML的源代碼,可以看到第一個li節點的源代碼,如圖3-11所示。3.3beautifulsoup4庫圖3-11Q房租房網站的HTML源代碼3.3beautifulsoup4庫【參考代碼】

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

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

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

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

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

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

程序的運行結果如圖3-16所示。圖3-16例3-9程序的運行結果3.3beautifulsoup4庫.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲SectionTitle3.4正則表達式3.4正則表達式3.4.1案例引入——爬取百度搜索首頁的數據【問題分析】

通過分析百度搜索首頁的HTML源代碼可以看到,“新聞”對應的節點為id屬性值為“s-top-left”的div節點下的第一個a節點,如圖3-17所示。【例3-9】

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

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

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

程序的運行結果如圖3-20所示。圖3-20例3-11程序的運行結果3.4正則表達式.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲.Python網絡爬蟲SectionTitle3.5存儲數據至文件3.5存儲數據至文件3.5.1存儲數據至JSON文件JavaScript對象標記(JavascriptObjectNotation,JSON)是一種輕量級的文本數據交換格式。它通過對象和數組的組合來表示數據,構造簡潔但是結構化程度非常高。Python提供了json庫來實現對JSON文件的讀寫操作。json庫是Python內置的標準庫,不需要額外安裝即可使用。JSON數據的書寫格式是:鍵-值對,如{"age":18}。鍵是字符串,值可以是對象、數組、數字(整數或浮點數)、布爾值、null和字符串,此處字符串必須要用雙引號引起來,不能用單引號。3.5存儲數據至文件利用dumps()方法可以將Python數據類型轉化為JSON格式的字符串,然后調用文件的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存儲數據至文件(1)obj:Python數據序列。(2)skipkeys:表示是否跳過非Python基本類型的鍵,默認值為False,設置為True時,表示跳過此類鍵。(3)ensure_ascii:表示顯示格式,默認為True,如果需要輸出中文字符,需要將這個參數設置為False,并在寫入文件時規定文件輸出的編碼。(4)indent:表示輸出時縮進字符的個數。(5)sort_keys:表示是否根據鍵的值進行排序,默認為False,設置為True時數據將根據鍵的值進行排序。【例3-12】定義數據,輸出轉化為JSON格式的字符串,并保存至JSON文件中。3.5存儲數據至文件【參考代碼】

importjson #導入json模塊#定義datadata=[{'姓名':'小明','性別':'男','生日':'2016-06-06'},{'姓名':'小紅','性別':'女','生日':'2017-07-07'}]#將data轉化為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存儲數據至文件【運行結果】

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

程序的運行結果如圖3-22所示。圖3-22例3-13程序的運行結果3.5存儲數據至文件3.5.2

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

保存的“data.csv”文件的內容如圖3-23所示。圖3-23例3-14程序的運行結果3.5存儲數據至文件讀取CSV文件時,可通過調用reader()方法返回一個可迭代對象,此對象只能迭代一次,不能直接輸出,須調用list()方法將其轉換為列表輸出。2.讀取CSV文件【例3-15】

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

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

實戰演練——爬取Q房租房網站房源信息

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-實戰演練——爬取Q房租房網站房源信息

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'} #設置請求頭User-Agent和Cookie信息#定義函數,獲取所有頁面房源信息defget_allpage_info():#發送請求,并將返回結果賦值給rr=requests.get(base_url,headers=headersvalue)#創建BeautifulSoup對象,并設置使

溫馨提示

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

評論

0/150

提交評論