利用python多線程爬取妹子圖


一、妹子圖爬取前分析

1、首先我們還是要簡單分析一下妹子圖,第一就是要知道爬取網站的url,這里妹子圖的url就是它https://www.mzitu.com/
2、接着我們分析妹子圖的請求方式,看看它以什么方式渲染。這里妹子圖只是利用了傳統的網頁(沒有使用Ajax或js)。

image.png

3、接着點擊進入頁面,連續點擊下一頁,發現url存在一定規律,如圖,url最后4會變成5、6、7

image.png

4、再查看具體頁面的請求方式,這里使用的是GET方法,沒有什么特別的。

image.png

二、妹子圖爬取代碼布局

1、大體了解妹子圖使用的技術后,我們就可以開始嘗試爬取妹子圖了,首先我們爬取首頁面所有的”妹子“url

            response = requests.get(url, headers=headers)
            #從內容中分析出的響應內容編碼方式進行編碼
            response.encoding = response.apparent_encoding
            tree = etree.HTML(response.text)
            page = tree.xpath('//div[@class="pagenavi"]//span/text()')[-2]
            title = tree.xpath('//*[@class="main-title"]/text()')[0]
            for i in range(1, int(page) + 1):
                # url格式化后再進行重構
                new_url = url + '/{}'.format(i)
                rep = requests.get(new_url, headers=headers)
                html = etree.HTML(rep.text)
                src = html.xpath('//div[@class="main-image"]//img/@src')
                pic_src.append(src)
            self.img_queue.put((title, pic_src))

2、接着再進入特定的”妹子“頁面,再進行具體的”妹子圖片“爬取,獲取到圖片的地址信息

        response = requests.get(url, headers=headers)
        response.encoding = response.apparent_encoding
        tree = etree.HTML(response.text)
        url_lists = tree.xpath('//div[@class="postlist"]//span/a/@href')
        return url_lists

3、最后再將獲得的圖片地址下載保存在本地即可

            if self.page_queue.empty() and self.img_queue.empty():
                return
            list = self.img_queue.get(block=True)
            title, pic_srcs = list
            root = "C:\\meizitu\\"
            num = len(pic_srcs)
            pic_title = '{}【共{}頁】'.format(title, num)
            dirname = root + pic_title
            try:
                #判斷系統中是否存在同樣名稱的目錄,若沒有的話則創建一個新的目錄
                if not os.path.exists(dirname):
                    print('=' * 30 + "正在創建名為《%s》的文件夾" % pic_title)
                    os.mkdir('C:\meizitu\%s' % pic_title)
                else:
                    print("《{}》文件已經存在".format(pic_title))
                i = 1
                for pic_src in pic_srcs:
                    pic_num = pic_src[0].split('/')[-1]
                    pic = requests.get(pic_src, headers=headers).content
                    pic_name = dirname + '/' + pic_num
                    #判斷是否存在同樣名稱的圖片,沒有的話則下載
                    if not os.path.exists(pic_name):
                        print("正在《%s》文件中下載%s張圖片" % (pic_title, i))
                        #圖片要用bite的形式進行保存
                        with open(pic_name, 'wb') as fb:
                            fb.write(pic)
                            print("成功保存圖片")
                    else:
                        print("{}圖片已存在".format(pic_title + pic_num))
                    i = i + 1

注意:妹子圖具有簡單的反爬蟲設置,我們需要設置好請求頭,否則下載下來的圖片為空。

三、技術使用

上篇文章中采用單線程的方式爬取了妹子圖,效率實在是太低,本次將采用多線程的方式爬取妹子圖,並對妹子進行分類保存。

四、代碼實現

import requests
from lxml import etree
import os
import time
import threading
import re
from queue import Queue

headers = {
        'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Mobile Safari/537.36',
        'cookie': 'Hm_lvt_dbc355aef238b6c32b43eacbbf161c3c=1528013189,1528123045,1528211821,1528376611',
        'referer': 'https://www.mzitu.com/'
    }
class Producer(threading.Thread):
    def __init__(self,page_queue,img_queue,*args,**kwargs):
        super(Producer,self).__init__(*args,*kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue

    def run(self):
        while True:
            if self.page_queue.empty():
                break
            url = self.page_queue.get()
            self.get_img_src(url)


    def get_img_src(self,url):
        try:
            pic_src = []
            response = requests.get(url, headers=headers)
            #從內容中分析出的響應內容編碼方式進行編碼
            response.encoding = response.apparent_encoding
            tree = etree.HTML(response.text)
            page = tree.xpath('//div[@class="pagenavi"]//span/text()')[-2]
            title = tree.xpath('//*[@class="main-title"]/text()')[0]
            for i in range(1, int(page) + 1):
                # url格式化后再進行重構
                new_url = url + '/{}'.format(i)
                rep = requests.get(new_url, headers=headers)
                rep.encoding = rep.apparent_encoding
                html = etree.HTML(rep.text)
                src = html.xpath('//div[@class="main-image"]//img/@src')[0]
                pic_src.append(src)
            print(title,pic_src)
            self.img_queue.put((title, pic_src))
        except:
            print("爬取妹子圖片地址失敗")


class Consumer(threading.Thread):
    def __init__(self,page_queue,img_queue,*args,**kwargs):
        super(Consumer,self).__init__(*args,*kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue

    def run(self):
        while True:
            if self.page_queue.empty() and self.img_queue.empty():
                return
            list = self.img_queue.get(block=True)
            title, pic_srcs = list
            root = "C:\\meizitu\\"
            num = len(pic_srcs)
            pic_title = '{}【共{}頁】'.format(title, num)
            dirname = root + pic_title
            try:
                #判斷系統中是否存在同樣名稱的目錄,若沒有的話則創建一個新的目錄
                if not os.path.exists(dirname):
                    print('=' * 30 + "正在創建名為《%s》的文件夾" % pic_title)
                    os.mkdir('C:\meizitu\%s' % pic_title)
                else:
                    print("《{}》文件已經存在".format(pic_title))
                i = 1
                for pic_src in pic_srcs:
                    pic_num = pic_src.split('/')[-1]
                    pic = requests.get(pic_src, headers=headers).content
                    pic_name = dirname + '/' + pic_num
                    #判斷是否存在同樣名稱的圖片,沒有的話則下載
                    if not os.path.exists(pic_name):
                        print("正在《%s》文件中下載%s張圖片" % (pic_title, i))
                        #圖片要用bite的形式進行保存
                        with open(pic_name, 'wb') as fb:
                            fb.write(pic)
                            print("成功保存圖片")
                    else:
                        print("{}圖片已存在".format(pic_title + pic_num))
                    i = i + 1
            except:
                print('{}爬取失敗'.format(dirname))


def get_all_host_url(url):
    try:
        response = requests.get(url, headers=headers)
        response.encoding = response.apparent_encoding
        tree = etree.HTML(response.text)
        url_lists = tree.xpath('//div[@class="postlist"]//span/a/@href')
        return url_lists
    except:
        print("爬取首頁妹子地址失敗")


if __name__ == '__main__':
    base_url = 'https://www.mzitu.com/page/{}/'
    page_queue = Queue(100)
    img_queue = Queue(500)
    for i in range(1,4):
        url = base_url.format(i)
        url_lists = get_all_host_url(url)
        print("第%d頁的圖片地址%s"%(i,url_lists))
        # time.sleep(1)
        for url_list in url_lists:
            page_queue.put(url_list)
    for x in range(10):
        t = Producer(page_queue,img_queue)
        t.start()
    for x in range(10):
        t = Consumer(page_queue,img_queue)
        t.start()


五、效果圖

image.png


免責聲明!

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



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