爬虫之数据解析的三种方式
一,正則表達(dá)式解析
re正則就不寫(xiě)了,前面已經(jīng)寫(xiě)入一篇很詳細(xì)的正則表達(dá)式模塊了~
而且,在爬蟲(chóng)中,下面兩種方式用的多一些~
正則表達(dá)式:https://www.cnblogs.com/peng104/p/9619801.html
大致用法:
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?src="(.*?)".*?name"><a'+'.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'+'.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S) items = re.findall(pattern, html)二,Xpath解析
簡(jiǎn)介及安裝
簡(jiǎn)介:XPath 是一門(mén)在 XML 文檔中查找信息的語(yǔ)言。XPath 可用來(lái)在 XML 文檔中對(duì)元素和屬性進(jìn)行遍歷。XPath 是 W3C XSLT 標(biāo)準(zhǔn)的主要元素,并且 XQuery 和 XPointer 都構(gòu)建于 XPath 表達(dá)之上。
安裝:pip install lxml
調(diào)用方法:
# 先導(dǎo)包 from lxml import etree# 將html文檔或者xml文檔轉(zhuǎn)換成一個(gè)etree對(duì)象,然后調(diào)用對(duì)象中的方法查找指定的節(jié)點(diǎn) # 1. 本地文件 tree = etree.parse(文件名) tree.xpath("xpath表達(dá)式")# 2. 網(wǎng)絡(luò)數(shù)據(jù) tree = etree.HTML(網(wǎng)頁(yè)內(nèi)容字符串) tree.xpath("xpath表達(dá)式")語(yǔ)法簡(jiǎn)介
先準(zhǔn)備一個(gè)HTML格式的字符串
html_doc = """ <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><div class="d1"><div class="d2"><p class="story"><a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and<a href="http://example.com/tillie" id="link3">Tillie</a></p></div><div><p id="p1">人生苦短</p><p id="p2">我用python</p></div> </div><div class="d3"><a href="http://www.baidu.com">baidu</a><p>百度</p> </div></body> </html> """ 變量準(zhǔn)備1,選取節(jié)點(diǎn)
nodename # 選取nodename節(jié)點(diǎn)的所有子節(jié)點(diǎn) xpath(‘//div’) # 選取了所有div節(jié)點(diǎn) / # 從根節(jié)點(diǎn)選取 xpath(‘/div’) # 從根節(jié)點(diǎn)上選取div節(jié)點(diǎn) // # 選取所有的當(dāng)前節(jié)點(diǎn),不考慮他們的位置 xpath(‘//div’) # 選取所有的div節(jié)點(diǎn) . # 選取當(dāng)前節(jié)點(diǎn) xpath(‘./div’) # 選取當(dāng)前節(jié)點(diǎn)下的div節(jié)點(diǎn) .. # 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn) xpath(‘..’) # 回到上一個(gè)節(jié)點(diǎn) @ # 選取屬性 xpath(’//@calss’) # 選取所有的class屬性#######################?例子?###################### ret=selector.xpath("//div") ret=selector.xpath("/div") ret=selector.xpath("./div") ret=selector.xpath("//p[@id='p1']") ret=selector.xpath("//div[@class='d1']/div/p[@class='story']")2,謂語(yǔ)
表達(dá)式 結(jié)果 xpath(‘/body/div[1]’) # 選取body下的第一個(gè)div節(jié)點(diǎn) xpath(‘/body/div[last()]’) # 選取body下最后一個(gè)div節(jié)點(diǎn) xpath(‘/body/div[last()-1]’) # 選取body下倒數(shù)第二個(gè)div節(jié)點(diǎn) xpath(‘/body/div[positon()<3]’) # 選取body下前兩個(gè)div節(jié)點(diǎn) xpath(‘/body/div[@class]’) # 選取body下帶有class屬性的div節(jié)點(diǎn) xpath(‘/body/div[@class=”main”]’) # 選取body下class屬性為main的div節(jié)點(diǎn) xpath(‘/body/div[@price>35.00]’) # 選取body下price元素值大于35的div節(jié)點(diǎn)#######################?例子?###################### ret=selector.xpath("//p[@class='story']//a[2]") ret=selector.xpath("//p[@class='story']//a[last()]")3,通配符
Xpath通過(guò)通配符來(lái)選取未知的XML元素
表達(dá)式 結(jié)果 xpath(’/div/*’) # 選取div下的所有子節(jié)點(diǎn) xpath(‘/div[@*]’) # 選取所有帶屬性的div節(jié)點(diǎn)#######################?例子?###################### ret=selector.xpath("//p[@class='story']/*") ret=selector.xpath("//p[@class='story']/a[@class]")4,取多個(gè)路徑
使用 “|” 運(yùn)算符可以選取多個(gè)路徑
表達(dá)式 結(jié)果 xpath(‘//div|//table’) # 選取所有的div和table節(jié)點(diǎn)#######################?例子?###################### ret=selector.xpath("//p[@class='story']/a[@class]|//div[@class='d3']") print(ret)5,Xpath軸
軸可以定義相對(duì)于當(dāng)前節(jié)點(diǎn)的節(jié)點(diǎn)集
軸名稱(chēng) 表達(dá)式 描述 ancestor xpath(‘./ancestor::*’) # 選取當(dāng)前節(jié)點(diǎn)的所有先輩節(jié)點(diǎn)(父、祖父) ancestor-or-self xpath(‘./ancestor-or-self::*’) # 選取當(dāng)前節(jié)點(diǎn)的所有先輩節(jié)點(diǎn)以及節(jié)點(diǎn)本身 attribute xpath(‘./attribute::*’) # 選取當(dāng)前節(jié)點(diǎn)的所有屬性 child xpath(‘./child::*’) # 返回當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn) descendant xpath(‘./descendant::*’) # 返回當(dāng)前節(jié)點(diǎn)的所有后代節(jié)點(diǎn)(子節(jié)點(diǎn)、孫節(jié)點(diǎn)) following xpath(‘./following::*’) # 選取文檔中當(dāng)前節(jié)點(diǎn)結(jié)束標(biāo)簽后的所有節(jié)點(diǎn) following-sibing xpath(‘./following-sibing::*’) # 選取當(dāng)前節(jié)點(diǎn)之后的兄弟節(jié)點(diǎn) parent xpath(‘./parent::*’) # 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn) preceding xpath(‘./preceding::*’) # 選取文檔中當(dāng)前節(jié)點(diǎn)開(kāi)始標(biāo)簽前的所有節(jié)點(diǎn) preceding-sibling xpath(‘./preceding-sibling::*’) # 選取當(dāng)前節(jié)點(diǎn)之前的兄弟節(jié)點(diǎn) self xpath(‘./self::*’) # 選取當(dāng)前節(jié)點(diǎn)6,功能函數(shù)
使用功能函數(shù)能夠更好的進(jìn)行模糊搜索
函數(shù) 用法 解釋 starts-with xpath(‘//div[starts-with(@id,”ma”)]‘) # 選取id值以ma開(kāi)頭的div節(jié)點(diǎn) contains xpath(‘//div[contains(@id,”ma”)]‘) # 選取id值包含ma的div節(jié)點(diǎn) and xpath(‘//div[contains(@id,”ma”) and contains(@id,”in”)]‘) # 選取id值包含ma和in的div節(jié)點(diǎn) text() xpath(‘//div[contains(text(),”ma”)]‘) # 選取節(jié)點(diǎn)文本包含ma的div節(jié)點(diǎn)Element對(duì)象
from lxml.etree import _Element for obj in ret:print(obj)print(type(obj)) # from lxml.etree import _Element''' Element對(duì)象class xml.etree.ElementTree.Element(tag, attrib={}, **extra)tag:string,元素代表的數(shù)據(jù)種類(lèi)。text:string,元素的內(nèi)容。tail:string,元素的尾形。attrib:dictionary,元素的屬性字典。#針對(duì)屬性的操作clear():清空元素的后代、屬性、text和tail也設(shè)置為None。get(key, default=None):獲取key對(duì)應(yīng)的屬性值,如該屬性不存在則返回default值。items():根據(jù)屬性字典返回一個(gè)列表,列表元素為(key, value)。keys():返回包含所有元素屬性鍵的列表。set(key, value):設(shè)置新的屬性鍵與值。#針對(duì)后代的操作append(subelement):添加直系子元素。extend(subelements):增加一串元素對(duì)象作為子元素。#python2.7新特性find(match):尋找第一個(gè)匹配子元素,匹配對(duì)象可以為tag或path。findall(match):尋找所有匹配子元素,匹配對(duì)象可以為tag或path。findtext(match):尋找第一個(gè)匹配子元素,返回其text值。匹配對(duì)象可以為tag或path。insert(index, element):在指定位置插入子元素。iter(tag=None):生成遍歷當(dāng)前元素所有后代或者給定tag的后代的迭代器。#python2.7新特性iterfind(match):根據(jù)tag或path查找所有的后代。itertext():遍歷所有后代并返回text值。remove(subelement):刪除子元素。 '''三,BeautifulSoup
簡(jiǎn)介及安裝
簡(jiǎn)介:
? ? Beautiful Soup提供一些簡(jiǎn)單的、python式的函數(shù)用來(lái)處理導(dǎo)航、搜索、修改分析樹(shù)等功能。
? ? 它是一個(gè)工具箱,通過(guò)解析文檔為用戶提供需要抓取的數(shù)據(jù),因?yàn)楹?jiǎn)單,所以不需要多少代碼就可以寫(xiě)出一個(gè)完整的應(yīng)用程序。
安裝:pip3 install beautifulsoup4
解析器:
? ??Beautiful Soup支持Python標(biāo)準(zhǔn)庫(kù)中的HTML解析器,還支持一些第三方的解析器,如果我們不安裝它,則 Python 會(huì)使用 Python默認(rèn)的解析器,lxml 解析器更加強(qiáng)大,速度更快。
官方文檔
簡(jiǎn)單使用
使用方式:可以將一個(gè)html文檔,轉(zhuǎn)化為BeautifulSoup對(duì)象,然后通過(guò)對(duì)象的方法或者屬性去查找指定的節(jié)點(diǎn)內(nèi)容
from bs4 import BeautifulSoup# 轉(zhuǎn)化本地文件 soup = BeautifulSoup(open('本地文件'), 'lxml')# 轉(zhuǎn)化網(wǎng)絡(luò)文件 soup = BeautifulSoup('字符串類(lèi)型或者字節(jié)類(lèi)型', 'lxml')# 從文檔中獲取所有文字內(nèi)容: print(soup.get_text())語(yǔ)法簡(jiǎn)介
# 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') 找到第一個(gè)符合要求的- soup.find('a', title="xxx")- soup.find('a', alt="xxx")- soup.find('a', class_="xxx")- soup.find('a', id="xxx") # 5.find_all:找到所有符合要求的標(biāo)簽- soup.find_all('a')- soup.find_all(['a','b']) 找到所有的a和b標(biāo)簽- soup.find_all('a', limit=2) 限制前兩個(gè) # 6.根據(jù)選擇器選擇指定的內(nèi)容select:soup.select('#feng')- 常見(jiàn)的選擇器:標(biāo)簽選擇器(a)、類(lèi)選擇器(.)、id選擇器(#)、層級(jí)選擇器- 層級(jí)選擇器:div .dudu #lala .meme .xixi 下面好多級(jí)div > p > a > .lala 只能是下面一級(jí)注意:select選擇器返回永遠(yuǎn)是列表,需要通過(guò)下標(biāo)提取指定的對(duì)象find_all()
先準(zhǔn)備一個(gè)HTML格式的字符串
html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p id="my p" class="title"><b id="bbb" class="boldest">The Dormouse's story</b> </p><p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p><p class="story">...</p> """ 變量準(zhǔn)備1,五種過(guò)濾器
字符串、正則表達(dá)式、列表、True、方法
from bs4 import BeautifulSoup soup=BeautifulSoup(html_doc,'lxml')#1、字符串:即標(biāo)簽名 print(soup.find_all('b'))#2、正則表達(dá)式 import re print(soup.find_all(re.compile('^b'))) #找出b開(kāi)頭的標(biāo)簽,結(jié)果有body和b標(biāo)簽#3、列表:如果傳入列表參數(shù),Beautiful Soup會(huì)將與列表中任一元素匹配的內(nèi)容返回.下面代碼找到文檔中所有<a>標(biāo)簽和<b>標(biāo)簽: print(soup.find_all(['a','b']))#4、True:可以匹配任何值,下面代碼查找到所有的tag,但是不會(huì)返回字符串節(jié)點(diǎn) print(soup.find_all(True)) for tag in soup.find_all(True):print(tag.name)#5、方法:如果沒(méi)有合適過(guò)濾器,那么還可以定義一個(gè)方法,方法只接受一個(gè)元素參數(shù) ,如果這個(gè)方法返回 True 表示當(dāng)前元素匹配并且被找到,如果不是則反回 False def has_class_but_no_id(tag):return tag.has_attr('class') and not tag.has_attr('id') print(soup.find_all(has_class_but_no_id))2、按照類(lèi)名查找
注意:關(guān)鍵字是class_,class_=value,value可以是五種選擇器之一
print(soup.find_all('a',class_='sister')) # 查找類(lèi)為sister的a標(biāo)簽 print(soup.find_all('a',class_='sister ssss')) # 查找類(lèi)為sister和sss的a標(biāo)簽,順序錯(cuò)誤也匹配不成功 print(soup.find_all(class_=re.compile('^sis'))) # 查找類(lèi)為sister的所有標(biāo)簽3、attrs
print(soup.find_all('p',attrs={'class':'story'}))4、text
值可以是:字符,列表,True,正則
print(soup.find_all(text='Elsie')) print(soup.find_all('a',text='Elsie'))5、limit參數(shù)
如果文檔樹(shù)很大那么搜索會(huì)很慢.如果我們不需要全部結(jié)果,可以使用 limit 參數(shù)限制返回結(jié)果的數(shù)量.效果與SQL中的limit關(guān)鍵字類(lèi)似,當(dāng)搜索到的結(jié)果數(shù)量達(dá)到 limit 的限制時(shí),就停止搜索返回結(jié)果
print(soup.find_all('a',limit=2))6、recursive
調(diào)用tag的 find_all() 方法時(shí),Beautiful Soup會(huì)檢索當(dāng)前tag的所有子孫節(jié)點(diǎn),如果只想搜索tag的直接子節(jié)點(diǎn),可以使用參數(shù) recursive=False .
print(soup.html.find_all('a')) print(soup.html.find_all('a',recursive=False))tag
像調(diào)用 find_all() 一樣調(diào)用tag find_all() 幾乎是Beautiful Soup中最常用的搜索方法,所以我們定義了它的簡(jiǎn)寫(xiě)方法. BeautifulSoup 對(duì)象和 tag 對(duì)象可以被當(dāng)作一個(gè)方法來(lái)使用~
這個(gè)方法的執(zhí)行結(jié)果與調(diào)用這個(gè)對(duì)象的 find_all() 方法相同~
# 下面兩行代碼是等價(jià)的: soup.find_all("a") soup("a")# 這兩行代碼也是等價(jià)的: soup.title.find_all(text=True) soup.title(text=True)find
find( name , attrs , recursive , text , **kwargs )
find_all() 方法將返回文檔中符合條件的所有tag,盡管有時(shí)候我們只想得到一個(gè)結(jié)果.比如文檔中只有一個(gè)<body>標(biāo)簽,那么使用 find_all() 方法來(lái)查找<body>標(biāo)簽就不太合適, 使用 find_all 方法并設(shè)置 limit=1 參數(shù)不如直接使用 find() 方法
下面兩行代碼是等價(jià)的:soup.find_all('title', limit=1) # [<title>The Dormouse's story</title>] soup.find('title') # <title>The Dormouse's story</title>唯一的區(qū)別是 find_all() 方法的返回結(jié)果是值包含一個(gè)元素的列表,而 find() 方法直接返回結(jié)果.
find_all() 方法沒(méi)有找到目標(biāo)是返回空列表, find() 方法找不到目標(biāo)時(shí),返回 None .
soup.head.title 是 tag的名字 方法的簡(jiǎn)寫(xiě).這個(gè)簡(jiǎn)寫(xiě)的原理就是多次調(diào)用當(dāng)前tag的 find() 方法:
soup.head.title # <title>The Dormouse's story</title> soup.find("head").find("title") # <title>The Dormouse's story</title>?
轉(zhuǎn)載于:https://www.cnblogs.com/peng104/p/10317601.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的爬虫之数据解析的三种方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《独家记忆》见面会高甜宠粉 张超现场解锁
- 下一篇: 梦到自己逮了好多大螃蟹