(三)三種資料解析方式學習
阿新 • • 發佈:2018-12-24
資料解析三種方式
1 常用正則表示式回顧
單字元: . : 除換行以外所有字元 [] :[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(正則表示式, 替換內容, 字串) 對應練習# 1 提取出python ''' key = 'javapythonc++php' re.findall('python',key) re.findall('python',key)[0] ''' # 2 提取出 hello word ''' key = '<html><h1>hello word</h1></html>' print(re.findall('<h1>.*</h1>', key)) print(re.findall('<h1>(.*)</h1>', key)) print(re.findall('<h1>(.*)</h1>', key)[0])''' # 3 提取170 ''' key = '這個女孩身高170釐米' print(re.findall('\d+', key)[0]) ''' # 4 提取出http://和https:// ''' key = 'http://www.baidu.com and https://www.cnblogs.com' print(re.findall('https?://', key)) ''' # 5 提取出 hello ''' key = 'lalala<hTml>hello</HtMl>hahaha' # 輸出的結果<hTml>hello</HtMl> print(re.findall('<[hH][tT][mM][lL]>.*[/hH][tT][mM][lL]>',key)) ''' # 6 提取hit. 貪婪模式;儘可能多的匹配資料 ''' key = '[email protected]' # 加?是貪婪匹配,不加?是非貪婪匹配 print(re.findall('h.*?\.', key)) ''' # 7 匹配出所有的saas和sas ''' key = 'saas and sas and saaas' print(re.findall('sa{1,2}s',key)) ''' # 8 匹配出 i 開頭的行 ''' key = """fall in love with you i love you very much i love she i love her """ print(re.findall('^i.*', key, re.M)) ''' # 9 匹配全部行 ''' key = """ <div>細思極恐 你的隊友在看書, 你的閨蜜在減肥, 你的敵人在磨刀, 隔壁老王在練腰. </div> """ print(re.findall('.*', key, re.S)) '''
專案例項
需求1 :爬取糗事百科指定頁面的糗圖,並將其儲存到指定資料夾中
import re
import os
import requests
if not os.path.exists('qiutu'):
os.mkdir('qiutu')
url = 'https://www.qiushibaike.com/pic'
heards = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}
response = requests.get(url=url, headers=heards)
page_text = response.text
# 正則匹配出圖片的src
# <div class="thumb">
#
# <a href="/article/121360019" target="_blank">
# <img src="//pic.qiushibaike.com/system/pictures/12136/121360019/medium/0TOTENVGL8R9KQFD.jpg" alt="這位同學老哥千里送人頭">
# </a>
#
# </div>
img_url_list = re.findall('<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>', page_text, re.S)
for img_url in img_url_list:
img_url = "https:" + img_url
res = requests.get(url=img_url, headers = heards)
img = res.content
# 持久化處理
imgName = img_url.split('/')[-1]
filePath = './qiutu/' + imgName # ./qiutu/
with open(filePath, 'wb') as f:
f.write(img)
1 回顧:
<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>
練習
屬性定位:
#找到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
2 Xpath的使用
1.下載:pip install lxml
2.導包:from lxml import etree
3.將html文件或者xml文件轉換成一個etree物件,然後呼叫物件中的方法查詢指定的節點
3.1 本地檔案:tree = etree.parse(檔名)
tree.xpath("xpath表示式")
3.2 網路資料:tree = etree.HTML(網頁內容字串)
tree.xpath("xpath表示式")
專案例項
需求2:Xpath解析boss招聘網站
import os import requests from lxml import etree if not os.path.exists('boss'): os.mkdir('boss') job = input('請輸入job名') headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' } url = 'https://www.zhipin.com/job_detail/?' params = { 'query':job } response = requests.get(url=url, params=params, headers=headers) page_text = response.text # 解析 # 1 例項化一個etree物件,然後將頁面資料封裝到該物件 tree = etree.HTML(page_text) # 2 呼叫 etree 物件中的Xpath函式實現解析 li_list = tree.xpath('//*[@id="main"]/div/div[3]/ul/li') for el in li_list: url_list = el.xpath('./div/div[1]/h3/a/@href')[0] url = 'https://www.zhipin.com' + url_list # 第二頁面發請求 second_page = requests.get(url=url, headers=headers) second_page_detail = second_page.text # 建立第二頁面的tree tree1 = etree.HTML(second_page_detail) jobName = tree1.xpath('//div[@class="info-primary"]/div[2]/h1/text()')[0] detail = tree1.xpath('//div[@class="info-primary"]/p//text()')[0] company = tree1.xpath('//div[@class="info-company"]/h3/a/text()')[0] job_sec = tree1.xpath('//div[@class="job-sec"]/h3/text()')[0] job_sec_detail = tree1.xpath('//div[@class="job-sec"]/div/text()')[0] detail_total = jobName + '\n' + detail + '\n' + company + '\n' + job_sec + '\n' + job_sec_detail # 持久化 jobPath = './boss/' + jobName with open(jobPath, 'w', encoding='utf-8') as f: f.write(detail_total)
環境安裝
- 需要將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
- 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檔案中的內容
BeautifulSoup基礎操作
(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選擇器(#)、層級選擇器 - 層級選擇器: div .dudu #lala .meme .xixi 下面好多級 div > p > a > .lala 只能是下面一級 【注意】select選擇器返回永遠是列表,需要通過下標提取指定的物件
專案需求:使用bs4實現將詩詞名句網站中三國演義小說的每一章的內容爬去到本地磁碟進行儲存 http://www.shicimingju.com/book/sanguoyanyi.html
import requests from bs4 import BeautifulSoup headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' }
# 獲取內容函式 def get_content(url): res = requests.get(url=url, headers=headers).text soup = BeautifulSoup(res, 'lxml') return soup.find('div', class_='chapter_content').text # 第一次請求 url = 'http://www.shicimingju.com/book/sanguoyanyi.html' response = requests.get(url=url, headers=headers).text # Beautiful例項化 soup = BeautifulSoup(response, 'lxml') # 解析 list = soup.select('.book-mulu > ul > li > a') fp = open('sanguo.txt', 'w', encoding='utf-8') for li in list: title = li.text # 獲取標題 con_url = 'http://www.shicimingju.com' + li['href'] # 獲取url content = get_content(con_url) # 獲取標題下的內容(二次請求) fp.write(title + '\n' + content) # 寫入檔案 print(title+'被下載成功') fp.close()