一、妹子圖爬取前分析
1、首先我們還是要簡單分析一下妹子圖,第一就是要知道爬取網站的url,這里妹子圖的url就是它https://www.mzitu.com/
2、接着我們分析妹子圖的請求方式,看看它以什么方式渲染。這里妹子圖只是利用了傳統的網頁(沒有使用Ajax或js)。
3、接着點擊進入頁面,連續點擊下一頁,發現url存在一定規律,如圖,url最后4會變成5、6、7
4、再查看具體頁面的請求方式,這里使用的是GET方法,沒有什么特別的。
二、妹子圖爬取代碼布局
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()