爬蟲實(shí)戰(zhàn):一鍵爬光指定網(wǎng)站所有圖片(一)

前言:

? 最近自己在做圖片處理工具卖子,最開始的初衷只是為了做一個(gè)圖片深度學(xué)習(xí)項(xiàng)目搀矫,做的時(shí)候缺少大量的圖片素材夏伊,手動(dòng)去下載自己又是比較懶驳规,并且操作起來(lái)非常的麻煩,于是自己寫了一個(gè)單頁(yè)面全圖片的爬蟲署海,等自己實(shí)現(xiàn)完功能之后,發(fā)現(xiàn)又有很多功能是可以優(yōu)化的医男,于是在這個(gè)基礎(chǔ)上我又做了一下功能升級(jí)砸狞,最終出了一個(gè)爬取指定網(wǎng)站所有圖片的版本,當(dāng)然镀梭,這個(gè)版本還有很多可以優(yōu)化的點(diǎn)刀森,我會(huì)在下面的實(shí)際過(guò)程中進(jìn)行說(shuō)明。本篇著重說(shuō)明指定頁(yè)面的圖片抓取报账。

項(xiàng)目目標(biāo):

? 指定某一頁(yè)面進(jìn)行圖片資源進(jìn)行爬取研底,保存到本地硬盤埠偿。

項(xiàng)目分析:

? 1、本項(xiàng)目我們要實(shí)現(xiàn)某一個(gè)指定網(wǎng)站的頁(yè)面URL榜晦,也就是提取href的鏈接冠蒋。并將所有的內(nèi)鏈創(chuàng)建到下一個(gè)任務(wù)當(dāng)中去。

? 2乾胶、除了頁(yè)面中的href鏈接抖剿,我們還要讀取頁(yè)面中所有圖片元素,通過(guò)get方式進(jìn)行訪問(wèn)识窿,讀取后保存斩郎。

簡(jiǎn)單分析了一下,我們開始代碼的實(shí)現(xiàn)

首先完成第2項(xiàng)的功能喻频,我們要將頁(yè)面圖片元素提取出來(lái)缩宜,并寫入到一個(gè)指定的文件目錄當(dāng)中,根據(jù)url中的文件名進(jìn)行保存處理甥温,考慮到我們未來(lái)功能復(fù)用性锻煌,所以我單獨(dú)為單頁(yè)面文件下載實(shí)現(xiàn)了一個(gè)類,(當(dāng)然最終實(shí)現(xiàn)之后窿侈,發(fā)現(xiàn)Python中存在一些問(wèn)題炼幔,這里我們?cè)谖膊吭僮鼋忉專?/p>

我們先定義一個(gè)類,這里命名叫“DownloadImage.py”史简,因?yàn)槭峭ㄟ^(guò)curl方式進(jìn)行抓取采集圖片列表乃秀,我們要定義一個(gè)header頭屬性,以及一個(gè)保存圖片的本地的地址圆兵,定義代碼如下:

headers = {
# 用戶代理
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
_downloadDir = './img/'

因?yàn)檫@個(gè)類我們要復(fù)用跺讯,所以單獨(dú)放到一個(gè)py文件中,方便后面進(jìn)行引用殉农。

在類的構(gòu)造方法中刀脏,我們需要進(jìn)行一個(gè)參數(shù)的初始化。為了下載指定頁(yè)面的圖片超凳,那么我們需要指定一個(gè)頁(yè)面(必要參數(shù))愈污,為了路徑可定義化,我們考慮增加了一個(gè)可選的本地存放的路徑參數(shù)轮傍。 另外暂雹,因?yàn)槊總€(gè)頁(yè)面其實(shí)有些圖片我們是不需要的,比如一些頁(yè)面的logo.gif创夜,style.css中的樣式圖片我們并不需要杭跪,那我們這里就定義了一個(gè)圖片過(guò)濾參數(shù)。

定義完之后我們需要對(duì)對(duì)象中的參數(shù)進(jìn)行賦值,并初始化相關(guān)的參數(shù)涧尿。

def __init__(self,url,download_path=None,filter=[]):
    self.url = url
    self.initUrl()
    self.filter =filter

    # 定義圖片下載圖徑
    if download_path:
        self.downloadPath=self._downloadDir + download_path
    else:
        self.downloadPath=self._downloadDir + self.urlParse.netloc
    self.makeDir()
    self.getImages()

首頁(yè)我們?cè)趥魅險(xiǎn)rl之后系奉,將這個(gè)url賦給個(gè)類,方便對(duì)象中直接調(diào)用姑廉,然后我們要將url進(jìn)行一個(gè)格式化缺亮,解析一次。

這個(gè)方法名就是initUrl()庄蹋,方法的主用要途對(duì)過(guò) urlparse方法瞬内,將url的域名和參數(shù)進(jìn)行分離。整理成我們需要的格式限书。

原因是因?yàn)樵趆ttp的頁(yè)面當(dāng)中虫蝶,我們定義圖片會(huì)有幾種格式:

1.絕對(duì)路徑,大部分網(wǎng)站的圖片url都是這樣倦西,單獨(dú)配置了域名資源進(jìn)行顯示

2.相對(duì)路徑能真,有很多網(wǎng)站只有一臺(tái)服務(wù)器,會(huì)把靜態(tài)資源和html文件放在一起

3.某些站點(diǎn)的域名證書綁定是兼容性的扰柠,所以也會(huì)有//前綴進(jìn)行http和https的兼容處理粉铐。

處理完url之后,我們將圖片的過(guò)濾增加進(jìn)去卤档, 方法我不再細(xì)說(shuō)蝙泼,處理方式是通過(guò)正則進(jìn)入搜索匹配來(lái)過(guò)濾的,比如傳入['png','gif']劝枣,那么所有的png和gif都不再被下載汤踏。

然后我們?cè)僬f(shuō)一下makeDir,初始化時(shí)會(huì)判斷文件下載目錄是否存在舔腾,如果不存在溪胶,則新建。

def makeDir(self):
    if not os.path.exists(self.downloadPath):
        os.makedirs(self.downloadPath)

最后稳诚,我們通過(guò)curl獲取傳參的url頁(yè)面中所有的圖片地址哗脖!

def getImages(self):
    response = requests.get(self.url, headers=self.headers)
    if response.status_code == 200:
        html = et.HTML(response.text)
        images = html.xpath('//img/@src')
        if self.filter:
            match = '|'.join(self.filter)
            self.Imageurls = []
            for value in images:
                if not re.search(match,value):
                    self.Imageurls.append(value)

        else:
            self.Imageurls=images
    else:
        return None

最終類代碼如下:

# 抓取指定網(wǎng)頁(yè)所有圖片保存到本地
import requests
import os
from urllib.parse import *
from lxml import etree as et
import re
import sys
# 請(qǐng)求頭
class DownloadImage(object):
    headers = {
    # 用戶代理
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
    }
    _downloadDir = './img/'

    def __init__(self,url,download_path=None,filter=[]):
        self.url = url
        self.initUrl()
        self.filter =filter

        # 定義圖片下載圖徑
        if download_path:
            self.downloadPath=self._downloadDir + download_path
        else:
            self.downloadPath=self._downloadDir + self.urlParse.netloc
        self.makeDir()
        self.getImages()

    #通用圖片路徑方法格式化
    def initUrl(self):
        self.urlParse=urlparse(self.url)

    def getImages(self):
        response = requests.get(self.url, headers=self.headers)
        if response.status_code == 200:
            html = et.HTML(response.text)
            images = html.xpath('//img/@src')
            if self.filter:
                match = '|'.join(self.filter)
                self.Imageurls = []
                for value in images:
                    if not re.search(match,value):
                        self.Imageurls.append(value)

            else:
                self.Imageurls=images
        else:
            return None

    #格式化圖片URL
    def formatImageUrls(self,url):
        imgParase = urlparse(url)
        if not imgParase.netloc:
            imgpath = "%s://%s/%s" %(self.urlParse.scheme,self.urlParse.netloc,imgParase.path)
        else:
            imgpath = urljoin(self.url,url)
        return imgpath
    # 保存圖片
    def downloadImage(self,url):
        print("download :" + url)
        arr = url.split('/')
        file_name = self.downloadPath +'/' + arr[-1]
        # file_name = self.downloadPath +'/' + arr[-2] +'/' + arr[-1]
        try:
            response = requests.get(url, headers=self.headers)
            with open(file_name, 'wb') as fp:
                for data in response.iter_content(128):
                    fp.write(data)
            self.start = self.start+1
            return file_name
        except:
            print("download error")

    def makeDir(self):
        if not os.path.exists(self.downloadPath):
            os.makedirs(self.downloadPath)

    def run(self):
        for img in self.Imageurls:
            self.downloadImage(self.formatImageUrls(img))

相關(guān)的頭文件引用,大家可以參考python手冊(cè)扳还,這里不再細(xì)說(shuō)才避。

新建一個(gè)單頁(yè)的download_image_page.py文件。

import argparse
from DownloadImage import DownloadImage
def getArgv():
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--uri', dest='Url', type=str, default='root', help='target Url')
    args= parser.parse_args()
    return args.Url

if __name__ == '__main__':
    url = getArgv()
    obj=DownloadImage(url,None)
    obj.run()

在控制臺(tái)中運(yùn)行:python3 download_image_page.py -i https://www.baidu.com

可以看到執(zhí)行結(jié)果氨距。

這里大家注意了桑逝,因?yàn)槲易铋_始要做的是單頁(yè)面采集,最開始設(shè)計(jì)的時(shí)候并未考慮圖片的采集控制衔蹲,這里算是一個(gè)優(yōu)化點(diǎn)。

第一階段結(jié)束,因?yàn)槠蛴呤唬静糠值恼f(shuō)明我將在下一篇中進(jìn)行講解說(shuō)明橱健。當(dāng)然,代碼已經(jīng)上傳沙廉,感興趣的朋友可以先行clone拘荡。

代碼地址:https://gitee.com/python_play/download_image

本文是“明哥陪你學(xué)Python”系列章節(jié)之一,如果你對(duì)Python有更多興趣撬陵,或有問(wèn)題珊皿,可以私信與明哥聯(lián)系,我會(huì)陪你一起解決巨税,其它相關(guān)章節(jié)可以從首頁(yè)中的“明哥陪你學(xué)Python”列表進(jìn)行查看蟋定。

本系列教程及源碼地址:點(diǎn)擊訪問(wèn)

最后:如果你正在學(xué)習(xí)Python的路上,或者準(zhǔn)備打算學(xué)習(xí)Python草添、明哥會(huì)陪著你陪你一起共同進(jìn)步驶兜!

手打不易,有用的話远寸,請(qǐng)記得關(guān)注轉(zhuǎn)發(fā)抄淑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市驰后,隨后出現(xiàn)的幾起案子肆资,更是在濱河造成了極大的恐慌,老刑警劉巖灶芝,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郑原,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡监署,警方通過(guò)查閱死者的電腦和手機(jī)颤专,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钠乏,“玉大人栖秕,你說(shuō)我怎么就攤上這事∠埽” “怎么了簇捍?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)俏拱。 經(jīng)常有香客問(wèn)我暑塑,道長(zhǎng),這世上最難降的妖魔是什么锅必? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任事格,我火速辦了婚禮惕艳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驹愚。我一直安慰自己远搪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布逢捺。 她就那樣靜靜地躺著谁鳍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪劫瞳。 梳的紋絲不亂的頭發(fā)上倘潜,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音志于,去河邊找鬼涮因。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恨憎,可吹牛的內(nèi)容都是我干的蕊退。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼憔恳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瓤荔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起钥组,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤输硝,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后程梦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體点把,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年屿附,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了郎逃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挺份,死狀恐怖褒翰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匀泊,我是刑警寧澤优训,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站各聘,受9級(jí)特大地震影響揣非,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜躲因,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一早敬、第九天 我趴在偏房一處隱蔽的房頂上張望忌傻。 院中可真熱鬧,春花似錦搞监、人聲如沸芯勘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至衡怀,卻和暖如春棍矛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抛杨。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工够委, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怖现。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓茁帽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親屈嗤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子潘拨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容