python 多線程爬取網(wǎng)站圖片(詳解)

1網(wǎng)站整個(gè)圖片的意思是铆帽,網(wǎng)站有用的圖片胞枕,廣告推薦位,等等除外
萌新上路娩嚼,老司機(jī)請(qǐng)略過(guò)

第一步找出網(wǎng)站url分頁(yè)的規(guī)律

選擇自己要爬取的分類(lèi)(如果要所有的圖片可以不選蘑险,顯示的就是所有的照片,具體怎么操作請(qǐng)根據(jù)實(shí)際情況進(jìn)行改進(jìn))


QQ截圖20190620144258.png

url地址的顯示


QQ截圖20190620144349.png

看分頁(yè)的url規(guī)律


QQ截圖20190620144417.png

url地址的顯示



由此可知分頁(yè)的參數(shù)就是 page/頁(yè)數(shù)

第二步獲取總頁(yè)數(shù)和進(jìn)行url請(qǐng)求

1判斷頁(yè)數(shù)的幾種辦法岳悟,1最直接的從瀏覽器上眼看 2先數(shù)一頁(yè)完整的網(wǎng)頁(yè)一共有多少套圖片佃迄,假如有15套,如果有一頁(yè)少于15套那它就是最后一頁(yè)(不排除最后一頁(yè)也是15張)3和第一種方法差不多區(qū)別在于是用程序來(lái)查看總頁(yè)數(shù)的贵少,4不管多少頁(yè)寫(xiě)個(gè)http異常捕獲呵俏,如果get請(qǐng)求返回的是404那就是已經(jīng)爬完了 5頁(yè)面捕獲下一頁(yè),如果沒(méi)有下一頁(yè)就證明爬取完成(但是有些數(shù)據(jù)少的頁(yè)面就沒(méi)有下一頁(yè)這個(gè)標(biāo)簽春瞬,這就尷尬了)柴信,這里以第三種方法為例
由圖可知總頁(yè)數(shù)

you

用程序捕捉頁(yè)數(shù)
由上圖可知翻頁(yè)的布局在一個(gè)div里 正常情況下包括 上一頁(yè)1 2 3 4 5 ... 101下一頁(yè) 一共9個(gè)選擇項(xiàng)那么倒數(shù)第二個(gè)就是總頁(yè)數(shù)
通過(guò)xpath獲取標(biāo)簽的規(guī)則
這里點(diǎn)擊右鍵copy copy xpath
QQ截圖20190620150800.png

然后用到一個(gè)谷歌插件 xpath
剛才

把剛才復(fù)制的xpath 粘貼進(jìn)去


QQ截圖20190620150845.png

可以看到獲取的是總頁(yè)數(shù)101 但是我們認(rèn)為的是標(biāo)簽的倒數(shù)第二個(gè)才是總頁(yè)數(shù),所以我們獲取的是一個(gè)列表而不是一個(gè)確定的值宽气,因?yàn)榉?yè)的便簽的個(gè)數(shù)是會(huì)變的但是總頁(yè)數(shù)一直都是最后一個(gè)*(這里以我測(cè)試的網(wǎng)站為例随常,,一切以實(shí)際情況為準(zhǔn))
獲取翻頁(yè)的列表


QQ截圖20190620150859.png

調(diào)用查找總頁(yè)數(shù)的方法返回第二個(gè)值就是總頁(yè)數(shù)


QQ截圖20190620152157.png

并做個(gè)判斷如果頁(yè)數(shù)大于總頁(yè)數(shù)的時(shí)候跳出循環(huán)

頁(yè)數(shù)判斷完畢進(jìn)行圖片爬取

一個(gè)頁(yè)面有20組圖片 通過(guò)xpath獲取這10組圖片的鏈接并進(jìn)行請(qǐng)求
QQ截圖20190620152830.png

一共四步
1訪問(wèn)第一頁(yè)抓取一共多少頁(yè)萄涯,


QQ截圖20190620183133.png

第二步抓取頁(yè)面10組圖詳情頁(yè)的連接


QQ截圖20190620183139.png

第三 請(qǐng)求第一組圖片的詳情頁(yè)獲取多少?gòu)垐D片绪氛,


![QQ截圖20190620183154.png](https://upload-images.jianshu.io/upload_images/18295040-d11db768fd21ecf0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

第四步請(qǐng)求每一頁(yè)的詳情頁(yè)并保存圖片,


QQ截圖20190620183154.png

其實(shí)可以整合成兩步涝影,我這樣寫(xiě)等于多請(qǐng)求了兩次枣察,懶的改了,有興趣的話可以自己改一下

QQ截圖20190620183420.png

看我嗶嗶了那么多燃逻,其實(shí)沒(méi)啥用 有用的才開(kāi)始 多線程

根據(jù)你的網(wǎng)速如果下一張圖片沒(méi)問(wèn)題序目,那么100張100萬(wàn)張呢?
整個(gè)http訪問(wèn)的過(guò)程最慢的就是請(qǐng)求圖片鏈接進(jìn)行保存伯襟,這是最慢的一步猿涨,因?yàn)閳D片的資源大(這是廢話)
假如一組套圖有70張,保存一張就要3秒姆怪,70張是多少秒叛赚,我不知道(小學(xué)畢業(yè)),稽揭,俺附,但是如果開(kāi)了多線程,保存一張要3秒保存100張也要3秒(原理就不解釋了溪掀,大家都懂事镣,上代碼了)

開(kāi)啟隊(duì)列


QQ截圖20190620184013.png

整合 圖片詳情頁(yè)的url添加到隊(duì)列里 并開(kāi)啟進(jìn)程(其實(shí)可以一個(gè)for循環(huán)完成,但是我試了幾次老是添加的多了 所以添加隊(duì)列和 開(kāi)啟進(jìn)程就分開(kāi)揪胃,你可以試試用一個(gè)循環(huán))


QQ截圖20190620184041.png

每個(gè)線程結(jié)束后刪除一個(gè)相應(yīng)的隊(duì)列
QQ截圖20190620184121.png

(由于mac 和win的路徑方式不同 我就沒(méi)有寫(xiě)如果沒(méi)有創(chuàng)建文件夾 就自動(dòng)創(chuàng)建蛮浑,所以運(yùn)行之前請(qǐng)?jiān)诖a的同級(jí)目錄創(chuàng)建一個(gè)imgs文件夾)
看看速度的對(duì)比

多線程的前提是對(duì)訪問(wèn)的頻率沒(méi)有限制唠叛,一般的小網(wǎng)站和見(jiàn)不得人的網(wǎng)站都沒(méi)有這樣限制只嚣,所以你懂得沮稚!
QQ截圖20190620190027.png

爬取相同的一組圖片


QQ截圖20190620190256.png

普通版

import requests
from lxml import etree
import random
import threading
from  time import sleep
from queue import Queue
class ImgSpider() :
    def __init__(self):
        self.urls = 'http://www.jitaotu.com/tag/meitui/page/{}'
        self.deatil = 'http://www.jitaotu.com/xinggan/{}'
        self.headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Cache-Control': 'max-age=0',
            'Cookie': 'UM_distinctid=16b7398b425391-0679d7e790c7ad-3e385b04-1fa400-16b7398b426663;Hm_lvt_7a498bb678e31981e74e8d7923b10a80=1561012516;CNZZDATA1270446221 = 1356308073 - 1561011117 - null % 7C1561021918;Hm_lpvt_7a498bb678e31981e74e8d7923b10a80 = 1561022022',
            'Host': 'www.jitaotu.com',
            'If-None-Match': '"5b2b5dc3-2f7a7"',
            'Proxy-Connection': 'keep-alive',
            'Referer': 'http://www.jitaotu.com/cosplay/68913_2.html',
            'Upgrade-Insecure-Requests': '1',
             'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
                        }
        self.url_queue = Queue()

    def pages(self):
        #總頁(yè)數(shù)
        response = requests.get(self.urls.format(2))
        strs = response.content.decode()
        html = etree.HTML(strs)
        page = html.xpath('/html/body/section[1]/nav/div/a/text()')
        return page[-2]

    def html_list(self, page):
        #頁(yè)面組圖的連接
        print(self.urls.format(page))
        response = requests.get(self.urls.format(page))
        strs = response.content.decode()
        html = etree.HTML(strs)
        page = html.xpath('/html/body/section[1]/div/ul/li/div[1]/a/@href')
        return page

    def detail_page(self, imgde):
        #總圖片數(shù)
        response = requests.get(self.deatil.format(imgde))
        strs = response.content.decode()
        html = etree.HTML(strs)
        page = html.xpath("http://*[@id='imagecx']/div[4]/a[@class='page-numbers']/text()")
        return page[-1]
    def detail_list(self, imgde, page):
        #圖片詳情頁(yè)連接
        #截取鏈接關(guān)鍵碼
        urls = imgde[-10:-5]
        print('開(kāi)始訪問(wèn)圖片頁(yè)面并抓取圖片地址保存')
        for i in range(int(page)):
            print(self.deatil.format(urls+'_'+str(i+1)+'.html'))
            response = requests.get(self.deatil.format(urls+'_'+str(i+1)+'.html'))
            strs = response.content.decode()
            html = etree.HTML(strs)
            imgs = html.xpath('//*[@id="imagecx"]/div[3]/p/a/img/@src')
            #保存圖片
            self.save_img(imgs)

    def save_img(self, imgs):
        print(imgs[0]+'?tdsourcetag=s_pcqq_aiomsg')
        response = requests.get(imgs[0], headers=self.headers)
        strs = response.content
        s = random.sample('zyxwvutsrqponmlkjihgfedcba1234567890', 5)
        a = random.sample('zyxwvutsrqponmlkjihgfedcba1234567890', 5)
        with open("./imgs/" + str(a) + str(s) + ".jpg", "wb") as f:
            f.write(strs)
        print("保存圖片")
        return
    def run(self):
        page = 1
        # 獲取總頁(yè)數(shù)
        pageall = self.pages()
        print('總頁(yè)數(shù)'+str(pageall))
        while True:
            print('訪問(wèn)第' + str(page)+'頁(yè)')
            #訪問(wèn)頁(yè)面,獲取10組圖片的詳情頁(yè)鏈接
            html_list = self.html_list(page)
            #訪問(wèn)圖片的詳情頁(yè)
            s =1
            for htmls in html_list:
                print('訪問(wèn)第'+str(page)+'頁(yè)第'+str(s)+'組')
                imgdetalpage = self.detail_page(htmls)
                # 址遍歷詳情頁(yè)請(qǐng)求獲取圖片地
                print('第' + str(page) + '頁(yè)第' + str(s) + '組有'+str(imgdetalpage)+'張圖片')
                self.detail_list(htmls, imgdetalpage)
                s += 1
            page += 1
            if page > pageall:
                print('爬取完畢 退出循環(huán)')
                return

if __name__ == '__main__':
    Imgs = ImgSpider()
    Imgs.run()

多線程

import requests
from lxml import etree
import random
import threading
from  time import sleep
from queue import Queue
class ImgSpider() :
    def __init__(self):
        self.urls = 'http://www.jitaotu.com/tag/meitui/page/{}'
        self.deatil = 'http://www.jitaotu.com/xinggan/{}'
        self.headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Cache-Control': 'max-age=0',
            'Cookie': 'UM_distinctid=16b7398b425391-0679d7e790c7ad-3e385b04-1fa400-16b7398b426663;Hm_lvt_7a498bb678e31981e74e8d7923b10a80=1561012516;CNZZDATA1270446221 = 1356308073 - 1561011117 - null % 7C1561021918;Hm_lpvt_7a498bb678e31981e74e8d7923b10a80 = 1561022022',
            'Host': 'www.jitaotu.com',
            'If-None-Match': '"5b2b5dc3-2f7a7"',
            'Proxy-Connection': 'keep-alive',
            'Referer': 'http://www.jitaotu.com/cosplay/68913_2.html',
            'Upgrade-Insecure-Requests': '1',
             'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
                        }
        self.url_queue = Queue()

    def pages(self):
        response = requests.get(self.urls.format(2))
        strs = response.content.decode()
        html = etree.HTML(strs)
        page = html.xpath('/html/body/section[1]/nav/div/a/text()')
        return page[-2]

    def html_list(self, page):
        print(self.urls.format(page))
        response = requests.get(self.urls.format(page))
        strs = response.content.decode()
        html = etree.HTML(strs)
        page = html.xpath('/html/body/section[1]/div/ul/li/div[1]/a/@href')
        return page

    def detail_page(self, imgde):
        response = requests.get(self.deatil.format(imgde))
        strs = response.content.decode()
        html = etree.HTML(strs)
        page = html.xpath("http://*[@id='imagecx']/div[4]/a[@class='page-numbers']/text()")
        return page[-1]
    def detail_list(self, imgde, page):
        #截取鏈接關(guān)鍵碼
        urls = imgde[-10:-5]
        print('開(kāi)始訪問(wèn)圖片頁(yè)面并抓取圖片地址保存')
        for i in range(int(page)):
            print(self.deatil.format(urls + '_' + str(i + 1) + '.html'))
            urlss = self.deatil.format(urls + '_' + str(i + 1) + '.html')
            self.url_queue.put(urlss)
        for i in range(int(page)):
            t_url = threading.Thread(target=self.More_list)
            # t_url.setDaemon(True)
            t_url.start()
        self.url_queue.join()
        print('主線程結(jié)束進(jìn)行下一個(gè)')
    def More_list(self):
        urls = self.url_queue.get()
        response = requests.get(urls)
        strs = response.content.decode()
        html = etree.HTML(strs)
        imgs = html.xpath('//*[@id="imagecx"]/div[3]/p/a/img/@src')
        # 保存圖片
        self.save_img(imgs)
    def save_img(self, imgs):
        try:
            print(imgs[0])
            response = requests.get(imgs[0], headers=self.headers)
        except:
            print('超時(shí)跳過(guò)')
            self.url_queue.task_done()
            return
        else:
            strs = response.content
            s = random.sample('zyxwvutsrqponmlkjihgfedcba1234567890', 5)
            a = random.sample('zyxwvutsrqponmlkjihgfedcba1234567890', 5)
            with open("./imgsa/" + str(a) + str(s) + ".jpg", "wb") as f:
                f.write(strs)
            print("保存圖片")
            self.url_queue.task_done()
            return
    def run(self):
        page = 1
        # 獲取總頁(yè)數(shù)
        pageall = self.pages()
        print('總頁(yè)數(shù)'+str(pageall))
        while True:
            print('訪問(wèn)第' + str(page)+'頁(yè)')
            #訪問(wèn)頁(yè)面册舞,獲取10組圖片的詳情頁(yè)鏈接
            html_list = self.html_list(page)
            #訪問(wèn)圖片的詳情頁(yè)
            s =1
            for htmls in html_list:
                print('訪問(wèn)第'+str(page)+'頁(yè)第'+str(s)+'組')
                imgdetalpage = self.detail_page(htmls)
                # 址遍歷詳情頁(yè)請(qǐng)求獲取圖片地
                print('第' + str(page) + '頁(yè)第' + str(s) + '組有'+str(imgdetalpage)+'張圖片')
                self.detail_list(htmls, imgdetalpage)
                s += 1
            page += 1
            if page > pageall:
                print('爬取完畢 退出循環(huán)')
                return

if __name__ == '__main__':
    Imgs = ImgSpider()
    Imgs.run()

看不懂不理解的可以問(wèn)我蕴掏,我也是新手可以交流交流 qq1341485724

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市调鲸,隨后出現(xiàn)的幾起案子盛杰,更是在濱河造成了極大的恐慌,老刑警劉巖藐石,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件即供,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡于微,警方通過(guò)查閱死者的電腦和手機(jī)逗嫡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)株依,“玉大人驱证,你說(shuō)我怎么就攤上這事×低螅” “怎么了抹锄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)荠藤。 經(jīng)常有香客問(wèn)我伙单,道長(zhǎng),這世上最難降的妖魔是什么哈肖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任吻育,我火速辦了婚禮,結(jié)果婚禮上牡彻,老公的妹妹穿的比我還像新娘扫沼。我一直安慰自己,他們只是感情好庄吼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布缎除。 她就那樣靜靜地躺著,像睡著了一般总寻。 火紅的嫁衣襯著肌膚如雪器罐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天渐行,我揣著相機(jī)與錄音轰坊,去河邊找鬼铸董。 笑死,一個(gè)胖子當(dāng)著我的面吹牛肴沫,可吹牛的內(nèi)容都是我干的粟害。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼颤芬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悲幅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起站蝠,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤汰具,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后菱魔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體留荔,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年澜倦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了聚蝶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肥隆,死狀恐怖既荚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情栋艳,我是刑警寧澤恰聘,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站吸占,受9級(jí)特大地震影響晴叨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜矾屯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一兼蕊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧件蚕,春花似錦孙技、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至妄痪,卻和暖如春哈雏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工裳瘪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留土浸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓彭羹,卻偏偏與公主長(zhǎng)得像黄伊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子皆怕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

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