一看就懂!小白就能用python爬到又大又白的圖片!

目錄

 

前言

爬蟲是個啥?

鋪墊知識

運行環境

Requests庫

BeautifulSoup 庫

PhatomJS + Selenium

記住,技術本身是無罪的,有罪的在於濫用技術的人


前言

當你看到這篇博客時,恭喜你被我的標題騙了進來🤪🤪  欸欸欸,別走,精彩的在下面。

本篇文章並不是什麼高大上的爬蟲教學,旨在激發一位小白的好奇心,通過本文的學習,基本可以滿足你的爬蟲小心思~

如果你是小白,這篇文章對你入坑有所幫助的話,麻煩點個贊❗
如果你是大佬,這篇文章有什麼說的不對的地方,麻煩給予指導✍

對了,本篇基於你得對所使用的語言Python有所瞭解,其次還基於你對前端三劍客HTML、CSS、JavaScript有所瞭解。如果你對上述沒有了解,你可以先去了解一下再來食用本篇文章。

其次,以下代碼我都會添加上time.sleep() 睡眠函數,目的是爲了不對目標網址造成不可逆的傷害(雖然不太可能),但是各位還是要注意,爬蟲可以,搞破壞就小心呵呵噠。

廢話不多說,我們來入坑了

 

爬蟲是個啥?

國際慣例,先給大家科普(雖然我很不情願,畢竟你想學這個東西,你起碼有所瞭解)

爬蟲,就是打開一個網頁,將你想要的東東下載下來。
XX:(小聲bb:這不就是鼠標點一點的事嗎,弄得這麼複雜)
這位同學,你說的沒錯,就是鼠標點一點的事,但是加入你打開了某個網站,裏面琳琅滿足的又大又白好看的圖片😍
如果用鼠標點,點一天可能才下載幾十張上百張,還有幾萬張等着你。這時候可心疼了,小孩子才選擇,我想全都要,這可咋辦?
爬蟲這時候就出來,爬蟲就是通過代碼的形式,幫你自動化的完成點擊操作,幾萬張的圖片,你要肆無忌憚(但千萬別肆無忌憚)的話一會就搞定了,然後就點開文件夾....

 

鋪墊知識

打開瀏覽器(建議谷歌瀏覽器),找到瀏覽器地址欄,然後在裏敲https://www.doutula.com/photo/list/,你會看到網頁內容。沒錯,今天我們就是來爬這些又大又白的表情包。(如果侵犯了鬥圖啦,聯繫我立馬更新)

我們Crtl+U,看到這些文字了嗎?這就是網頁源代碼,這纔是網頁赤裸裸的樣子。(也可以鼠標右鍵->查看網頁源代碼)

我們回到剛剛頁面,按一下F12,帶你一下彈出窗口左上角的箭頭,接着把鼠標移到你想要的圖片上,就可以找到對應的標籤。

好了,如何找到想要的東西我們就講到這,下一部分我們將編寫代碼,初步獲取到網頁的源代碼。


運行環境

首先說一下運行環境:

Windows10  我也想摸摸mac
Python3.7    推薦使用Anaconda這個管理工具,但是本篇我是不用的,避免大家的學習成本(而且Pycharm也有類似的工具)
PyCharm 2019.3.3 

貼心的大暖男給你準備好了Python和PyCharm安裝包了(溫馨提示,Pycharm破解是失效的,需要自己弄)

安裝包鏈接:https://share.weiyun.com/5CMS5fx 密碼:5ct54a

 

Requests庫

Requests庫是python中強大的網絡請求庫,可以實現跟瀏覽器一樣發送各種HTTP請求來獲取網站的數據。

安裝:win+R 輸入cmd打開命令行窗口,輸入下面這一句

pip install requests

Requests就安裝好了,提供一份 Requests中文文檔 

 

我們來看看如何獲取網頁源代碼

首先創建項目 quick_in_pit 

創建文件 pit.py

 編寫代碼

import requests  # 導入requests庫

r = requests.get('https://www.doutula.com/photo/list/', )  # 像目標url地址發送get請求,返回一個response對象
print(r.text)  # r.text是http response的網頁HTML

執行,發現獲取到了內容,不看內容,至少沒有報錯,證明我們是請求成功了

再來看看內容,報的是404。假裝深思熟路一會,沒想到這麼快就祭出殺手鐗了。這個網站用nginx代理,還進行了反爬操作。
(關於反爬不是我這篇要說的內容,說了我以後的素材怎麼辦?)

修改一下代碼,給我們的代碼添加上請求頭。僞造一個User-Agent

import requests  # 導入requests庫

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/54.0.2840.99 Safari/537.36'}
r = requests.get('https://www.doutula.com/', headers=headers)  # 像目標url地址發送get請求,返回一個response對象
print(r.text)  # r.text是http response的網頁HTML

在執行一次,這次源代碼還不被我們手到擒來😤

Requests就介紹到這裏,Requests的更多使用請自己翻文檔啦,有中文還有什麼看不懂的

BeautifulSoup 庫

上一小節我們拿到了網頁的源代碼啦,那麼怎麼提取我們想要的內容呢?xi大大教我們要不忘初心,我們的初心是什麼?是又大又白的圖片!BeautifulSoup庫就是一個解析HTML文檔的庫,能夠幫助我們提取我們想要的指定標籤的內容。

安裝:

pip install beautifulsoup4

我們簡稱 beautifulsoup4 爲bs4  溫馨提供:bs4中文文檔

使用bs4  解析器推薦使用lxml,這裏使用自帶html.parser

首先我們需要定位我們要找到的圖片,還記得F12嗎?我們可以用肉眼加手定位標籤,計算機怎麼做呢?當然是根據字符,有什麼可以定位標籤的字符? 當然是標籤屬性啦,像 id、class這些,還有css選擇器,還有Xpath(強烈推薦Xpath,但是我就不告訴你)

這裏我們觀察這個標籤,發現class,這應該是所有圖片都有的class。

 然後我們編寫下面代碼

import requests  # 導入requests庫
import bs4

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/54.0.2840.99 Safari/537.36'}
r = requests.get('https://www.doutula.com/', headers=headers)  # 像目標url地址發送get請求,返回一個response對象
#print(r.text)  # r.text是http response的網頁HTML

soup = bs4.BeautifulSoup(r.text, 'html.parser')
all_img = soup.findAll('img', class_='lazy image_dtb img-responsive loaded')
for img in all_img:
    print(img)

執行代碼,發現竟然什麼都沒有輸出?你們就會想立馬拉到最下面說評論說:你個大屁眼子,根本行不通。
客官別急,我們想一想,爲啥呀!再次深思熟慮後,這裏我們是對獲取到的源碼進行提取,不是網頁顯示的源碼進行提取,是不是這個網站又做了什麼手腳?我們把 print(r.txt)打開,好你的XXX,和我們網頁上看到的class進入不一樣。

修改代碼

import requests  # 導入requests庫
import bs4

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/54.0.2840.99 Safari/537.36'}
r = requests.get('https://www.doutula.com/', headers=headers)  # 像目標url地址發送get請求,返回一個response對象
# print(r.text)  # r.text是http response的網頁HTML
soup = bs4.BeautifulSoup(r.text, 'html.parser')
all_img = soup.findAll('img', class_='img-responsive lazy image_dta')
for img in all_img:
    print(img)

執行,img標籤就被我們手到擒來了。 

提取到標籤,進一步提取內容,因爲我們只用src的內容呀,放心,強大的bs4就可以做到,不用學新東西了

提取屬性簡直不要太簡單,在上面基礎上,添加上['src']即可

print(img['src'])

路徑獲取到了,我們再寫一個保存就應該可以搞定了,下方高能!

import bs4
import os
import requests
import time

class BeautifulPicture:

    def __init__(self):  # 類的初始化操作
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/54.0.2840.99 Safari/537.36'}  # 給請求指定一個請求頭來模擬chrome瀏覽器

        self.web_url = 'https://www.doutula.com/photo/list/'  # 要訪問的網頁地址

        self.folder_path = 'D:\youDaYouBai'  # 設置圖片要存放的文件目錄

    def get_pic(self):
        print('開始網頁get請求')
        r = self.request(self.web_url)
        print('開始獲取所有a標籤')
        all_img = bs4.BeautifulSoup(r.text, 'html.parser').find_all('img',
                                                                    class_='img-responsive lazy image_dta')  # 獲取網頁中的class爲img-responsive lazy image_dta的所有img標籤
        print('開始創建文件夾')
        self.mkdir(self.folder_path)  # 創建文件夾
        print('開始切換文件夾')
        os.chdir(self.folder_path)  # 切換路徑至上面創建的文件夾

        for img in all_img:  # 循環每個標籤,獲取標籤中圖片的url並且進行網絡請求,最後保存圖片
            img_src = img['data-original']  # img標籤中完整的 data-original 字符串
            print('img標籤的style內容是:', img_src)
            img_name = img['alt']

            time.sleep(2) # 不要肆無忌憚,2s抓一張圖
            self.save_img(img_src, img_name)  # 調用save_img方法來保存圖片

    def save_img(self, url, name):  ##保存圖片
        print('開始請求圖片地址,過程會有點長...')
        img = self.request(url)

        file_name = name + os.path.splitext(url)[-1]
        print('開始保存圖片')
        f = open(file_name, 'ab')
        f.write(img.content)
        print(file_name, '圖片保存成功!')
        f.close()

    def request(self, url):  # 返回網頁的response
        r = requests.get(url, headers=self.headers)  # 像目標url地址發送get請求
        return r

    def mkdir(self, path):  ##這個函數創建文件夾
        path = path.strip()
        isExists = os.path.exists(path)
        if not isExists:
            print('創建名字叫做', path, '的文件夾')
            os.makedirs(path)
            print('創建成功!')
        else:
            print(path, '文件夾已經存在了,不再創建')


beauty = BeautifulPicture()  # 創建類的實例
beauty.get_pic()  # 執行類中的方法

接着我們執行代碼。控制檯打出一系列說明,代碼正常運行。看着飛快流動的控制檯,不說了,我先去拿紙巾了.....

我回來啦

迫不及待點開文件夾一看,這都是些啥啊。我要這紙巾有何用?

沒想到這裏還有一關,再次陷入沉思,等會,我們回頭看剛剛的動圖,發現怎麼都是loader.gif?33 再回頭看看網頁源代碼,發現問題不簡單,原來真正的圖片路徑保存在 data-original 和 data-backup屬性中,這裏我想說的是 我們要學會和網站開發者鬥智鬥勇

修改代碼!

import bs4
import os
import requests


class BeautifulPicture:

    def __init__(self):  # 類的初始化操作
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/54.0.2840.99 Safari/537.36'}  # 給請求指定一個請求頭來模擬chrome瀏覽器

        self.web_url = 'https://www.doutula.com/photo/list/'  # 要訪問的網頁地址

        self.folder_path = 'D:\youDaYouBai'  # 設置圖片要存放的文件目錄

    def get_pic(self):
        print('開始網頁get請求')
        r = self.request(self.web_url)
        print('開始獲取所有a標籤')
        all_img = bs4.BeautifulSoup(r.text, 'html.parser').find_all('img',
                                                                    class_='img-responsive lazy image_dta')  # 獲取網頁中的class爲img-responsive lazy image_dta的所有img標籤
        print('開始創建文件夾')
        self.mkdir(self.folder_path)  # 創建文件夾
        print('開始切換文件夾')
        os.chdir(self.folder_path)  # 切換路徑至上面創建的文件夾

        for img in all_img:  # 循環每個標籤,獲取標籤中圖片的url並且進行網絡請求,最後保存圖片
            img_src = img['data-original']  # img標籤中完整的 data-original 字符串
            print('img標籤的style內容是:', img_src)
            img_name = img['alt']

            time.sleep(2) # 睡2s  不要肆無忌憚,被抓了我不負責
            self.save_img(img_src, img_name)  # 調用save_img方法來保存圖片

    def save_img(self, url, name):  ##保存圖片
        print('開始請求圖片地址,過程會有點長...')
        img = self.request(url)

        file_name = name + os.path.splitext(url)[-1]
        print('開始保存圖片')
        f = open(file_name, 'ab')
        f.write(img.content)
        print(file_name, '圖片保存成功!')
        f.close()

    def request(self, url):  # 返回網頁的response
        r = requests.get(url, headers=self.headers)  # 像目標url地址發送get請求,返回一個response對象。有沒有headers參數都可以。
        return r

    def mkdir(self, path):  ##這個函數創建文件夾
        path = path.strip()
        isExists = os.path.exists(path)
        if not isExists:
            print('創建名字叫做', path, '的文件夾')
            os.makedirs(path)
            print('創建成功!')
        else:
            print(path, '文件夾已經存在了,不再創建')


beauty = BeautifulPicture()  # 創建類的實例
beauty.get_pic()  # 執行類中的方法

再跑一遍!

 

Wow,又白又大的表情包就被我們下載下來了。但是還有個問題!他怎麼只能保存這一頁的,我還得手動更換頁碼嗎?這裏我們下一節說 

bs4當然還有很多妙用,像上面說的 css選擇器,還有Xpath ,自學纔是王道啊

 

PhatomJS + Selenium

上文中,我們的爬蟲面臨着一個問題,我們還是被網站識別到了我們使用爬蟲操作的,這可咋辦啊?難不成要回到起點,手動點擊?更重要的是,現在的JS技術這麼炫酷,下拉刷新,Ajax渲染,這些等頁面加載完了還得加載一堆東西的網址,單純使用request並不能滿足需求了,這可怎麼辦?
作爲推動時間發展的程序員,怎麼會被這點問題難到?沒有瀏覽器?我們就創建一個瀏覽器出來,這就是這一小節要說的PhatomJS + Selenium

PhatomJS是一個WebKit內核的瀏覽器引擎,它能像瀏覽器一樣(它就是一個瀏覽器,只不過沒有界面)解析網頁,以及運行JavaScript腳本。

Selenium是一個自動化測試框架,因爲它能夠模擬人工操作,比如能在瀏覽器中點擊按鈕、在輸入框中輸入文本、自動填充表單、還能進行瀏覽器窗口的切換、對彈出窗口進行操作。也就是說你能手動做的東西,基本都能用它來實現自動化!

聽到上面這兩句話,是不是大徹大悟,頻頻點頭,可行!Python + PhatomJS + Selenium 是爬蟲的無敵三件套。

PhatomJS 不能使用pip install 來安裝。需要去官網安裝,小暖男在這裏給你備好了,在上文的包裏面一併擁有,因爲實在是下不下來,後面用服務器weget去下載下載了一個多小時才下下來的。

下載完成的是一個壓縮包,解壓到你想存放的目錄,同時配置環境變量,沒錯又是環境變量。

只找到了英文文檔 PhatomJS 英文文檔

安裝selenium就用pip安裝就可以 Selenium中文文檔

 pip install selenium

selenium也提供了對標籤進行提取的操作,我們既可以用selenium也可以繼續使用bs4,下面我使用selenium。

PhatomJS 無頁面版本已經被廢棄了,現在都推薦使用瀏覽器驅動的形式,如果我們使用PhatomJS會在控制檯輸出這樣一句話。

D:\Program Files\python3.7\lib\site-packages\selenium\webdriver\phantomjs\webdriver.py:49: UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead
  warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '

首先下載Chrome瀏覽器驅動:Chrome瀏覽器驅動下載地址 選擇你瀏覽器的版本,大版本要一致。選擇自己的系統版本,然後下載。這是一個壓縮包,解壓後存到一個目錄中,然後把該目錄添加到環境變量。我就直接把他放在PhatomJS 的目錄下了

查看自己版本在網址上輸入

chrome://version/

寫段代碼測試一下 

from selenium import webdriver  # 導入Selenium的webdriver
from selenium.webdriver.common.keys import Keys  # 導入Keys
import time  # 導入time控制時間

driver = webdriver.Chrome()  # 指定使用的瀏覽器,初始化webdriver
driver.get("http://www.baidu.com")  # 請求網頁地址
assert "百度一下" in driver.title  # 看看 “百度一下” 關鍵字是否在網頁title中,如果在則繼續,如果不在,程序跳出。
elem = driver.find_element_by_name("wd")  # 找到name爲wd的元素,這裏是個搜索框
elem.clear()  # 清空搜索框中的內容
elem.send_keys("大誌的博客")  # 在搜索框中輸入 “大誌的博客”
time.sleep(2)  # 睡兩秒
elem.send_keys(Keys.RETURN)  # 相當於回車鍵,提交
assert "No results found." not in driver.page_source  # 如果當前頁面文本中有“No results found.”則程序跳出

time.sleep(10)  # 睡10秒
driver.close()  # 關閉webdriver

 

 

接下來就是改造我們上一節的項目了

首先是創建Chrome,__init__方法中追加 self.browser = webdriver.Chrome()

    def __init__(self):  # 類的初始化操作
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/54.0.2840.99 Safari/537.36'}  # 僞造請求頭
        self.web_url = 'https://www.doutula.com/photo/list/'  # 要訪問的網頁地址
        self.folder_path = 'D:\youDaYouBai'  # 設置圖片要存放的文件目錄
        self.browser = webdriver.Chrome()

 

接着改造get_pic 方法

首先我們要找到下一頁的按鈕,但是我們發現沒辦法太明確的獲取到這個a標籤,但是我們換個思路,這個是所有的page-link最後一個,所以我們可以這樣做。爬蟲中思路很重要。

        # 先獲取所有的分頁按鈕
        pages = self.browser.find_elements_by_class_name("page-link")
        # 最後一個就是下一頁 這裏並沒有做最後一頁的判斷 可以用一個current 來比較
        next_page = pages[len(pages) - 1]

 

接着是遞歸到下一頁,很簡單,我們修改web_url,遞歸調用get_pic()方法即可。這裏我只抓取前三頁。

        # 獲取href路徑
        next_page_href = next_page.get_attribute("href")
        # 只抓取前三頁的內容,不要太肆無忌憚了。
        if int(next_page_href[-1]) > 3:
            print("抓取完成")
            self.browser.close()
            exit()

        # 這裏開始遞歸獲取下一頁
        # 設置訪問路徑
        time.sleep(5)  # 每抓一頁 睡五秒
        self.web_url = next_page_href
        self.get_pic()

我們看看效果

拉取圖片中:

切換下一頁,注意url和刷新 

 

 

 

附上究極形態源碼:

import os
import requests
from selenium import webdriver  # 導入Selenium的webdriver

import time


class BeautifulPicture:

    def __init__(self):  # 類的初始化操作
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/54.0.2840.99 Safari/537.36'}  # 僞造請求頭
        self.web_url = 'https://www.doutula.com/photo/list/'  # 要訪問的網頁地址
        self.folder_path = 'D:\youDaYouBai'  # 設置圖片要存放的文件目錄
        self.browser = webdriver.Chrome()

    def get_pic(self):

        print('開始網頁get請求')
        self.browser.get(self.web_url)
        # selenium 獲取標籤 classname是用 . 間隔的
        all_img = self.browser.find_elements_by_class_name(
            "img-responsive.lazy.image_dta.loaded")

        if (len(all_img)) < 1:
            print("沒有獲取到圖片,程序退出")
            self.browser.close()
            exit()

        # 先獲取所有的分頁按鈕

        pages = self.browser.find_elements_by_class_name("page-link")
        # 最後一個就是下一頁 這裏並沒有做最後一頁的判斷 可以用一個current 來比較
        next_page = pages[len(pages) - 1]

        print('開始創建文件夾')
        self.mkdir(self.folder_path)  # 創建文件夾
        print('開始切換文件夾')
        os.chdir(self.folder_path)  # 切換路徑至上面創建的文件夾

        for img in all_img:  # 循環每個標籤,獲取標籤中圖片的url並且進行網絡請求,最後保存圖片
            img_src = img.get_attribute('data-original')  # img標籤中data-original完整的字符串
            print('img標籤的style內容是:', img_src)
            img_name = img.get_attribute('alt')
            time.sleep(1)  # 1秒抓一張圖,不要太肆無忌憚了
            self.save_img(img_src, img_name)  # 調用save_img方法來保存圖片

        # 獲取href路徑
        next_page_href = next_page.get_attribute("href")
        # 只抓取前三頁的內容,不要太肆無忌憚了。
        if int(next_page_href[-1]) > 3:
            print("抓取完成")
            self.browser.close()
            exit()

        # 這裏開始遞歸獲取下一頁
        # 設置訪問路徑
        time.sleep(5)  # 每抓一頁 睡五秒
        self.web_url = next_page_href
        self.get_pic()

    def save_img(self, url, name):  ##保存圖片
        print('開始請求圖片地址,過程會有點長...')
        img = requests.get(url, headers=self.headers)
        file_name = name + os.path.splitext(url)[-1]
        print('開始保存圖片')
        f = open(file_name, 'ab')
        f.write(img.content)
        print(file_name, '圖片保存成功!')
        f.close()

    def mkdir(self, path):  ##這個函數創建文件夾
        path = path.strip()
        isExists = os.path.exists(path)
        if not isExists:
            print('創建名字叫做', path, '的文件夾')
            os.makedirs(path)
            print('創建成功!')
        else:
            print(path, '文件夾已經存在了,不再創建')


beauty = BeautifulPicture()  # 創建類的實例
beauty.get_pic()  # 執行類中的方法

 

最後,希望這篇文章能夠激起你的興趣。上述講的可以滿足我們的大多數需求,但還有很多優秀的技術框架,還有反爬以及避免被封殺等操作,這些都不是重點,

記住,技術本身是無罪的,有罪的在於濫用技術的人

我去鬥圖了,我們下次再見~


有什麼問題可以評論或者私信我,每日在線解(LIAO)疑(SAO)。

我是大誌,一位準備996的卑微碼農🐶,覺得好用記得點贊收藏!!!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章