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