[譯] 30 分鐘 Python 爬蟲教程

一直想用 Python 和 Selenium 寫一個網頁爬蟲,但一直都沒去實現。直到幾天前我才決定動手實現它。寫代碼從 Unsplash 網站上抓取一些漂亮的圖片,這看起來好像是很是艱鉅的事情,但實際上倒是極其簡單。css

圖片來源:Blake Connally 發佈於 Unsplash.comhtml

簡單圖片爬蟲的原料

簡單圖片爬蟲的菜譜

以上的全部都安裝好了?棒!在咱們繼續開始寫代碼前,我先來解釋一下以上這些原料都是用來幹什麼的。前端

咱們首先要作的是利用 Selenium webdrivergeckodriver 來爲咱們打開一個瀏覽器窗口。首先,在 Pycharm 中新建一個項目,根據你的操做系統下載最新版的 geckodriver,將其解壓並把 geckodriver 文件拖到項目文件夾中。Geckodriver 本質上就是一個能讓 Selenium 控制 Firefox 的工具,所以咱們的項目須要它來讓瀏覽器幫咱們作一些事。python

接下來咱們要作的事就是從 Selenium 中導入 webdriver 到咱們的代碼中,而後鏈接到咱們想爬取的 URL 地址。說作就作:android

from selenium import webdriver
# 咱們想要瀏覽的 URL 連接
url = "https://unsplash.com"
# 使用 Selenium 的 webdriver 來打開這個頁面
driver = webdriver.Firefox(executable_path=r'geckodriver.exe')
driver.get(url)
複製代碼

打開瀏覽器窗口到指定的 URL。ios

一個遠程控制的 Firefox 窗口。git

至關容易對吧?若是以上所說你都正確完成了,你已經攻克了最難的那部分了,此時你應該看到一個相似於以上圖片所示的瀏覽器窗口。github

接下來咱們就應該向下滾動以便更多的圖片能夠加載出來,而後咱們纔可以將它們下載下來。咱們還想再等幾秒鐘,以便萬一網絡鏈接太慢了致使圖片沒有徹底加載出來。因爲 Unsplash 網站是使用 React 構建的,等個 5 秒鐘彷佛已經足夠」慷慨」了,那就使用 Python 的 time 包等個 5 秒吧,咱們還要使用一些 Javascript 代碼來滾動網頁——咱們將會用到 [window.scrollTo()](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo) 函數來實現這個功能。將以上所說的合併起來,最終你的代碼應該像這樣:web

import time
from selenium import webdriver

url = "https://unsplash.com"

driver = webdriver.Firefox(executable_path=r'geckodriver.exe')
driver.get(url)
# 向下滾動頁面而且等待 5 秒鐘
driver.execute_script("window.scrollTo(0,1000);")
time.sleep(5)
複製代碼

滾動頁面並等待 5 秒鐘。網頁爬蟲

測試完以上代碼後,你應該會看到瀏覽器的頁面稍微往下滾動了一些。下一步咱們要作的就是找到咱們要下載的那些圖片。在探索了一番 React 生成的代碼以後,我發現了咱們可使用一個 CSS 選擇器來定位到網頁上畫廊的圖片。網頁上的佈局和代碼在之後可能會發生改變,但目前咱們可使用 #gridMulti img 選擇器來得到屏幕上可見的全部 <img> 元素。

咱們能夠經過 [find_elements_by_css_selector()](http://selenium-python.readthedocs.io/api.html#selenium.webdriver.remote.webdriver.WebDriver.find_element_by_css_selector) 獲得這些元素的一個列表,但咱們想要的是這些元素的 src 屬性。咱們能夠遍歷這個列表並一一抽取出 src 來:

import time
from selenium import webdriver

url = "https://unsplash.com"

driver = webdriver.Firefox(executable_path=r'geckodriver.exe')
driver.get(url)

driver.execute_script("window.scrollTo(0,1000);")
time.sleep(5)
# 選擇圖片元素並打印出他們的 URL
image_elements = driver.find_elements_by_css_selector("#gridMulti img")
for image_element in image_elements:
    image_url = image_element.get_attribute("src")
    print(image_url)
複製代碼

選擇圖片元素並得到圖片 URL。

如今爲了真正得到咱們找到的圖片,咱們會使用 requests 庫和 PIL 的部分功能,也就是 Image。咱們還會用到 io 庫裏面的 BytesIO 來將圖片寫到文件夾 ./images/ 中(在項目文件夾中建立)。如今把這些都一塊兒作了,咱們要先往每張圖片的 URL 連接發送一個 HTTP GET 請求,而後使用 ImageBytesIO 來將返回的圖片存儲起來。如下是實現這個功能的其中一種方式:

import requests
import time
from selenium import webdriver
from PIL import Image
from io import BytesIO

url = "https://unsplash.com"

driver = webdriver.Firefox(executable_path=r'geckodriver.exe')
driver.get(url)

driver.execute_script("window.scrollTo(0,1000);")
time.sleep(5)
image_elements = driver.find_elements_by_css_selector("#gridMulti img")
i = 0

for image_element in image_elements:
    image_url = image_element.get_attribute("src")
    # 發送一個 HTTP GET 請求,從響應內容中得到圖片並將其存儲
    image_object = requests.get(image_url)
    image = Image.open(BytesIO(image_object.content))
    image.save("./images/image" + str(i) + "." + image.format, image.format)
    i += 1
複製代碼

下載圖片。

這就是爬取一堆圖片所須要作的全部了。很顯然的是,除非你想隨便找些圖片素材來作個設計原型,不然這個小小的爬蟲用處可能不是很大。因此我花了點時間來優化它,加了些功能:

  • 容許用戶經過指定一個命令行參數來指定搜索查詢,還有一個數值參數指定向下滾動次數,這使得頁面能夠顯示更多的圖片可供咱們下載。
  • 能夠自定義的 CSS 選擇器。
  • 基於搜索查詢關鍵字的自定義結果文件夾
  • 經過截斷圖片的預覽圖連接來得到全高清圖片
  • 基於圖片的 URL 給圖片文件命名。
  • 爬取最終結束後關閉瀏覽器。

你能夠(你也應該)嘗試本身實現這些功能。全功能版本的爬蟲能夠在這裏下載。記得要先按照文章開頭所說的,下載 geckodriver 而後鏈接到你的項目中。


不足之處,注意事項和將來優化項

整個項目是一個簡單的「驗證概念」,以弄清楚網頁爬蟲是如何作的,這也就意味着有不少東西能夠作,來優化這個小工具:

  • 沒有致謝圖片最開始的上傳者是個很很差的作法。Selenium 確定是有能力處理這種狀況的,那麼每一個圖片都帶有做者的名字。
  • Geckodriver 不該該被放在項目文件夾中,而是安裝在全局環境下,並被放到 PATH 系統變量中。
  • 搜索功能能夠輕易地擴展到多個查詢關鍵字,那麼下載不少類型圖片地過程就能夠被簡化了。
  • 默認瀏覽器能夠用 Chrome 替代 Firefox,甚至能夠用 PhantomJS 替代,這對這種類型的項目來講是更好的。

掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索