上?章中, 我們基本上掌握了抓取整個??的基本技能。 但是呢, ?多數情況下, 我們并不需要整個??的內容, 只是需要那么??部分。怎么辦呢? 這就涉及到了數據提取的問題。
本課程中, 提供三種解析?式:
這三種?式可以混合進?使?, 完全以結果做導向, 只要能拿到你想要的數據。 ?什么?案并不重要。 當你掌握了這些之后。 再考慮性能的問題。
XPath是??在 XML ?檔中查找信息的語?, XPath可?來在 XML?檔中對元素和屬性進?遍歷,?我們熟知的HTML恰巧屬于XML的?個?集,所以完全可以?xpath去查找html中的內容。
?先, 先了解?個概念:
在上述html中,
1. book, id, name, price....都被稱為節點.
2. Id, name, price, author被稱為book的?節點
3. book被稱為id, name, price, author的?節點
4. id, name, price,author被稱為同胞節點
OK~ 有了這些基礎知識后, 我們就可以開始了解xpath的基本語法了
在python中想要使?xpath,需要安裝lxml模塊。
pip install lxml
?法:
1. 將要解析的html內容構造出etree對象.
2. 使?etree對象的xpath()?法配合xpath表達式來完成對數據的提取
from lxml import etree
html="""
<book>
<id>1</id>
<name>野花遍地?</name>
<price>1.23</price>
<nick>臭?腐</nick>
<author>
<nick id="10086">周?強</nick>
<nick id="10010">周芷若</nick>
<nick class="joy">周杰倫</nick>
<nick class="jolin">蔡依林</nick>
<div>
<nick>惹了</nick>
</div>
</author>
<partner>
<nick id="ppc">胖胖陳</nick>
<nick id="ppbc">胖胖不陳</nick>
</partner>
</book>
"""
et=etree.XML(html)
# 根據節點進?搜索
# result=et.xpath("/book")
# result=et.xpath("/book/id") # /在開頭表示?檔最開始, /在中間表示??
# result=et.xpath("/book//nick") # //表示后代
result=et.xpath("/book/*/nick") # *表示通配符
print(result)
xpath如何提取屬性信息. 我們上?段真實的HTML來給各位講解?下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<ul>
<li><a href="http://www.baidu.com">百度
</a></li>
<li><a href="http://www.google.com">?
歌</a></li>
<li><a href="http://www.sogou.com">搜狗
</a></li>
</ul>
<ol>
<li><a href="feiji">?機</a></li>
<li><a href="dapao">?炮</a></li>
<li><a href="huoche">??</a></li>
</ol>
<div class="job">李嘉誠</div>
<div class="common">胡辣湯</div>
</body>
</html>
from lxml import etree
tree=etree.parse("1.html")
result=tree.xpath("/html/body/ul/li/a/@href")
print(result)
result=tree.xpath("/html/body/ul/li")
for li in result:
print(li.xpath("./a/@href")) # 局部解析
result=tree.xpath("//div[@class='job']/text()")
# [@class='xxx']屬性選取 text()獲取?本
print(result)
實戰案例:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
import requests
if __name__=="__main__":
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3884.400 QQBrowser/10.8.4560.400'}
url="https://bj.58.com/ershoufang/"
page_text=requests.get(url,headers=headers).text
tree=etree.HTML(page_text)
titles=tree.xpath("//h3/text()")
for title in titles:
print(title)
?
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
import requests
import os
if __name__=="__main__":
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3884.400 QQBrowser/10.8.4560.400'}
url="https://pic.netbian.com/4kfengjing/"
page_text=requests.get(url,headers=headers).text.encode("ISO-8859-1")
tree=etree.HTML(page_text)
li_list=tree.xpath('//div[@class="slist"]//li')
if not os.path.exists("./piclibs"):
os.mkdir('./piclibs')
for li in li_list:
img_src='https://pic.netbian.com/'+li.xpath('./a/img/@src')[0]
# print()
img_name=li.xpath('./a/img/@alt')[0]+'.jpg'
# print(img_name,img_src)
img_data=requests.get(url=img_src,headers=headers).content
img_path="piclibs/"+img_name
with open(img_path,"wb") as fp:
fp.write(img_data)
print(img_name,"下載成功")
?
三、全國城市名稱爬取
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
import requests
import os
if __name__=="__main__":
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3884.400 QQBrowser/10.8.4560.400'}
url="https://www.aqistudy.cn/historydata/"
page_text=requests.get(url,headers=headers).text
tree=etree.HTML(page_text)
#全部城市
all_city_list=tree.xpath('//div[@class="bottom"]//li')
all_city_names=[]
for li in all_city_list:
city_name=li.xpath("./a/text()")[0]
all_city_names.append(city_name)
for city in all_city_names:
print(city)
# print(all_city_names)
#熱門城市
# hot_city_names=[]
# hot_city_list=tree.xpath('//div[@class="hot"]//li')
# for li in hot_city_list:
# city_name=li.xpath("./a/text()")[0]
#
# hot_city_names.append(city_name)
# print(hot_city_names)
?
關注我:帶你從零開始學爬蟲。
語言是一種古老且廣泛使用的編程語言,它擁有眾多第三方庫,為開發者提供了各種功能,從數據處理到網絡通信,再到圖形界面等。以下是一些流行的C語言第三方庫的詳細介紹:
這些庫只是C語言生態中的一部分,每個庫都有其特定的用途和優勢,為C語言開發者提供了強大的工具來創建高效、可靠的應用程序。這些庫的源代碼通常都是開放的,可以自由地使用、修改和分發,為C語言開發者提供了豐富的資源。
除了上述的庫,還有許多其他的C語言第三方庫,如用于網絡編程的libcurl、用于圖像處理的OpenCV、用于數學計算的GNU MP等。這些庫各自都有其特點和用途,可以根據具體的應用場景選擇合適的庫。
在C語言編程中,選擇合適的第三方庫可以幫助開發者提高開發效率,減少重復造輪子的工作,同時也可以提高應用程序的性能和可靠性。使用第三方庫還可以使應用程序更加模塊化,便于維護和升級。
然而,使用第三方庫也需要考慮到一些問題,如庫的兼容性、穩定性、安全性等。因此,在選擇第三方庫時,應該盡量選擇成熟、活躍、社區支持良好的庫,并對其進行充分的測試和驗證。
總之,C語言擁有豐富的第三方庫資源,這些庫為C語言開發者提供了強大的支持和便利。掌握這些庫的使用方法和技巧,可以幫助開發者更好地應對各種編程挑戰,提高開發效率和應用程序質量。
xml是基于 libxml2解析庫的Python封裝。libxml2是使用C語言編寫的,解析速度很好,不過安裝起來稍微有點復雜。安裝說明可以參考(http: //Lxml.de/installation.html),在CentOS7上中文安裝說明(http://www.cjavapy.com/article/64/),使用lxml庫來解析網絡爬蟲抓取到的HTML是一種非常高效的方式。lxml的html模塊特別適合處理HTML內容,它可以快速解析大型HTML文件,并提供XPath和CSS選擇器來查詢和提取數據。
參考文檔:https://www.cjavapy.com/article/65/
從網絡上抓取到的html的內容,有可能都是標準寫法,標簽什么的都閉合,屬性也是標準寫法,但是有可能有的網站的程序員不專業,這樣抓到的html解析就有可能有問題,因此,解析時先將有可能不合法的html解析為統一的格式。避免為后續的解析造成困擾。
1、lxml.html
lxml.html是專門用于解析和處理HTML文檔的模塊。它基于lxml.etree,但是為HTML文檔的特點做了優化。lxml.html能夠處理不良形式的HTML代碼,這對于解析和爬取網頁尤其有用。
>>> import lxml.html
>>> broken_html='<ul class="body"><li>header<li>item</ul>'
>>> tree=lxml.html.fromstring(broken_html) #解析html
>>> fixed_html=lxml.html.tostring(tree,pretty_print=True)
>>> print fixed_html
<ul class="body">
<li>header</li>
<li>item</li>
</ul>
2、lxml.etree
lxml.etree是lxml庫中用于處理XML文檔的模塊。它基于非常快的XML解析庫libxml2,提供了一個類似于標準庫xml.etree.ElementTreeAPI的接口,但是在性能和功能性方面要更加強大。lxml.etree支持XPath、XSLT、和Schema驗證等高級XML特性。
>>> import lxml.etree
>>> broken_html='<ul class="body"><li>header<li>item</ul>'
>>> tree=lxml.etree.fromstring(broken_html) #解析html
>>> fixed_html=lxml.etree.tostring(tree,pretty_print=True)
>>> print fixed_html
<ul class="body">
<li>header</li>
<li>item</li>
</ul>
通過以上可以看出,lxml可以正確解析兩側缺失的括號,并閉合標簽,但不會額外增加<html>和<body>標簽。
若在html中找到我們想要的內容,用lxml有幾種不同的方法,XPath選擇器類似Beautiful Soup的find()方法。CSS選擇器用法和jQuery中的選擇器類似。兩種選擇器都可以用來查找文檔中的元素,但它們各有特點和適用場景。XPath是一種在XML文檔中查找信息的語言。它可以用來遍歷XML文檔的元素和屬性。CSS選擇器通常用于選擇和操作HTML文檔中的元素。
1、XPath選擇器(/單斜杠表示絕對查找,//雙斜杠表示相對查找)
from lxml import etree
source_html="""
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
"""
html=etree.HTML(source_html)
print(html)
result=etree.tostring(html)#會對的html標簽進行補全
print(result.decode("utf-8"))
輸出結果:
<Element html at 0x39e58f0>
<html><body><div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</li></ul>
</div>
</body></html>
1)獲取某個標簽的內容(a標簽后不需要加斜杠,否則會報錯)
#第一種寫法
html=etree.HTML(source_html)
html_data=html.xpath('/html/body/div/ul/li/a')#絕對查找
#html_data=html.xpath('//li/a')#相對查找
print(html)
for i in html_data:
print(i.text)
輸出結果:
<Element html at 0x14fe6b8>
first item
second item
third item
fourth item
fifth item
#第二種寫法
#在要找的標簽后面加/text(),就是獲取標簽中的文本內容,結果中直接就是文本內容了,不用在通過text屬性獲取了。
html=etree.HTML(source_html)
html_data=html.xpath('/html/body/div/ul/li/a/text()')#絕對查找
#html_data=html.xpath('//li/a/text()')#相對查找
print(html)
for i in html_data:
print(i)
輸出結果:
<Element html at 0x128e3b7>
first item
second item
third item
fourth item
fifth item
2)獲取a標簽下的屬性
html=etree.HTML(source_html)
html_data=html.xpath('//li/a/@href') #相對查找
#html_data=html.xpath('/html/body/div/ul/li/a/@href') #絕對查找
for i in html_data:
print(i)
輸出結果:
link1.html
link2.html
link3.html
link4.html
link5.html
3)查找a標簽屬性等于link2.html的內容
html=etree.HTML(source_html)
html_data=html.xpath('/html/body/div/ul/li/a[@href="link2.html"]/text()')絕對查找
#html_data=html.xpath('//li/a[@href="link2.html"]/text()')#相對查找
print(html_data)
for i in html_data:
print(i)
輸出結果:
['second item']
second item
4)查找最后一個li標簽里的a標簽的href屬性
html=etree.HTML(source_html)
html_data=html.xpath('//li[last()]/a/text()')
print(html_data)
for i in html_data:
print(i)
輸出結果:
['fifth item']
fifth item
5)查找倒數第二個li標簽里a標簽的href屬性
html=etree.HTML(source_html)
html_data=html.xpath('//li[last()-1]/a/text()')
print(html_data)
for i in html_data:
print(i)
輸出結果:
['fourth item']
fourth item
6)查找某個標簽id屬性值等于value的標簽
//*[@id="value"]
7)使用chrome瀏覽器提取某個標簽的XPath
2、CSS選擇器(基本上和jQuery選擇器用法一樣)
選擇器 | 描述 |
* | 選擇所有標簽 |
a | 選擇<a>標簽 |
.link | 選擇所有class='link'的元素 |
a.link | 選擇class='link'的<a>標簽 |
a#home | 選擇id='home'的<a>標簽 |
a > span | 選擇父元素為<a>標簽的所有<span>子標簽 |
a span | 選擇<a>標簽內部的所有<span>標簽 |
使用示例:
>>> html="""<div>
<tr id="places_area_row" class="body">
<td>header</td>
<td class="w2p_fw">item1</td>
<td class="w2p_fw">item2</td>
<td class="w2p_fw">item3</td>
<td><tr><td class="w2p_fw">header</td>
<td class="w2p_fw">item4</td>
<td class="w2p_fw">item5</td>
<td class="w2p_fw">item6</td></tr></td>
</tr>
</div>"""
>>> tree=lxml.html.fromstring(html)
>>> td=tree.cssselect('tr#places_area_row > td.w2p_fw')[0]
>>> htmlText=td.text_content()
>>> print htmlText
item1
參考文檔:https://www.cjavapy.com/article/65/
?
*請認真填寫需求信息,我們會在24小時內與您取得聯系。