Python爬蟲基礎練習(七)貓貓壁紙酷壁紙爬取
來自專欄 Python程序員28 人贊了文章
今天我們要爬取的依然是圖片,爬取的是貓貓壁紙酷網頁上的各種壁紙。
不過今天運用的是一個新的解析工具Xpath。所以我們先來了解一下xpath的用法。運行平台:WindowsPython版本:Python3.6IDE: Sublime Text其他:Chrome瀏覽器
簡述流程為:步驟1:了解Xpath的使用規則以及簡單實例步驟2:獲取到貓貓壁紙酷的各種壁紙集的鏈接步驟3:解析壁紙集鏈接並獲取到圖片鏈接步驟4:爬取圖片並保存Xpath是一門XML文檔中查找信息的語言,但同樣適用於HTML文檔的搜索。這裡我只簡單介紹一下Xpath的使用規則及示例。再通過實例簡單看下Xpath的用法。
text = """<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_acttve"><a href=link3.html">Third item</a></li><li class="item_0"><a href=link4.html">Fourth item</a></li><li class="item_1"><a href=link5.html">Five item</a></li></ul></div>"""
提取所有節點
from lxml import etreehtml = etree.HTML(text)result = html.xpath("//*")print(result)[<Element html at 0x2346afc5ec8>, <Element body at 0x2346afdf1c8>, <Element div at 0x2346b076b48>,<Element ul at 0x2346b076b88>, <Element li at 0x2346b076bc8>, <Element a at 0x2346b076c48>,<Element li at 0x2346b076c88>, <Element a at 0x2346b076cc8>, <Element li at 0x2346b076d08>, <Element a at 0x2346b076c08>, <Element li at 0x2346b076d48>, <Element a at 0x2346b076d88>, <Element li at 0x2346b076dc8>, <Element a at 0x2346b076e08>]
使用通配符匹配所有節點,返回形式為列表,每個元素都是Element類型,後面緊跟節點的名稱
提取指定節點名稱
from lxml import etreehtml = etree.HTML(text)result = html.xpath("//li")print(result)[<Element li at 0x2346b092088>, <Element li at 0x2346b0920c8>, <Element li at 0x2346b092108>, <Element li at 0x2346b092148>, <Element li at 0x2346b092188>]
這裡提取了所有li節點,提取指定節點時,直接在//後加上節點名稱即可
提取子節點
from lxml import etreehtml = etree.HTML(text)result = html.xpath("//li/a")result_1 = html.xpath("//ul/li")print(result_1)print(result)[<Element li at 0x2346b0921c8>, <Element li at 0x2346b092088>, <Element li at 0x2346b0920c8>, <Element li at 0x2346b092108>, <Element li at 0x2346b092148>][<Element a at 0x2346b04f7c8>, <Element a at 0x2346b076f48>, <Element a at 0x2346b076dc8>, <Element a at 0x2346b076e08>, <Element a at 0x2346b092048>]
通過在節點名稱後加上「/節點名稱」的方法可以返回當前節點的子節點,相應的父節點則是在子節點後加上「..」便能獲取到對應父節點。
提取匹配屬性的節點
from lxml import etreehtml = etree.HTML(text)result = html.xpath(//li[@class="item_0"])print(result)[<Element li at 0x2346aefeec8>, <Element li at 0x2346b076fc8>]
@為選取屬性,我們通過選取屬性為「class="item_0"」限制了匹配對象,這裡需要注意的是,class對應的屬性已經用雙引號括起來了,所以我們Xpath選擇的時候用單引號。
以上就是對於Xpath的簡單介紹了,如果想了解更多Xpath的知識的話,可以看看w3school的Xpath教程
接下來便可以利用上面所講的來爬取壁紙了。
我們直接用requests請求網頁http://www.wallcoo.com/new/index.html,查看返回結果吧。
這裡需要注意的是從網站解析編碼的那一行,我們把這一行注釋掉,看看網站返回的是什麼。
顯然返回的結果亂碼了。所以加上response.apparent_encoding很有必要的,可以從網站中分析出響應內容的編碼。
隨即我們便可以抓取各個壁紙集的鏈接後半部分,首先我們還是通過Chrome瀏覽器分析一下網頁。
可以看到我們要抓取的壁紙集鏈接就在li標籤的第三個href中但有的又只有兩個鏈接,這就不方便我們通過索引獲取到有效鏈接了。我們先將所有href獲取到吧。
這裡先介紹一個用於抓取HTML文檔Xpath的Chrome插件Xpath helper,Xpath helper可以支持點擊元素生成Xpath,如果我們要查找某一個,或者某一塊元素的xpath的路徑,可以按住移位,並移動到這一塊中,上面的框就會顯示這個元素的xpath的路徑,右邊則會顯示解析出的文本內容,並且我們可以自己改動的xpath路徑,程序也會自動的顯示對應的位置,可以很方便的幫助我們判斷我們xpath的語句是否書寫正確。比如我們這裡獲取壁紙集的鏈接
按下ctrl+shift+x啟動Xpath helper,然後右鍵檢查一個鏈接,根據右鍵檢查的結果,對照返回的源碼寫出Xpath,然後就可以看到右側返回了一系列滿足條件的href。但我們在使用Xpath helper的時候,需要注意有的網頁是動態載入的,所以requests.get返回的頁面可能與右鍵檢查得到的頁面不一樣,所以可能導致Xpath匹配不到節點信息。
可以看到Xpath爬取到的壁紙集鏈接有很多,但很多不是我們想要的鏈接,通過觀察發現,我們需要的壁紙集鏈接均以『html』結尾,而其他分類頁面則是『htm』結尾。所以我們可以通過endswith判斷是否以『html』結尾,如果是,則構建完整的壁紙集鏈接。
然後可以用同樣的方法從壁紙集詳情頁獲取到圖片的鏈接,但通過xpath獲取到的鏈接會通過列表返回,且類型為lxml.etree._Element
我們可以通過tagattrib ext三個不同的屬性來獲取我們需要的東西,tag會返回字元串格式的標籤名,attrib獲取到的是節點標籤的屬性,且會以字典形式返回,如下圖所示。text則是返迴文本。
如圖,我們便可以通過字典提取出其中的圖片部分的鏈接。然後拼接完整的圖片鏈接。拼接過程中我們可以先通過瀏覽器找到大圖的完整鏈接格式,然後對之前獲取得到的圖片鏈接加以切片得到大圖鏈接。
於是便獲取到頁面內所有的壁紙鏈接,複製一個鏈接在瀏覽器中檢查,看是否可以正確找到路徑,結果很好。
我們還可以通過構建索引頁鏈接的方法,獲取到更多頁的壁紙集,以及更多的壁紙鏈接,鏈接可以獲取到後,便能通過前面兩篇文章所說的方法保存至本地文件,這裡就不再保存了。
代碼如下:
import requestsfrom lxml import etreedef get_url_Page(url): # 構建請求頭 headers = {User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36} response = requests.get(url,headers=headers,timeout=10) if response.status_code == 200: # 從網站分析出響應內容的編碼 response.encoding = response.apparent_encoding # print(response.text) return response.text else: print("請求網頁失敗")def parse_url_Page(html): img_url = [] html_lxml = etree.HTML(html) # 抓取各個壁紙集的鏈接的後半部分 # 示例:/holiday/Sign_of_2013_New_Year/index.html links = html_lxml.xpath(//tr//ul/li/a/@href) # print(links) for link in links: if link.endswith(html): # 構建壁紙集完整鏈接 image_link = http://www.wallcoo.com + link # print(image_link) img_url.append(image_link) return img_urldef load_Image(image_info): for image_link in image_info: html = get_url_Page(image_link) image_lxml = etree.HTML(html) # 抓取圖片鏈接 返回的是一個列表 image_urls = image_lxml.xpath(//*[@id="thums"]/ul/li/a/img) # print(image_urls) for image_url in image_urls: # 圖片為lxml.etree._Element,所以要從元素中取出 # 取出的是字典,所以單獨取出圖片鏈接 # print(image_url.attrib) image_url = image_url.attrib[src] # 構建完整圖片鏈接 image = image_link[:-10] + images + image_url[1:-5] + .jpg print(image) def main(): image_info = [] beginPage = 0 # 起始頁 endPage = 2 # 結束頁 for page in range(beginPage,endPage+1): if page == 0: url = http://www.wallcoo.com/new/index.html else: url = http://www.wallcoo.com/new/index + str(page) + .html html = get_url_Page(url) image_info = parse_url_Page(html) load_Image(image_info)if __name__ == __main__: main()
推薦閱讀:
※python爬取網頁圖片
※case1: 爬取豆瓣top250排行榜的所有電影的信息
※python爬取搜狗熱搜榜
※Python爬蟲學習之(一)| 從零開始