我學爬蟲一直有一個夢想,就是想真正達到可見即可爬的態度,所以我一直在嘗試找一種方式去搞定它,從最開始的模擬接口去交接數據,但是我發現這行不通,然而條條大路通羅馬,後浪又怎麼能這麼消逝在沙灘上,直到我想了一個問題,爲什麼我們每次保存圖片都是JPG格式,爲什麼不是PNG格式? 那我就查閱了相關文獻,終於,我成功了,我用另類的方式搞定了這些限制次數的圖庫,這是一次大膽的創意,可以適用在任何圖站,希望對大家有幫助!
都2020年了,爬蟲黨還在爲了圖片的下載質量煩惱嗎?還是隻會下載JPG圖片?那我有一種另類方式可以幫助你真正的白嫖高質量圖片,肝了一個禮拜的乾貨,絕對能改變你對爬蟲的看法和思考,原來爬蟲這麼有趣,也不會這麼思維固然,代碼方式儘量簡單一點,讓大家能看懂,加油各位!
防止有人說我標題黨,我先給圖致敬,絕對是4k以上畫質,作假的剁手!
技術分析:
爬蟲還用JPG?
這個另類技術設計到一點值得我們思考,我們每次爬蟲保存的圖片都是默認JPG,爲什麼
- 先不管他們的定義是什麼,簡單來說,JPG就是一種有損壓縮技術,在符合所需畫質的前提下,儘可能的提高壓縮比,來減少儲存空間,所以傳輸速度快,文件小,畫質低,這也就是網站爲什麼都用JPG來存儲圖片了。
- 而PNG我定義就是一種
大保健
,他能保存完整的畫質,也就是相對無損壓縮技術,缺點也就是存儲空間大,保留了很多原始通道,所以網站不採用,爬蟲教學也不採用。 - 而位圖的定義,理論上是可以無限放大的,JPG作爲位圖自然是糟糕的選擇,而PNG確實是一個完美的搭檔,這裏我就
鑽了這個空子
,用了這種方式搞定了高清圖庫。 - 採用這種方式,我不是吹噓我有多厲害,可能有人想過,但是我只是分享這種方式給更多的朋友,改善他們的固有思維,如果你想要小圖片的話保存JPG也是很好的選擇,而我喜歡
高清大圖
,我採用的是PIL庫的Image類的操作,下面我會給出很好的解釋。這是一個全站點圖片爬取的爬蟲,速度可能有點慢,我盡力使用了線程池,謝謝理解!
技術關鍵代碼:
存儲爲位圖,然後無損放大圖片,就可以得到我們的效果了,還不懂的留言問我。
with open(''.join(name) + '.png', 'wb') as fw:
fw.write(rr.content)
img = Image.open(''.join(name) + '.png')
img = img.resize((4000, 2000), Image.ANTIALIAS) # 改變大小 抗鋸齒
# print(img.size)
img.save(''.join(name) + '.png', quality=95) # 質量分數 95
如果看到這裏覺得對你有幫助的,希望給個關注和贊,這是對我最大的支持!
項目技術:
- 還是熟悉的網站 彼岸圖網 這個網站質量挺高的,但是有個缺點就是限制次數,所以這次就決定搞它了,其他網站也是大同小異之作。
- 總的步驟分了幾大模塊,設計到的技術點不是很多,requests和xpath 作爲爬蟲基礎技術,還有Image類和線程池技術,然後文件的os庫也是必須的。
- 我保證說的很清楚,我們就開始實踐吧!
獲取分組網址和標題:
- 我們這次做的是一個全站點爬取,所以得考慮分組問題,這裏我們編寫爬蟲獲取箭頭所指向的信息,我保存爲一個列表,方便我接下來的操作。
代碼:
def get_groups(url, headers): # 獲得重要信息
"""根據傳入的最初網址和標題頭,獲得每個專欄的網址和標題"""
r = requests.get(url, headers=headers)
r.encoding = r.apparent_encoding # 轉換編碼
if r.status_code == 200:
html = etree.HTML(r.text)
html = etree.tostring(html)
html = etree.fromstring(html)
url_list = html.xpath(r"//div[@class='classify clearfix']//a/@href") # 獲得網頁分組的url
name = html.xpath(r"//div[@class='classify clearfix']//a/text()") # 獲得網頁分組的標題
else:
print('請求錯誤!')
return name, url_list # 把分組標題和分組網址回溯
開始下載選擇:
- 獲取成功這些我們就開始選擇下載,更友好和人性化:
這裏我就簡單的寫寫哈,別介意:
代碼如下:
def begin_down(title, url, headers): # 下載選擇
"""這裏的參數爲剛獲取的標題和網址還有請求頭"""
print('白嫖方式下載高清圖片'.center(30, '-'))
for i, j in enumerate(title):
print(i, '\t\t\t\t\t', j)
inp = int(input('輸入下載選項:'))
# print(title[inp], url[inp])
get_image_1st(title[inp], url[inp], headers) # 調用第一頁的網址進行下載
get_image(title[inp], url[inp], headers) # 下載剩下的所有頁
這裏獲取的網址需要到下一步進行拼接,根據我的觀察,分組網站的第一頁和其他頁網址不相連,沒有規律可循,所以我寫了爬取第一頁和爬取其他頁二個函數來獲取圖片,這裏下面我也會說。
獲取圖片網址:
- 隨後我們點擊圖片進入這樣頁面,看我箭頭標註,我們要獲取href的內容,而不是img中的網址,img裏面的是縮小圖片,沒什麼質量,看多了還傷眼睛,不值得,我給你大圖,你也爽。編寫代碼,獲取href然後網址拼接這個樣子 http://pic.netbian.com/tupian/17781.html 就可以打開了。
代碼:
def get_image_1st(title, url, headers): # 得到第一頁的圖片網址
url_1st = 'http://pic.netbian.com/' + url # 拼接分組網址
r = requests.get(url_1st, headers)
if r.status_code == 200:
html = etree.HTML(r.text)
html = etree.tostring(html)
html = etree.fromstring(html)
page_url = html.xpath(r'//ul[@class="clearfix"]//li/a/@href') # 獲得每張圖片的真實網址
# print(page_url)
page_url = ['http://pic.netbian.com' + i for i in page_url] # 網址拼接
pool_down(title, page_url, headers) # 調用圖片下載函數 下載選擇頁的 第一頁全部圖片,因爲第一頁網址特殊
def get_image(title, url, headers): # 得到其他頁的圖片網址
"""找其他頁的網址,然後找到每張圖片的點擊圖片網址"""
pages_url = []
for i in range(2, 10): # 我們假定最大翻頁爲10頁
other_url = 'http://pic.netbian.com' + url + 'index_' + str(i) + '.html' # 拼接網址
# print(other_url)
r = requests.get(other_url, headers=headers) # 嘗試請求第二頁 獲得圖片的點擊網址
if r.status_code == 200:
html = etree.HTML(r.text)
html = etree.tostring(html)
html = etree.fromstring(html)
page_url = html.xpath(r'//ul[@class="clearfix"]//li/a/@href') # 獲得每張圖片的真實網址
page_url = ['http://pic.netbian.com' + i for i in page_url] # 網址拼接
pages_url.append(page_url)
pool_down(title, pages_url, headers) # 調用下載
獲得下載網址:
- 然後我們打開圖片,通過控制檯,可以得到我下圖的畫面:
這裏注意一點,我們獲取的是src裏面的圖片網址,這個質量更高一點,便於我們修改畫質,這裏使用到了線程池和Image的使用,簡單使用起來不是很難。
代碼如下:
def image_down(title, page_url, headers): # 下載圖片
if not os.path.exists(title + '//'):
os.mkdir(title + '//')
os.chdir(title + '//')
else:
os.chdir(title + '//')
for i, j in enumerate(page_url): # 遍歷第一頁的圖表列表
r = requests.get(j, headers=headers) # 請求這個圖片網址
if r.status_code == 200:
r.encoding = r.apparent_encoding # 修改編碼
html = etree.HTML(r.text)
html = etree.tostring(html)
html = etree.fromstring(html) # 以上搭建xpath對象
url = html.xpath(r'//a[@id="img"]/img/@src')
name = html.xpath(r'//a[@id="img"]/img/@title')
rr = requests.get('http://pic.netbian.com' + ''.join(url), headers=headers)
if rr.status_code == 200: # 請求下載圖片網址
rr.encoding = rr.apparent_encoding # 修改編碼
with open(''.join(name) + '.png', 'wb') as fw:
fw.write(rr.content)
img = Image.open(''.join(name) + '.png')
img = img.resize((4000, 2000), Image.ANTIALIAS) # 改變大小 抗鋸齒
# print(img.size)
img.save(''.join(name) + '.png', quality=95) # 質量分數 95
print(f'{title} 中第 {i + 1} 張下載完成!')
else:
print('錯誤啦')
def pool_down(title, page_url, headers): # 線程下載
# print(title, len(page_url))
path = 'D://彼岸圖庫//'
# 創建總的文件夾
if not os.path.exists(path):
os.mkdir(path)
os.chdir(path)
else:
os.chdir(path)
# 創建一個多線程下載
pool = Pool(6) # 一次6下
if len(page_url) > 2: # 如果是其他網址
for i in page_url:
pool.apply(image_down, args=(title, i, headers))
elif len(page_url) == 1: # 如果是第一頁
pool.apply(image_down, args=(title, page_url, headers)) # 調用線程池
pool.close()
pool.join()
項目經驗:
-
全部的代碼我差不多全部給出了,爲了讓你們身體健康,我還是希望大家可以自行的編寫一下主函數,主函數很簡單的,就是簡單的調用,參數我已經都給了,體驗一下編程的快樂,這樣左右手就很充實啦!
-
我對爬蟲的理解不在於代碼多難實現,而是如何分析網站,好的分析,絕對事半功倍!
-
這一次項目,因爲是靜態網址,沒有遇到多少坑坑窪窪,都是小毛病,我就不提出來博取幸苦費用了。
-
總的來說,你們看了覺得有幫助的,給個關注和支持,就是對我最大的幫助,我會加油,你們也是!
項目後記:
任他天高鳥飛,奔湧吧,後浪!