數據解析方式之一:xpath
使用流程:
- 下載:pip install lxml
- 導包:from lxml import etree
- 創建etree對象進行指定數據的解析
本地:etree=etree.parse('本地文件路徑')
etree.xpath('xpath表達式')
網絡:etree=etree.HTML('網絡請求到的頁面數據')
etree.xpath('xpath表達式')
xpath插件:火狐瀏覽器右上角——>附加組件——>搜索Try XPath——>添加即可!

案例:
test.html
<html lang="en"> <head> <meta charset="UTF-8" /> <title>測試</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語法練習:
from lxml import etree #xpath函數返回的總是一個列表 #創建etree對象進行指定數據解析 tree = etree.parse('./test.html')#./表示當前路徑 #屬性定位:根據指定的屬性定位到指定的節點標簽 #tree.xpath('//div[@class="song"] ')#//表示相對路徑,所有子代節點,不用考慮是否直接子節點 #層級索引定位 #tree.xpath('//div[@class="tang"]/ul/li[2]/a') #邏輯定位 #tree.xpath('//a[@href="" and @class="du"]') #模糊查詢 #tree.xpath('//div[contains(@class, "ng")]') #tree.xpath('//div[starts-with(@class, "ta")]') #取文本 #tree.xpath('//div[@class="song"]/p[1]/text()') #/text()獲取當前標簽中直系存儲的文本數據 #tree.xpath('//div[@class="tang"]//text()') #//text()獲取某一個標簽下所有子標簽中存儲的文本數據 #取屬性 # tree.xpath('//div[@class="tang"]//li[2]/a/@href') #/表示絕對路徑,從根節點選取 #.表示選取當前節點 #..表示選取當前節點的父節點 #@表示 選取屬性
需求:利用xpath爬取經典段子網內容
1 import requests 2 from lxml import etree 3 #指定url 4 url='https://ishuo.cn/yulu' 5 #自定義頭信息 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0' 8 } 9 #發起get請求,返回響應對象 10 response=requests.get(url=url,headers=headers) 11 #獲取頁面數據 12 page_data=response.text 13 #數據解析 14 tree=etree.HTML(page_data) 15 #注:Element類型的對象可以繼續調用xpath函數,對該對象表示的局部內容進行指定內容的解析 16 li_list=tree.xpath('//div[@id="content"]/div[2]/ul/li') 17 #不要把文件放在循環體內,浪費資源 18 f=open('./duan.txt','w',encoding='utf-8') 19 for li in li_list: 20 content=li.xpath('./div[@class="content"]//text()')[0] 21 f.write(content+'\n\n')
數據解析之二:正則表達式
常用正則練習:
#提取出python key="javapythonc++php" re.findall('python',key)[0] #提取出hello world key="<html><h1>hello world<h1></html>" re.findall('<h1>hello world<h1>',key)[0] #提取170 string = '我喜歡身高為170的女孩' re.findall('\d+',string) #提取出http://和https:// key='http://www.baidu.com and https://boob.com' re.findall('https{0,1}',key) #提取出hit. key='bobo@hit.edu.com' re.findall('h.*?\.',key) #貪婪模式:根據正則表達式盡可能多的提取出數據 #匹配sas和saas key='saas and sas and saaas' re.findall('sa{1,2}s',key) #匹配出i開頭的行 re.S(基於單行) re.M(基於多行) string = '''fall in love with you i love you very much i love she i love her''' re.findall('^i.*',string,re.M) #匹配全部行 string = """<div>靜夜思 窗前明月光 疑是地上霜 舉頭望明月 低頭思故鄉 </div>""" re.findall('<div>.*</div>',string,re.S)
練習:需求是使用正則對糗事百科的圖片數據下載
1 import requests 2 import re 3 import os 4 #指定url 5 url = 'https://www.qiushibaike.com/pic/' 6 headers={ 7 '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', 8 } 9 #發起請求 10 response = requests.get(url=url,headers=headers) 11 #獲取頁面數據 12 page_text = response.text 13 #數據解析(該列表中存儲的就是當前頁面源碼中所有的圖片鏈接) 14 img_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>',page_text,re.S) 15 #創建一個存儲圖片數據的文件夾 16 if not os.path.exists('./imgs'): 17 os.mkdir('imgs') 18 for url in img_list: 19 #將圖片的url進行拼接,拼接成一個完成的url 20 img_url = 'https:' + url 21 #持久化存儲:存儲的是圖片的數據,並不是url。 22 #獲取圖片二進制的數據值 23 img_data = requests.get(url=img_url,headers=headers).content 24 imgName = url.split('/')[-1] 25 imgPath = 'imgs/'+imgName 26 with open(imgPath,'wb') as fp: 27 fp.write(img_data) 28 print(imgName+'寫入成功')
數據解析之三:BS4
python獨有。簡單便捷和高效。
環境安裝:
需要將pip源設置為國內源,阿里源、豆瓣源、網易源等
Windows:
(1)打開文件資源管理器(文件夾地址欄中)
(2)地址欄上面輸入 %appdata%
(3)在這里面新建一個文件夾 pip
(4)在pip文件夾里面新建一個文件叫做 pip.ini ,內容寫如下即可
[global] timeout = 6000 index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com
需要安裝:pip install bs4
bs4在使用時候需要一個第三方庫,把這個庫也安裝一下 pip install lxml
代碼的使用流程:將html文檔轉換成Beautiful對象,然后調用該對象中的屬性和方法進行html文檔指定內容的定位查找。
導包:from bs4 import BeautifulSoup 創建Beautiful對象:
如果html文檔的來源是來源於本地:
Beautiful('open('本地的html文件')','lxml')
如果html是來源於網絡
Beautiful(‘網絡請求到的頁面數據’,‘lxml’)
屬性和方法:
(1)根據標簽名查找
- soup.a 只能找到第一個符合要求的標簽
(2)獲取屬性
- soup.a.attrs 獲取a所有的屬性和屬性值,返回一個字典
- soup.a.attrs['href'] 獲取href屬性
- soup.a['href'] 也可簡寫為這種形式
(3)獲取內容
- soup.a.string /text()
- soup.a.text //text()
- soup.a.get_text() //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選擇器(#)、層級選擇器
- 層級選擇器:
div .dudu #lala .meme .xixi 下面好多級 div//img
div > p > a > .lala 只能是下面一級 div/img
【注意】select選擇器返回永遠是列表,需要通過下標提取指定的對象
BS4語法練習:
from bs4 import BeautifulSoup fp = open('text.html') soup = BeautifulSoup(fp,'lxml') #根據標簽名進行查找 #soup.div #獲取標簽屬性值 #soup.a['href'] #獲取內容 #soup.p.string #獲取符合要求的標簽 #soup.find('div',class_="tang") #soup.findAll('a',limit=2) #select函數的層級選擇器: #soup.select('div li')
練習:需求是利用BS4爬取古詩文網中三國小說的標題和內容
1 import requests 2 from bs4 import BeautifulSoup 3 url = 'http://www.shicimingju.com/book/sanguoyanyi.html' 4 headers={ 5 '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', 6 } 7 #根據url獲取頁面內容中指定的標題所對應的文章內容 8 def get_content(url): 9 content_page = requests.get(url=url,headers=headers).text 10 soup = BeautifulSoup(content_page,'lxml') 11 div = soup.find('div',class_='chapter_content') 12 return div.text 13 page_text = requests.get(url=url,headers=headers).text 14 #數據解析 15 soup = BeautifulSoup(page_text,'lxml') 16 #a_list列表中存儲的是一系列的a標簽對象 17 a_list = soup.select('.book-mulu > ul > li > a') 18 #type(a_list[0]) 19 #注意:Tag類型的對象可以繼續調用響應的解析屬性和方法進行局部數據的解析 20 fp = open('./sanguo.txt','w',encoding='utf-8') 21 for a in a_list: 22 #獲取了章節的標題 23 title = a.string 24 content_url = 'http://www.shicimingju.com'+a['href'] 25 print(content_url) 26 #獲取章節的內容 27 content = get_content(content_url) 28 fp.write(title+':'+content+"\n\n\n") 29 print('寫入一個章節內容')
