python實例:xpath爬蟲實例


 案例一:

某套圖網站,套圖以封面形式展現在頁面,需要依次點擊套圖,點擊廣告盤鏈接,最后到達百度網盤展示頁面。

這一過程通過爬蟲來實現,收集百度網盤地址和提取碼,采用xpath爬蟲技術

 

1、首先分析圖片列表頁,該頁按照更新先后順序暫時套圖封面,查看HTML結構。每一組“li”對應一組套圖。屬性href后面即為套圖的內頁地址(即廣告盤鏈接頁)。所以,我們先得獲取列表頁內所有的內頁地址(即廣告盤鏈接頁)

代碼如下:

import requests   倒入requests庫
from lxml import etree   倒入lxml 庫(沒有這個庫,pip install lxml安裝)
url = "https://www.xxxx.com/gc/"  請求地址
response = requests.get(url= url)   返回結果
wb_data = response.text   文本展示返回結果
html = etree.HTML(wb_data)   將頁面轉換成文檔樹
b = html.xpath('//ul[@class = "clearfix"]//@href')  這一步的意思是class“clearfix”下所有屬性為“href”賦值給“b”,因為我們的目標內容都展示在class“clearfix”下,且在href屬性后面
print(b)   打印b,這里的b是一個數組
print(b[0]) 打印b的第一項數據

執行結果:成功返回所有內頁

 

2、打開內頁(即廣告盤鏈接頁),獲取廣告盤地址。下圖紅色箭頭,還不是真正的百度盤頁,需要點擊后才可以看的到百度盤的地址。所以這一步驟,只需要抓取紅色箭頭內容地址;

 

代碼如下:

url = "https://www.xxxx.com/gc/toutiao/87098.html"
response = requests.get(url= url)
wb_data = response.text # 將頁面轉換成文檔樹
html = etree.HTML(wb_data)
b = html.xpath('//div[@class = "pictext"]//@href')
c=b[1]      #需要注意的地方,class = "pictext"下有兩個href,我們只需要第一個href的值,所以返回值再賦值給c且取第二項數據
print(c)

執行結果:成功返回所有內頁

 

3、獲取到廣告盤地址,接下來要打開該地址,抓百度盤真實地址。鏈接和提取碼在兩個不同的元素中,所有最后返回兩組數據。

 

 

代碼如下:

url = "http://xxx.la/xam9I6"
response = requests.get(url= url)
wb_data = response.text
# 將頁面轉換成文檔樹
html = etree.HTML(wb_data)
b = html.xpath('//tr/td/text()')
c=b[6]#提取碼
d = html.xpath('//tr//@href')#百度地址
print(c)
print(d)

注意,這里html.xpath寫法與上面有些區別,目標元素的上級沒有class,只能模糊取值

比如提取碼的HTML結構如下圖,結構為//tr/td/,單/代表父節點下的子節點,雙/代表父節點后的子孫節點。提取碼為tr的子節點。但是這個結構下有很多組數據,最后輸出一個數組b(看上面代碼b)。如此,我們找到提取碼位於數組序列,賦值給c(看上面代碼c),這樣獲得了真實的百度盤地址

網盤地址則因為有href屬性,所以好爬去一些,注意/的數量即可

 

4、把以上步驟拼成一個腳本,這里就涉及到函數和函數之間的傳參,還有循環的問題。代碼直接貼出來

 

# -*-coding:utf8-*-
# encoding:utf-8

import requests
from lxml import etree
import os
import sys

path = os.path.abspath(os.path.dirname(sys.argv[0]))

firstlink = "https://www.xxx.com/gc/qt/xxx.html"
AA=["https://www.xxx.com/gc/",
   "https://www.xxx.com/gc/index_2.html",
   "https://www.xxx.com/gc/index_3.html",
    "https://www.xxx.com/gq/",
    "https://www.xxx.com/gq/index_2.html",
    "https://www.xxx.com/gq/index_3.html",
    "https://www.xxx.com/gq/index_4.html"]

#第1步,獲取每一頁所有的資源地址,地址格式“https://www.xxx.com/gq/mistar/mistar300.html”
def stepa (AA):
    lit=[]
    for url in AA:
        response = requests.get(url=url)
        wb_data = response.text
        # 將頁面轉換成文檔樹
        html = etree.HTML(wb_data)
        a = html.xpath('//ul[@class = "clearfix"]//@href')
        lit.append(a)
    return(lit) 
alllink = stepa(AA)

#第2步,獲取的地址,循環讀取打開,從而獲取百度網盤信息
def stepb(alllink,firstlink):
    for list in alllink:
        for url in list:
            if url in firstlink:
                continue
            elif "www" in url:
                url2 = url
            else:
                url2 ="https://www.xxx.com" +url
            response = requests.get(url=url2)
            wb_data = response.text # 將頁面轉換成文檔樹
            html = etree.HTML(wb_data)
            b = html.xpath('//div[@class = "pictext"]//@href')
            g = html.xpath('//div[@class = "pictext"]/text()')
            c = b[1]#地址(廣告盤地址或者百度盤地址)地址格式“http://xxx.la/Tm1R2T“或者”https://pan.baidu.com/s/xxx-xxx-azplbTIQ“
            h = g[-1]
            i=h[14:18]#提取碼(獲取到的提取碼打印出來的是亂碼,如果獲取到內容不正確,優先考慮是這里的問題)
            test3=c+i#把鏈接和提取碼拼接成一條數據
 #下面的條件判斷是解決獲取鏈接不一致的問題,本來通過第一步驟獲取的套圖頁,需要進一步點擊廣告頁獲取百度地址,有些資源不需要獲取廣告盤地址,點擊后直接是百度地址
 # 所以做了判斷,如果是百度地址,直接寫入文檔,如果是廣告盤地址,則打開廣告盤地址,再獲取百度盤地址寫入文檔           
            if "pan.baidu.com" in c:
                with open(path+'\\1.txt', 'a',encoding='utf-8') as w:
                    w.write('\n'+test3)
                    w.close()
            else:
                #獲取到廣告頁地址
                url3 = c
                response = requests.get(url=url3)
                wb_data = response.text
                # 將頁面轉換成文檔樹
                html = etree.HTML(wb_data)
                d = html.xpath('//tr/td/text()')
                #print(d)
                e=d[6]#獲取提取碼
                f = html.xpath('//tr//@href')#獲取地址
                test = e[-5:]#提取碼值只保留提取碼(4位)
                test2 = f[-1]#鏈接只保留鏈接內容,去掉前后['']
                test3=test2+test#把鏈接和提取碼拼接成一條數據
                print(test3)
                with open(path+'\\1.txt', 'a',encoding='utf-8') as w:
                    w.write('\n'+test3)
                    w.close()
stepb(alllink,firstlink)

#第3步:提示爬取完成
def over():
    print("ok")
over()   

 

 需要注意的地方:

1、return的用法,如果想把函數生成的值傳給后面的函數用,就需要返回這個值,如def stepa 里定義的a為爬去的套圖封面地址(通過打開這個地址進行下一步),就需要return(a)返回a的值,否則執行后無數據

2、Continue的應用,因為第一個套圖地址打開的內容沒有目標內容,這樣找不到元素會報錯,所以需要讀取套圖地址的時候要跳過第一個地址。加一個if判斷,當第一個地址等於事先定義好的非正常地址的時候,跳過這個循環

 

打印結果:

 

 

 案例二:

爬取豆瓣的讀書的評論

分析html,評論存儲放在標紅色元素位置,且觀察結構,其他評論都存儲在li節點的相同位置

所以,xpath的解析對象為//*[@id="comments"]//div[2]/p/span

前面的實例講過"//" 代表從當前節點選取子孫節點,這里就可以直接跳過li節點,直接選擇li后的div[2]/p/span內容

代碼如下:

# -*-coding:utf8-*-
# encoding:utf-8

import requests
from lxml import etree

firstlink = "https://book.douban.com/subject/30172069/comments/hot?p=6"

def stepa (firstlink):
    response = requests.get(url=firstlink)
    wb_data = response.text
    html = etree.HTML(wb_data)
    a = html.xpath('//*[@id="comments"]//div[2]/p/span')
    print(a)
stepa (firstlink)

運行代碼,打印出來的結果如下圖,沒有得到想要的評論內容

后來發現,想要獲取內容,必須以文本的形式輸出,即xpath的解析對象為//*[@id="comments"]//div[2]/p/span/text()

修改后的代碼

 

# -*-coding:utf8-*-
# encoding:utf-8

import requests
from lxml import etree

firstlink = "https://book.douban.com/subject/30172069/comments/hot?p=6"

def stepa (firstlink):
    response = requests.get(url=firstlink)
    wb_data = response.text
    html = etree.HTML(wb_data)
    a = html.xpath('//*[@id="comments"]//div[2]/p/span/text()')
    print(a)
stepa (firstlink)

執行一下,內容來了

 

參考地址:https://cuiqingcai.com/5545.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM