python爬虫中三种数据解析方式
一.正解解析
常用正則表達(dá)式:
單字符:
- .: 除換行以外所有字符
- []:[aoe] [a-w]匹配集合中任意一個(gè)字符
- \d:數(shù)字 [0-9]
- \D: 非數(shù)字
- \w :數(shù)字、字母、下劃線、中文
- \W : 非\w
- \s :所有的空白字符包,括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。
- \S : 非空白
數(shù)量修飾:
- *: 任意多次 >=0
- +: 至少1次 >=1
- ? : 可有可無(wú) 0次或者1次
- {m} :固定m次 hello{3,}
- {m,}:至少m次
- {m,n}:m-n次
邊界:
- $ : 以某某結(jié)尾
- ^ : 以某某開(kāi)頭
分組:
(ab) 貪婪模式: .* 非貪婪(惰性)模式: .*?re.I : 忽略大小寫(xiě) re.M :多行匹配 re.S :單行匹配re.sub(正則表達(dá)式, 替換內(nèi)容, 字符串)練習(xí):
import re #提取出python key="javapythonc++php" re.findall('python',key)[0] ##################################################################### #提取出hello world key="<html><h1>hello world<h1></html>" re.findall('<h1>(.*)<h1>',key)[0] ##################################################################### #提取170 string = '我喜歡身高為170的女孩' re.findall('\d+',string) ##################################################################### #提取出http://和https:// key='http://www.baidu.com and https://boob.com' re.findall('https?://',key) ##################################################################### #提取出hello key='lalala<hTml>hello</HtMl>hahah' #輸出<hTml>hello</HtMl> re.findall('<[Hh][Tt][mM][lL]>(.*)</[Hh][Tt][mM][lL]>',key) ##################################################################### #提取出hit. key='bobo@hit.edu.com'#想要匹配到hit. re.findall('h.*?\.',key) ##################################################################### #匹配sas和saas key='saas and sas and saaas' re.findall('sa{1,2}s',key) ##################################################################### #匹配出i開(kāi)頭的行 string = '''fall in love with you i love you very much i love she i love her'''re.findall('^.*',string,re.M) ##################################################################### #匹配全部行 string1 = """<div>靜夜思 窗前明月光 疑是地上霜 舉頭望明月 低頭思故鄉(xiāng) </div>"""re.findall('.*',string1,re.S)需求:爬取糗事百科指定頁(yè)面的糗圖,并將其保存到指定文件夾中
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #!/usr/bin/env python # -*- coding:utf-8 -*- import requests import re import os if __name__ == "__main__":url = 'https://www.qiushibaike.com/pic/%s/'headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',}#指定起始也結(jié)束頁(yè)碼page_start = int(input('enter start page:'))page_end = int(input('enter end page:'))#創(chuàng)建文件夾if not os.path.exists('images'):os.mkdir('images')#循環(huán)解析且下載指定頁(yè)碼中的圖片數(shù)據(jù)for page in range(page_start,page_end+1):print('正在下載第%d頁(yè)圖片'%page)new_url = format(url % page)response = requests.get(url=new_url,headers=headers)#解析response中的圖片鏈接e = '<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>'pa = re.compile(e,re.S)image_urls = pa.findall(response.text)#循環(huán)下載該頁(yè)碼下所有的圖片數(shù)據(jù)for image_url in image_urls:image_url = 'https:' + image_urlimage_name = image_url.split('/')[-1]image_path = 'images/'+image_nameimage_data = requests.get(url=image_url,headers=headers).contentwith open(image_path,'wb') as fp:fp.write(image_data)二.Xpath解析
測(cè)試頁(yè)面數(shù)據(jù)
<html lang="en"> <head><meta charset="UTF-8" /><title>測(cè)試bs4</title> </head> <body><div><p>百里守約</p></div><div class="song"><p>李清照</p><p>王安石</p><p>蘇軾</p><p>柳宗元</p><a href="http://www.song.com/" title="趙匡胤" target="_self"><span>this is span</span>宋朝是最強(qiáng)大的王朝,不是軍隊(duì)的強(qiáng)大,而是經(jīng)濟(jì)很強(qiáng)大,國(guó)民都很有錢(qián)</a><a href="" class="du">總為浮云能蔽日,長(zhǎng)安不見(jiàn)使人愁</a><img src="http://www.baidu.com/meinv.jpg" alt="" /></div><div class="tang"><ul><li><a href="http://www.baidu.com" title="qing">清明時(shí)節(jié)雨紛紛,路上行人欲斷魂,借問(wèn)酒家何處有,牧童遙指杏花村</a></li><li><a href="http://www.163.com" title="qin">秦時(shí)明月漢時(shí)關(guān),萬(wàn)里長(zhǎng)征人未還,但使龍城飛將在,不教胡馬度陰山</a></li><li><a href="http://www.126.com" alt="qi">岐王宅里尋常見(jiàn),崔九堂前幾度聞,正是江南好風(fēng)景,落花時(shí)節(jié)又逢君</a></li><li><a href="http://www.sina.com" class="du">杜甫</a></li><li><a href="http://www.dudu.com" class="du">杜牧</a></li><li><b>杜小月</b></li><li><i>度蜜月</i></li><li><a href="http://www.haha.com" id="feng">鳳凰臺(tái)上鳳凰游,鳳去臺(tái)空江自流,吳宮花草埋幽徑,晉代衣冠成古丘</a></li></ul></div> </body> </html>常用xpath表達(dá)式
屬性定位:
#找到class屬性值為song的div標(biāo)簽 //div[@class="song"]層級(jí)&索引定位:
#找到class屬性值為tang的div的直系子標(biāo)簽ul下的第二個(gè)子標(biāo)簽li下的直系子標(biāo)簽a //div[@class="tang"]/ul/li[2]/a邏輯運(yùn)算:
#找到href屬性值為空且class屬性值為du的a標(biāo)簽 //a[@href="" and @class="du"]模糊匹配:
//div[contains(@class, "ng")] //div[starts-with(@class, "ta")]取文本:
# /表示獲取某個(gè)標(biāo)簽下的文本內(nèi)容 # //表示獲取某個(gè)標(biāo)簽下的文本內(nèi)容和所有子標(biāo)簽下的文本內(nèi)容 //div[@class="song"]/p[1]/text() //div[@class="tang"]//text()取屬性:
//div[@class="tang"]//li[2]/a/@href代碼中使用xpath表達(dá)式進(jìn)行數(shù)據(jù)解析:
1.下載:pip install lxml
2.導(dǎo)包:from lxml import etree
3.將html文檔或者xml文檔轉(zhuǎn)換成一個(gè)etree對(duì)象,然后調(diào)用對(duì)象中的方法查找指定的節(jié)點(diǎn)
本地文件:
tree = etree.parse(文件名) tree.xpath("xpath表達(dá)式")網(wǎng)絡(luò)數(shù)據(jù):
tree = etree.HTML(網(wǎng)頁(yè)內(nèi)容字符串)tree.xpath("xpath表達(dá)式")安裝xpath插件在瀏覽器中對(duì)xpath表達(dá)式進(jìn)行驗(yàn)證:可以在插件中直接執(zhí)行xpath表達(dá)式
-
將xpath插件拖動(dòng)到谷歌瀏覽器拓展程序(更多工具)中,安裝成功
-
啟動(dòng)和關(guān)閉插件 ctrl + shift + x
需求:獲取好段子中段子的內(nèi)容和作者 http://www.haoduanzi.com
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' from lxml import etree import requestsurl='http://www.haoduanzi.com/category-10_2.html' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36',} url_content=requests.get(url,headers=headers).text #使用xpath對(duì)url_conten進(jìn)行解析 #使用xpath解析從網(wǎng)絡(luò)上獲取的數(shù)據(jù) tree=etree.HTML(url_content) #解析獲取當(dāng)頁(yè)所有段子的標(biāo)題 title_list=tree.xpath('//div[@class="log cate10 auth1"]/h3/a/text()')ele_div_list=tree.xpath('//div[@class="log cate10 auth1"]')text_list=[] #最終會(huì)存儲(chǔ)12個(gè)段子的文本內(nèi)容 for ele in ele_div_list:#段子的文本內(nèi)容(是存放在list列表中)text_list=ele.xpath('./div[@class="cont"]//text()')#list列表中的文本內(nèi)容全部提取到一個(gè)字符串中text_str=str(text_list)#字符串形式的文本內(nèi)容防止到all_text列表中text_list.append(text_str) print(title_list) print(text_list)下載煎蛋網(wǎng)中的圖片數(shù)據(jù):http://jandan.net/ooxx
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' import requests from lxml import etree from fake_useragent import UserAgent import base64 import urllib.request url = 'http://jandan.net/ooxx' ua = UserAgent(verify_ssl=False,use_cache_server=False).random headers = {'User-Agent':ua } page_text = requests.get(url=url,headers=headers).text#查看頁(yè)面源碼:發(fā)現(xiàn)所有圖片的src值都是一樣的。 #簡(jiǎn)單觀察會(huì)發(fā)現(xiàn)每張圖片加載都是通過(guò)jandan_load_img(this)這個(gè)js函數(shù)實(shí)現(xiàn)的。 #在該函數(shù)后面還有一個(gè)class值為img-hash的標(biāo)簽,里面存儲(chǔ)的是一組hash值,該值就是加密后的img地址 #加密就是通過(guò)js函數(shù)實(shí)現(xiàn)的,所以分析js函數(shù),獲知加密方式,然后進(jìn)行解密。 #通過(guò)抓包工具抓取起始url的數(shù)據(jù)包,在數(shù)據(jù)包中全局搜索js函數(shù)名(jandan_load_img),然后分析該函數(shù)實(shí)現(xiàn)加密的方式。 #在該js函數(shù)中發(fā)現(xiàn)有一個(gè)方法調(diào)用,該方法就是加密方式,對(duì)該方法進(jìn)行搜索 #搜索到的方法中會(huì)發(fā)現(xiàn)base64和md5等字樣,md5是不可逆的所以?xún)?yōu)先考慮使用base64解密 #print(page_text)tree = etree.HTML(page_text) #在抓包工具的數(shù)據(jù)包響應(yīng)對(duì)象對(duì)應(yīng)的頁(yè)面中進(jìn)行xpath的編寫(xiě),而不是在瀏覽器頁(yè)面中。 #獲取了加密的圖片url數(shù)據(jù) imgCode_list = tree.xpath('//span[@class="img-hash"]/text()') imgUrl_list = [] for url in imgCode_list:#base64.b64decode(url)為byte類(lèi)型,需要轉(zhuǎn)成strimg_url = 'http:'+base64.b64decode(url).decode()imgUrl_list.append(img_url)for url in imgUrl_list:filePath = url.split('/')[-1]urllib.request.urlretrieve(url=url,filename=filePath)print(filePath+'下載成功')-
問(wèn)題:往往在進(jìn)行大量請(qǐng)求發(fā)送的時(shí)候,經(jīng)常會(huì)報(bào)出這一樣的一個(gè)錯(cuò)誤:HTTPConnectionPool(host:XX)Max retries exceeded with url。
-
原因:
1.每次數(shù)據(jù)傳輸前客戶端要和服務(wù)器建立TCP連接,為節(jié)省傳輸消耗,默認(rèn)為keep-alive,即連接一次,傳輸多次。然而如果連接遲遲不斷開(kāi)的話,則連接池滿后則無(wú)法產(chǎn)生新的鏈接對(duì)象,導(dǎo)致請(qǐng)求無(wú)法發(fā)送。
2.ip被封
3.請(qǐng)求頻率太頻繁
-
解決:如果下列解決未生效,則可以嘗試再次執(zhí)行程序
1.設(shè)置請(qǐng)求頭中的Connection的值為close,表示每次請(qǐng)求成功后斷開(kāi)連接
2.更換請(qǐng)求ip
3.每次請(qǐng)求之間使用sleep進(jìn)行等待間隔
三.BeautifulSoup解析
環(huán)境安裝
需要將pip源設(shè)置為國(guó)內(nèi)源,阿里源、豆瓣源、網(wǎng)易源等
windows
(1)打開(kāi)文件資源管理器(文件夾地址欄中)
(2)地址欄上面輸入 %appdata%
(3)在這里面新建一個(gè)文件夾 pip
(4)在pip文件夾里面新建一個(gè)文件叫做 pip.ini ,內(nèi)容寫(xiě)如下即可
linux
(1)cd ~
(2)mkdir ~/.pip
(3)vi ~/.pip/pip.conf
(4)編輯內(nèi)容,和windows一模一樣
需要安裝:pip install bs4
bs4在使用時(shí)候需要一個(gè)第三方庫(kù),把這個(gè)庫(kù)也安裝一下
pip install lxml
基礎(chǔ)使用
使用流程:
導(dǎo)包:from bs4 import BeautifulSoup
使用方式:可以將一個(gè)html文檔,轉(zhuǎn)化為BeautifulSoup對(duì)象,然后通過(guò)對(duì)象的方法或者屬性去查找指定的節(jié)點(diǎn)內(nèi)容
(1)轉(zhuǎn)化本地文件:
soup = BeautifulSoup(open('本地文件'), 'lxml')(2)轉(zhuǎn)化網(wǎng)絡(luò)文件:
soup = BeautifulSoup('字符串類(lèi)型或者字節(jié)類(lèi)型', 'lxml')(3)打印soup對(duì)象顯示內(nèi)容為html文件中的內(nèi)容
基礎(chǔ)鞏固:
(1)根據(jù)標(biāo)簽名查找
- soup.a 只能找到第一個(gè)符合要求的標(biāo)簽
(2)獲取屬性
- soup.a.attrs 獲取a所有的屬性和屬性值,返回一個(gè)字典
- soup.a.attrs[‘href’] 獲取href屬性
- soup.a[‘href’] 也可簡(jiǎn)寫(xiě)為這種形式
(3)獲取內(nèi)容
- soup.a.string
- soup.a.text
- soup.a.get_text()
【注意】如果標(biāo)簽還有標(biāo)簽,那么string獲取到的結(jié)果為None,而其它兩個(gè),可以獲取文本內(nèi)容
(4)find:找到第一個(gè)符合要求的標(biāo)簽
- soup.find(‘a(chǎn)’) 找到第一個(gè)符合要求的
- soup.find(‘a(chǎn)’, title=“xxx”)
- soup.find(‘a(chǎn)’, alt=“xxx”)
- soup.find(‘a(chǎn)’, class_=“xxx”)
- soup.find(‘a(chǎn)’, id=“xxx”)
(5)find_all:找到所有符合要求的標(biāo)簽
- soup.find_all(‘a(chǎn)’)
- soup.find_all([‘a(chǎn)’,‘b’]) 找到所有的a和b標(biāo)簽
- soup.find_all(‘a(chǎn)’, limit=2) 限制前兩個(gè)
(6)根據(jù)選擇器選擇指定的內(nèi)容
select:soup.select('#feng')- 常見(jiàn)的選擇器:標(biāo)簽選擇器(a)、類(lèi)選擇器(.)、id選擇器(#)、層級(jí)選擇器
層級(jí)選擇器:
【注意】select選擇器返回永遠(yuǎn)是列表,需要通過(guò)下標(biāo)提取指定的對(duì)象
需求:使用bs4實(shí)現(xiàn)將詩(shī)詞名句網(wǎng)站中三國(guó)演義小說(shuō)的每一章的內(nèi)容爬去到本地磁盤(pán)進(jìn)行存儲(chǔ) http://www.shicimingju.com/book/sanguoyanyi.html
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #!/usr/bin/env python # -*- coding:utf-8 -*- import requests from bs4 import BeautifulSoupheaders={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',} def parse_content(url):#獲取標(biāo)題正文頁(yè)數(shù)據(jù)page_text = requests.get(url,headers=headers).textsoup = BeautifulSoup(page_text,'lxml')#解析獲得標(biāo)簽ele = soup.find('div',class_='chapter_content')content = ele.text #獲取標(biāo)簽中的數(shù)據(jù)值return contentif __name__ == "__main__":url = 'http://www.shicimingju.com/book/sanguoyanyi.html'reponse = requests.get(url=url,headers=headers)page_text = reponse.text#創(chuàng)建soup對(duì)象soup = BeautifulSoup(page_text,'lxml')#解析數(shù)據(jù)a_eles = soup.select('.book-mulu > ul > li > a')print(a_eles)cap = 1for ele in a_eles:print('開(kāi)始下載第%d章節(jié)'%cap)cap+=1title = ele.stringcontent_url = 'http://www.shicimingju.com'+ele['href']content = parse_content(content_url)with open('./sanguo.txt','w') as fp:fp.write(title+":"+content+'\n\n\n\n\n')print('結(jié)束下載第%d章節(jié)'%cap)總結(jié)
以上是生活随笔為你收集整理的python爬虫中三种数据解析方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python学习-使用制表符或者换行符来
- 下一篇: Python手动实现kmeans聚类和调