xpath、bs4總結(jié)

Xpath解析器:

  • 什么是XPath蚕礼?

XPath (XML Path Language) 是一門在 XML 文檔中查找信息的語言叶圃,可用來在 XML 文檔中對元素和屬性進(jìn)行遍歷。

  • 什么是XML?

XML 指可擴(kuò)展標(biāo)記語言(EXtensible Markup Language)
XML 是一種標(biāo)記語言勒魔,很類似 HTML
XML 的設(shè)計宗旨是傳輸數(shù)據(jù)甫煞,而非顯示數(shù)據(jù)
XML 的標(biāo)簽需要我們自行定義。
XML 被設(shè)計為具有自我描述性冠绢。
XML 是 W3C 的推薦標(biāo)準(zhǔn)

選取節(jié)點(diǎn)
XPath 使用路徑表達(dá)式來選取 XML 文檔中的節(jié)點(diǎn)或者節(jié)點(diǎn)集抚吠。這些路徑表達(dá)式和我們在常規(guī)的電腦文件系統(tǒng)中看到的表達(dá)式非常相似。

  • 下面列出了最常用的路徑表達(dá)式:

nodename :選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)弟胀。
/ :從根節(jié)點(diǎn)選取楷力。
// : 從匹配選擇的當(dāng)前節(jié)點(diǎn)選擇文檔中的節(jié)點(diǎn),而不考慮它們的位置孵户。
. : 選取當(dāng)前節(jié)點(diǎn)萧朝。
.. : 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。
@ : 選取屬性夏哭。
在下面的表格中检柬,我們已列出了一些路徑表達(dá)式以及表達(dá)式的結(jié)果:
bookstore :選取 bookstore 元素的所有子節(jié)點(diǎn)。
/bookstore : 選取根元素 bookstore竖配。注釋:假如路徑起始于正斜杠( / )何址,則此路徑始終代表到某元素的絕對路徑!
bookstore/book : 選取屬于 bookstore 的子元素的所有 book 元素进胯。
//book : 選取所有 book 子元素用爪,而不管它們在文檔中的位置。
bookstore//book : 選擇屬于 bookstore 元素的后代的所有 book 元素龄减,而不管它們位于 bookstore 之下的什么位置项钮。
//@lang :選取名為 lang 的所有屬性。

  • 小案例:
案例:使用XPath的爬蟲 現(xiàn)在我們用XPath來做一個簡單的爬蟲希停,我們嘗試爬取某個貼吧里的所有帖子烁巫,并且將該這個帖子里每個樓層發(fā)布的圖片下載到本地。

    import requests
    from lxml import etree
    import json

    class Tieba:

        def __init__(self,tieba_name):
            self.tieba_name = tieba_name #接收貼吧名
            #設(shè)置為手機(jī)端的UA,也可以是指為瀏覽器的UA
            self.headers = {"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"}

        def get_total_url_list(self):
            '''獲取所有的urllist'''
            url = "https://tieba.baidu.com/f?kw="+self.tieba_name+"&ie=utf-8&pn={}&"
            url_list = []
            for i in range(100): #通過循環(huán)拼接100個url
                url_list.append(url.format(i*50))
            return url_list #返回100個url的urllist

        def parse_url(self,url):
            '''一個發(fā)送請求宠能,獲取響應(yīng)亚隙,同時etree處理html'''
            print("parsing url:",url)
            response = requests.get(url,headers=self.headers,timeout=10) #發(fā)送請求
            html = response.content.decode() #獲取html字符串
            html = etree.HTML(html) #獲取element 類型的html
            return html

        def get_title_href(self,url):
            '''獲取一個頁面的title和href'''
            html = self.parse_url(url)
            li_temp_list = html.xpath("http://li[@class='tl_shadow']") #分組,按照li標(biāo)簽分組
            total_items = []
            for i in li_temp_list: #遍歷分組
                href = "https:"+i.xpath("./a/@href")[0] if len(i.xpath("./a/@href"))>0 else None
                text = i.xpath("./a/div[1]/span[1]/text()")
                text = text[0] if len(text)>0 else None
                item = dict(  #放入字典
                    href = href,
                    text = text
                )
                total_items.append(item)
            return total_items #返回一個頁面所有的item

        def get_img(self,url):
            '''獲取一個帖子里面的所有圖片'''
            html = self.parse_url(url) #返回elemet累心的html违崇,具有xpath方法
            img_list = html.xpath('//div[@data-class="BDE_Image"]/@data-url')
            img_list = [i.split("src=")[-1] for i in img_list] #提取圖片的url
            img_list = [requests.utils.unquote(i) for i in img_list]
            return img_list

        def save_item(self,item):
            '''保存一個item'''
            with open("teibatupian.txt","a") as f:
                f.write(json.dumps(item,ensure_ascii=False,indent=2))
                f.write("\n")

        def run(self):
            #1阿弃、找到了url規(guī)律诊霹,url list
            url_list = self.get_total_url_list()
            for url in url_list:
            #2、遍歷urllist 發(fā)送請求渣淳,獲得響應(yīng)脾还,etree處理html
            # 3、提取title入愧,href
                total_item = self.get_title_href(url)
                for item in total_item:
                    href = item["href"]
                    img_list = self.get_img(href) #獲取到了帖子的圖片列表
                    item["img"] = img_list
                    # 4鄙漏、保存到本地
                    print(item)
                    self.save_item(item)

    if __name__ == "__main__":
            tieba = Tieba("美女")
            tieba.run()

BeautifulSoup4解析器

和 lxml 一樣,Beautiful Soup 也是一個HTML/XML的解析器棺蛛,主要的功能也是如何解析和提取 HTML/XML 數(shù)據(jù)怔蚌。
lxml 只會局部遍歷,而Beautiful Soup 是基于HTML DOM的旁赊,會載入整個文檔桦踊,解析整個DOM樹,因此時間和內(nèi)存開銷都會大很多终畅,所以性能要低于lxml籍胯。
BeautifulSoup 用來解析 HTML 比較簡單,API非常人性化声离,支持CSS選擇器芒炼、Python標(biāo)準(zhǔn)庫中的HTML解析器,也支持 lxml 的 XML解析器术徊。
Beautiful Soup 3 目前已經(jīng)停止開發(fā)本刽,推薦現(xiàn)在的項(xiàng)目使用Beautiful Soup 4。使用 pip 安裝即可:pip install beautifulsoup4

四大對象種類
Beautiful Soup將復(fù)雜HTML文檔轉(zhuǎn)換成一個復(fù)雜的樹形結(jié)構(gòu),每個節(jié)點(diǎn)都是Python對象,所有對象可以歸納為4種:

  • Tag :Tag 通俗點(diǎn)講就是 HTML 中的一個個標(biāo)簽
  • NavigableString
  • BeautifulSoup:BeautifulSoup 對象表示的是一個文檔的內(nèi)容
  • Comment:Comment 對象是一個特殊類型的 NavigableString 對象赠涮,其輸出的內(nèi)容不包括注釋符號子寓。
  • 小案例
from bs4 import BeautifulSoup
import urllib
import json    # 使用了json格式存儲

def tencent():
    url = 'http://hr.tencent.com/'
    request = urllib.request.Request(url + 'position.php?&start=10#a')
    response =urllib.request.urlopen(request)
    resHtml = response.read()

    output =open('tencent.json','w')

    html = BeautifulSoup(resHtml,'lxml')

# 創(chuàng)建CSS選擇器
    result = html.select('tr[class="even"]')
    result2 = html.select('tr[class="odd"]')
    result += result2

    items = []
    for site in result:
        item = {}

        name = site.select('td a')[0].get_text()
        detailLink = site.select('td a')[0].attrs['href']
        catalog = site.select('td')[1].get_text()
        recruitNumber = site.select('td')[2].get_text()
        workLocation = site.select('td')[3].get_text()
        publishTime = site.select('td')[4].get_text()

        item['name'] = name
        item['detailLink'] = url + detailLink
        item['catalog'] = catalog
        item['recruitNumber'] = recruitNumber
        item['publishTime'] = publishTime

        items.append(item)

    # 禁用ascii編碼,按utf-8編碼
    line = json.dumps(items,ensure_ascii=False)

    output.write(line.encode('utf-8'))
    output.close()

if __name__ == "__main__":
    tencent()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末笋除,一起剝皮案震驚了整個濱河市斜友,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垃它,老刑警劉巖鲜屏,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異国拇,居然都是意外死亡洛史,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門酱吝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來也殖,“玉大人,你說我怎么就攤上這事务热∫涫龋” “怎么了己儒?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長捆毫。 經(jīng)常有香客問我闪湾,道長,這世上最難降的妖魔是什么冻璃? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任响谓,我火速辦了婚禮,結(jié)果婚禮上省艳,老公的妹妹穿的比我還像新娘。我一直安慰自己嫁审,他們只是感情好跋炕,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著律适,像睡著了一般辐烂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捂贿,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天纠修,我揣著相機(jī)與錄音,去河邊找鬼厂僧。 笑死扣草,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的颜屠。 我是一名探鬼主播辰妙,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼甫窟!你這毒婦竟也來了密浑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤粗井,失蹤者是張志新(化名)和其女友劉穎尔破,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浇衬,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡懒构,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了径玖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痴脾。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖梳星,靈堂內(nèi)的尸體忽然破棺而出赞赖,到底是詐尸還是另有隱情滚朵,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布前域,位于F島的核電站辕近,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏匿垄。R本人自食惡果不足惜移宅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望椿疗。 院中可真熱鬧漏峰,春花似錦、人聲如沸届榄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铝条。三九已至靖苇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間班缰,已是汗流浹背贤壁。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留埠忘,地道東北人脾拆。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像给梅,于是被迫代替她去往敵國和親假丧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容