三步爬取半次元熱門圖片


前言:

邊學習,邊創造是一件開心的事情,因為你會清楚的認識到自己的狀態,以及那充滿內心的成就感,因此從寫爬蟲開始學習python是一個簡單粗暴的提升路線,不知不覺了解很多東西

這里以半次元為例對爬蟲整體流程以及部分細節進行簡單匯總,如果有不正確的地方還請大家指出

 

---------------------------------------分割線----------------------------------------------

 

話不多說,我們打開待爬的頁面

會發現這個頁面運用了ajax技術,只有向下滑動才會觸發請求,如果我們按照現在頁面地址爬取,也只能是得到部分相冊,既然是ajax,這里我們打開F12  網絡工具 刷新頁面

滑動到底部,會發現又多了四條GET請求,查看請求的url ,會發現這些url之間不同的只有 p 的值 p=1, p=2, p=3, p=4,p=5

知道了這些,就可以開始編寫python文件,請求頁面內容了

1、創建一個AlbumUrl類 , 開始獲取頁面所有相冊的url


 

import requests
from bs4 import BeautifulSoup


album_urls = [] #相冊url列表

headers = {
"Host": "bcy.net",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:63.0) Gecko/20100101 Firefox/63.0"
}


#獲取相冊url
class AlbumUrl():

def __init__(self, url, url2):
self.url = url
self.url2 = url2
def page(self, start, end):

for i in range(start, end):

url = self.url % i
response = requests.get(url, headers=headers)

response.encoding = 'utf-8'
after_bs = BeautifulSoup(response.text, 'lxml')

li_s = after_bs.find_all('li', class_='js-smallCards _box') #提取li標簽內容

for li in li_s:
list_a = li.find_all('a', class_='db posr ovf') #提取a標簽內容
for a in list_a:
a_href = a.get('href') #取出部分url 進行拼接
album_urls.append(self.url2 + a_href)



if __name__ == '__main__':
url = 'https://bcy.net/coser/index/ajaxloadtoppost?p=%s'
url2 = 'https://bcy.net'
spider = AlbumUrl(url, url2)
spider.page(1, 6) #分析出來的頁數

 
        

編寫完畢,運行一下, 無誤,把這些相冊url保存到列表,等待逐個分析里面的圖片內容

 

2、新建一個ImgUrl類  繼承threading.Thread類 因為這里我打算用多線程, 導入相應的模塊


 

import requests
from bs4 import BeautifulSoup
import threading
import re
import time


album_urls = [] #相冊url列表
all_img_urls = [] #所有圖片

lock = threading.Lock() #互斥鎖

headers = {
"Host": "bcy.net",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:63.0) Gecko/20100101 Firefox/63.0"
}

#抓取每個相冊里面圖片url
class ImgUrl(threading.Thread):

def run(self):

while len(album_urls) > 0: #只要不為空 就一直抓取
lock.acquire() #上鎖
album_url = album_urls.pop()
lock.release() # 解鎖

try:
response = requests.get(album_url, headers=headers, timeout=3)
response.encoding = 'utf-8'
re_obj = re.compile('"path(.*?)w650', re.S)
r = (re_obj.findall(response.text))
print("正在分析" + album_url)
after_bs = BeautifulSoup(response.text, 'lxml')

lock.acquire() # 上鎖
for title in after_bs.find_all('title'):
global album_title
album_title = (str(title.get_text())).split('-')[0]

for i in range(len(r)):
img_url = r[i].replace(r'\\u002F', '/')[5:] + 'w650.jpg' #拼接字符串,完成每張圖片url

img_dict = {album_title: img_url} #相冊名和圖片url存入字典
all_img_urls.append(img_dict)
print(album_title + '獲取成功')

lock.release() # 解鎖
time.sleep(0.5)
except:
pass



#獲取相冊url
class AlbumUrl():

def __init__(self, url, url2):
self.url = url
self.url2 = url2
def page(self, start, end):

for i in range(start, end):

url = self.url % i
response = requests.get(url, headers=headers)

response.encoding = 'utf-8'
after_bs = BeautifulSoup(response.text, 'lxml')

li_s = after_bs.find_all('li', class_='js-smallCards _box') #提取li標簽內容

for li in li_s:
list_a = li.find_all('a', class_='db posr ovf') #提取a標簽內容
for a in list_a:
a_href = a.get('href') #取出部分url 進行拼接
album_urls.append(self.url2 + a_href)



if __name__ == '__main__':
url = 'https://bcy.net/coser/index/ajaxloadtoppost?p=%s'
url2 = 'https://bcy.net'
spider = AlbumUrl(url, url2)
spider.page(1, 5) #分析出來的頁數
for x in range(5):
t = ImgUrl()
t.start()

 
        

# 這里需要注意的是,圖片的url並不是直接暴露的,里面慘雜了一些字符串,這里我們運用正則來進行篩選,然后用replace進行相應字符串的替換

開五個線程運行一下, 無誤,可以准備寫入文件了

 

 3、新建一個Download類  同樣繼承threading.Thread類 ,用於下載圖片到本地


 

 

import os

import requests
from bs4 import BeautifulSoup
import threading
import re
import time


album_urls = [] #相冊url列表
all_img_urls = [] #所有圖片

lock = threading.Lock() #互斥鎖

headers = {
"Host": "bcy.net",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:63.0) Gecko/20100101 Firefox/63.0"
}




#抓取每個相冊里面圖片url
class ImgUrl(threading.Thread):

def run(self):

while len(album_urls) > 0: #只要不為空 就一直抓取
lock.acquire() #上鎖
album_url = album_urls.pop()
lock.release() # 解鎖

try:
response = requests.get(album_url, headers=headers, timeout=3)
response.encoding = 'utf-8'
re_obj = re.compile('"path(.*?)w650', re.S)
r = (re_obj.findall(response.text))
print("正在分析" + album_url)
after_bs = BeautifulSoup(response.text, 'lxml')

lock.acquire() # 上鎖
for title in after_bs.find_all('title'):
global album_title
album_title = (str(title.get_text())).split('-')[0]

for i in range(len(r)):
img_url = r[i].replace(r'\\u002F', '/')[5:] + 'w650.jpg' #拼接字符串,完成每張圖片url

img_dict = {album_title: img_url}
all_img_urls.append(img_dict)
print(album_title + '獲取成功')

lock.release() # 解鎖
time.sleep(0.5)
except:
pass

num = 0
#下載圖片
class Download(threading.Thread):

def run(self):

while True:

lock.acquire() #上鎖
if len(all_img_urls) == 0:
lock.release() #解鎖
continue
else:
img_dict = all_img_urls.pop()
lock.release() #解鎖

for key, values in img_dict.items(): #把鍵值取出

try:
os.mkdir(key)
print(key + '創建成功')
except:
pass
global num
num += 1
filename = str(num) + '.' + str(values).split('.')[-1] #給每張圖片重新命名
filepath = os.path.join(key, filename)
session = requests.Session() #這里使用會話請求
http_obj = requests.adapters.HTTPAdapter(max_retries=20) #每次連接的最大失敗重試次數
session.mount('https://', http_obj) #增加請求類型
session.mount('http://', http_obj)
try:
response = session.get(values) #讀取會話

with open(filepath, 'wb', buffering=4*1024) as image:
image.write(response.content)
image.close()

print(filepath + '下載完畢')
except:
pass

time.sleep(0.1)


#獲取相冊url
class AlbumUrl():

def __init__(self, url, url2):
self.url = url
self.url2 = url2
def page(self, start, end):

for i in range(start, end):

url = self.url % i
response = requests.get(url, headers=headers)

response.encoding = 'utf-8'
after_bs = BeautifulSoup(response.text, 'lxml')

li_s = after_bs.find_all('li', class_='js-smallCards _box') #提取li標簽內容

for li in li_s:
list_a = li.find_all('a', class_='db posr ovf') #提取a標簽內容
for a in list_a:
a_href = a.get('href') #取出部分url 進行拼接
album_urls.append(self.url2 + a_href)



if __name__ == '__main__':
url = 'https://bcy.net/coser/index/ajaxloadtoppost?p=%s'
url2 = 'https://bcy.net'
spider = AlbumUrl(url, url2)
spider.page(1, 5) #分析出來的頁數
threads = []
for x in range(5):
t = ImgUrl()
t.start()
threads.append(t)

for tt in threads: #設置堵塞,避免線程搶先
tt.join()

for x in range(5):
down = Download()
down.start()

#這里需要注意的是,請求圖片的時候不能直接請求,否則會發生異常,這里用會話請求並設置相應的類型

好,開五個線程運行一下,看結果如何

 

 

到此為止,三步爬取半次元熱門圖片,演示完畢,其實不光是熱門,我們也可以換成別的鏈接進行分析爬取,包括全站,整體原理都是類似的,一些請求細節需要理解

還有,bs4簡直就是爬蟲神器

 


免責聲明!

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



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