用selenium自動加載瀏覽器下載圖片


上一篇用requests這個庫進行圖片的批量下載,只所以可以這樣做,是因為豆瓣提供的XHR的接口API,而且接口返回的數據類型為json格式,所以使用起來非常的方便,但是有時候我們需要分析html格式或xml格式的數據,從中提取需要的鏈接,再進行下載,這時候selenium就派上了用場。

一 人工下載海報

以下載甄子丹的海報為例,我們一般打開豆瓣電影網站:https://movie.douban.com/ 然后輸入關鍵詞甄子丹,然后再去下載海報。

二 自動下載處理思路

自動下載,我們需要能夠分析出網頁種海報圖片的具體地址,然后通過程序去下載。

2.1 xpath學習

這里通過xpath去搜尋圖片的地址,xpath是 XML Path Language的簡稱,原來用於搜索xml中的具體路徑的,同樣適用於搜尋html的元素,簡單語法說明下:
xpath基本語法
在python中,適用lxml庫可以將html轉成xpath對象,然后進行分析,非常方便,lxml庫可以對html未閉合的標簽元素做容錯處理。
看一個簡單的例子:

from lxml import etree

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-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.parse('test.html',etree.HTMLParser()) 
html = etree.HTML(text)
#轉成補全字節
r = etree.tostring(html,encoding='utf-8')
#打印補全結果
#print(r.decode('utf-8'))
#搜下下面所有為li的子孫節點
resultLi = html.xpath("//li")
print("//li: "+ str(resultLi))
#搜尋li節點下面的a節點,並取href屬性的值
reLiA = html.xpath("//li/a/@href")
print("//li/a/@href :"+ str(reLiA))
#獲取href的屬性值為link2.html的a節點的上層節點的class熟悉值
reClass=html.xpath('//a[@href="link2.html"]/../@class')
print('//a[@href="link2.html"]/../@class :'+ str(reClass))
#搜尋li節點下面的a節點,並取href屬性的值
reLiText = html.xpath("//li/a/text()")
print("//li/a/text() :"+ str(reLiText))

上述代碼本來是一段,在markdown中解析有問題,改成兩段了。
打印結果如下:

//li: [<Element li at 0x1cb14b89908>, <Element li at 0x1cb14b89988>, <Element li at 0x1cb14b899c8>, <Element li at 0x1cb14b89a08>, <Element li at 0x1cb14b89a48>]
//li/a/@href :['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']
//a[@href="link2.html"]/../@class :['item-1']
//li/a/text() :['first item', 'second item', 'third item', 'fourth item', 'fifth item']

2.2 圖片的xpath路徑提取

通過上面的例子,xpath的語法雖然不復雜,但是有時候還要記憶,幸好chorme瀏覽器有個xpath helper插件,安裝上之后鼠標放在圖片上,按下ctrl+shift+x鍵,彈出對話框:
xpath help獲取路徑
鼠標在這些海報中來回移動,發現變化的部分,然后修改xpath,去掉前面的固定前綴,把list的下標改成固定值,得到如下:
xpath調整
得到海報的xpath:

//div[@id='recent_movies']/div[@class='bd']/ul[@class='list-s']/*/div[@class='pic']/a/img/@src

這個xpath可以獲取到的圖片地址為:

https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2577437186.webp
https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2537133715.webp
https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542380253.webp
https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2528842218.webp
https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2499052494.webp

我們用selenium模擬瀏覽器來進行html的加載和xpath的查詢,獲取到地址后,就可以通過下載函數進行圖片下載。

三. 利用selenium 進行海報的下載

在豆瓣電影中搜索”甄子丹”
https://search.douban.com/movie/subject_search?search_text=%E7%94%84%E5%AD%90%E4%B8%B9&cat=1002
調整下xpath:

//div[1]/div[@class='sc-bZQynM jbSySb sc-bxivhb gemzcp'][*]/div[@class='item-root']/a[@class='cover-link']/img[@class='cover']/@src

得到的15個結果:

https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2577437186.webp
...

如果需要翻頁的話,鏈接加個start=15說明從16個海報開始展示。
獲取電影名稱:

//div[@class='_ytukbl17q']/div[1]/div[@class='sc-bZQynM cBnAay sc-bxivhb gemzcp'][*]/div[@class='item-root']/div[@class='detail']/div[@class='title']/a[@class='title-text']

得到結果:

武俠‎ (2011)
西游記之大鬧天宮‎ (2014)
...

最終下載代碼:

# -*- coding: utf-8 -*-
import requests
import json
import sys
import io
import os
from selenium import webdriver
from lxml import etree

def download(picPath,src, id):
  if not os.path.isdir(picPath):
      os.mkdir(picPath)
  dir = picPath+'/' + str(id) + '.webp'
  print(src)
  imageHeader  = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    #'accept-encoding': 'gzip, deflate',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'max-age=0',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
  }
  try:
    pic = requests.get(src,headers=imageHeader,timeout=50)
    fp = open(dir, 'wb')
    fp.write(pic.content)
    fp.close()
  except requests.exceptions.ConnectionError:
    print('Sorrry,image cannot downloaded, url is error{}.'.format(src))

def query_img(query,downloadUrl):
    realUrl = downloadUrl.format(query)
    print(realUrl)
    driver = webdriver.Chrome('D:\\py3\\Lib\\site-packages\\selenium\\webdriver\\chrome\\chromedriver_win32\\chromedriver.exe')
    driver.get(realUrl)
    #解析html
    html = etree.HTML(driver.page_source)
    image_url_path = "//div[1]/div[*]/div[@class='item-root']/a[@class='cover-link']/img[@class='cover']/@src"
    movie_name_path = "//div/div[1]/div[*]/div[@class='item-root']/div[@class='detail']/div[@class='title']/a[@class='title-text']/text()"
    urls = html.xpath(image_url_path)
    names = html.xpath(movie_name_path)
    picPath = 'F:\\python\\images'
    for (url,name) in zip(urls,names):
        download(picPath,url,name)

if __name__ == "__main__":
    query = '甄子丹'
    url = 'https://search.douban.com/movie/subject_search?search_text=\'{}\'&cat=1002'
    query_img(query,url)

注意:這里面利用chrome瀏覽器的driver,不同的瀏覽器的driver可以到https://selenium-python.readthedocs.io/installation.html鏈接去下載,主要要和自己的瀏覽器版本保持一致。
chrome瀏覽器的版本可以通過在瀏覽器中輸入:chrome://version/來進行查看。

祝大家冬至快樂!


免責聲明!

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



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