" 最近由于公司業(yè)務(wù)的需要,我開始做了一些簡單的爬蟲的工作。學了爬蟲之后,就在想,能不能用爬蟲做一些有趣的事情呢?想來想去,還是教大家寫個簡單的爬蟲,用
最近由于公司業(yè)務(wù)的需要,我開始做了一些簡單的爬蟲的工作。學了爬蟲之后,就在想,能不能用爬蟲做一些有趣的事情呢?想來想去,還是教大家寫個簡單的爬蟲,用來爬取一組美女圖。
因為只有美女圖才能吸引你們這些紳士過來圍觀。。。。。
最后附上源碼,拿去直接就可以用了。
目標
我在 bing 上搜索 美女圖,出來了這個。
那我們就用這個來開刀吧。
額。。。。。。。。
這尺度,我們還是選個保守一點的來做例子吧。。。。。。
配置環(huán)境
由于我們是使用 python 來做爬蟲的,所以我們要先裝好 python 環(huán)境,這個比較簡單,直接到官網(wǎng)下載安裝就可以了,安裝的過程也是一直下一步就行。
下載地址: https://www.python.org/downloads/
我們選擇相應(yīng)的操作系統(tǒng)平臺安裝就可以了。
還有一個是 python 的網(wǎng)絡(luò)請求庫 requests ,我們后面將要使用這個庫進行網(wǎng)絡(luò)請求,來爬取數(shù)據(jù)。
這個庫的安裝也很簡單,在命令行下執(zhí)行以下命令就可以了
pip3 install requests
還有一個是用來解析 html 結(jié)構(gòu),和提取元素內(nèi)容的一個庫。安裝也很簡單
pip3 install beautifulsoup4
開始分析
在 Chrome(谷歌瀏覽器) 下,打開我們要爬取的地址 https://www.walltu.com/tuku/201801/212736.html , 然后按 F12 ,在網(wǎng)絡(luò)這一欄,我們可以看到這個頁面的請求。
然后,再切到 XHR 下,發(fā)現(xiàn)這個頁面并沒有發(fā) ajax ,也就是說,我們要爬取的圖片地址和頁面可能是在一起的。
我們看一下這個 html 頁面里面是什么東西。
然后我們在使用元素選擇器,看一下我們要爬取的圖片是哪個元素,然后我們再到 html 代碼里面找一下,找到這個圖片的元素
找到了,然后我們再到網(wǎng)絡(luò)請求到頁面里面看一下,看能不能找到這個元素,果然找到了。
我們再瀏覽器直接打開這個地址:
那就說明可以通過地址直接獲取到圖片,那我們就開始了。
開始干活
到這里,我們就要開始正式寫代碼了,但是不要擔心,很簡單的。老司機帶路肯定是穩(wěn)的!
先從下載圖片開始
我們先試一下,看能不能直接請求到圖片。打印一下請求的狀態(tài)碼和內(nèi)容。
import requests
response = requests.get('https://img.walltu.com/d/file/shutu/2018-01/20150813115821611.jpg!800')
print(response.status_code)
print(response.content)
打印結(jié)果如下:
403
b'{"code":"40310014","msg":"invalid Referer header"}'
請求失敗了,但是提示我們 referer 非法。說起來也是挺好笑的,居然會提示我們錯誤的地方,這是怕我們爬不到數(shù)據(jù)嗎。。。。。。
知道問題在哪就好搞了。我們找一下這個信息要填什么。
切換之前頁面的調(diào)試界面,選中 img ,看一下頁面上請求時用的是什么,照抄過來就行了。
然后把這個東西加到請求頭試一下
import requests
headers = {
'Referer':'https://www.walltu.com/tuku/201801/212736.html'
}
response = requests.get('https://img.walltu.com/d/file/shutu/2018-01/20150813115821611.jpg!800',headers=headers)
print(response.status_code)
print(response.content)
上面的代碼應(yīng)該很容易看懂吧,即使沒有學過 python 。就是在請求的時候多添加了一個請求頭的參數(shù)
打印內(nèi)容如下:
200
b'xffxd8xeaxe3ox88...............1x12xc1x1bx19)xbcwx139ux0eLDxd8lx02ox81x12c&xc4xc9xf2MTx7fxffxd9'
我們看到狀態(tài)碼是 200 ,說明成功了,后面打印的是圖片的二進制數(shù)據(jù),由于圖片轉(zhuǎn)化成二進制內(nèi)容很多,中間的部分信息被我省略了。
保存圖片
剛才我們通過 requests 請求到了圖片,但是二進制的圖片給我們沒有用啊,我們要看圖片,真正的圖片!
那我們就要把圖片保存起來。我們先打開一個文件,然后把請求到的內(nèi)容寫入到文件里面就行了。
import requests
headers = {
'Referer':'https://www.walltu.com/tuku/201801/212736.html'
}
response = requests.get('https://img.walltu.com/d/file/shutu/2018-01/20150813115821611.jpg!800',headers=headers)
# 打開一個文件,第一個參數(shù)是文件路徑,第二參數(shù)是打開方式,'wb' 表示以二進制寫入的方式打開
img_file = open('img.jpg','wb')
# 然后往文件里面寫內(nèi)容
img_file.write(response.content)
這段代碼執(zhí)行完,應(yīng)該就可以在同個目錄下找到下載好的 img.jpg 圖片,打開就能看見下載好的圖片的了。是不是很簡單呢。
目標是爬取一組圖
我們搞半天,只是把一張圖片下載到本地而已,這么麻煩,還不如直接在頁面上右擊保存圖片來得快呢。。。。。。
我們的目標可不是下載一張圖片,而是一整組圖片!
從第一張圖片開始爬取
第一張圖片剛才不是下載完了?
不不不,我們要是輸入這一組圖片的網(wǎng)頁地址,就可以下載這一組圖片的效果。也就是輸入 https://www.walltu.com/tuku/201801/212736.html 就可以下載一整組圖的效果。
要實現(xiàn)這個效果,可就不能像之前那樣手動去找圖片的地址了,要通過代碼找到圖片的地址。那我們就需要使用一些工具來幫我們找到這個地址了,我這里使用的是 BeautifulSoup 來進行元素查找。
我們先看一下剛才查找的那個圖
觀察這個結(jié)構(gòu),發(fā)現(xiàn)比較靠近目標并且有特點的元素是 <ddclass="p"> ,我們只要找到這個元素,再順藤摸瓜,往下找到下面的 <p> 然后再往里面就可以找到我們要的 <img> 這個元素了。
代碼上,我們可以這么寫:
import requests
from bs4 import BeautifulSoup
# 請求這個頁面
response = requests.get('https://www.walltu.com/tuku/201801/212736.html')
# BeautifulSoup 的構(gòu)造函數(shù)最少需要兩個參數(shù),第一個是要解析的內(nèi)容,第二個是解析器,這里我們使用的是 'html.parser'
content = BeautifulSoup(response.content, 'html.parser')
target_parent = content.find('dd', class_='p')
target = target_parent.p.img
img_address = target['src']
print(img_address)
打印結(jié)果如下:
https://img.walltu.com/d/file/shutu/2018-01/20150813115821611.jpg!800
我們這樣就拿到了第一個頁面的圖片地址。
查找下一個
我們的最終目標的是爬取一整組圖。找到了第一個圖片,那就要準備找下一個了。
我想很多人想到的是圖片右邊的 下一圖 這個按鈕,但是有個問題,就是到這組圖的最后一張后,這個按鈕的鏈接就會變成下一組圖的地址了,這樣就會一直循環(huán)下去,這可不行。
我把目標轉(zhuǎn)到了下面。
我們發(fā)現(xiàn)當前的圖片是有個選中的樣式的,我們應(yīng)該可以找到這個元素,然后找到下一個元素,也就是下一個圖片的頁面的鏈接。這個會不會有最后一張的地址變成下一組的地址 這個問題呢?
我們看一下:
好像沒有,最后一個還是最后一個,沒有多出一個是跳下一組圖的元素。我們還得看一下 html 。
確實沒有一些多余的東西,而且我們還發(fā)現(xiàn)了選中的樣式是 class="c",那就開始干活!
import requests
from bs4 import BeautifulSoup
# 請求這個頁面
response = requests.get('https://www.walltu.com/tuku/201801/212736.html')
# BeautifulSoup 的構(gòu)造函數(shù)最少需要兩個參數(shù),第一個是要解析的內(nèi)容,第二個是解析器,這里我們使用的是 'html.parser'
content = BeautifulSoup(response.content, 'html.parser')
# 找到當前選中的圖片
index = content.find('a', class_='c')
# 找到下一個圖片的元素
next_target = index.next_sibling
if next_target is None:
# 沒有下一個了
print('沒有下一個了')
else:
# 找到了下一個,我們就打印出來
print('下一個')
next_addr = 'https://www.walltu.com' + next_target['href']
print(next_addr)
打印結(jié)果:
下一個
https://www.walltu.com/tuku/201801/212736_2.html
如果是最后一個呢?我們也看一下,我們把地址換成 https://www.walltu.com/tuku/201801/212736_7.html
再執(zhí)行一次,打印結(jié)果
沒有下一個了
再配合上之前下載圖片的代碼,應(yīng)該就可以把一整組圖給下載下來了。我們還需要一個文件夾把這些圖片給整理放好,其實還有剩下的兩步工作,就是新建一個文件夾,用來存放圖片,然后下載圖片的時候再給每個圖片命名,否則重復的文件名會把之前的圖片給覆蓋掉。
新建文件夾
新建文件夾很簡單
import os
# 創(chuàng)建文件夾
os.makedirs('文件夾的名稱')
用來存圖片的目錄名就用第一個頁面的標題吧。
給圖片命名
要給圖片命名,就要考慮唯一性,從圖片的下載地址上看,這些名稱確實是唯一的,但是都是一些隨機的名稱,也就是沒有順序,感覺也不太好,因為這些圖片實際上是有一定順序的。
實在不行,那就用頁面的地址吧。因為一個圖片對應(yīng)的也是一個頁面,而且我們看一下這些頁面地址。
https://www.walltu.com/tuku/201801/212736.html
https://www.walltu.com/tuku/201801/212736_2.html
https://www.walltu.com/tuku/201801/212736_3.html
https://www.walltu.com/tuku/201801/212736_4.html
我們發(fā)現(xiàn),這些還是有順序的,剛好滿足我們的需求。
在下載圖片的時候,傳入名稱就行了。這里就不上代碼了。
整理一下思路
整理一下代碼
我們最后整理一下代碼,把一些操作抽取成方法。
import os
import requests
from bs4 import BeautifulSoup
# 下載所有圖片
def downloadAllImg(address):
# 解析頁面
content = getContent(address)
# 獲取頁面標題
title = content.title.string
# 新建文件夾
os.makedirs(title)
# 獲取圖片的地址
download_img_addr = getDownloadImgAddr(content)
# 獲取文件名
file_name = getFileName(address)
print('開始下載:'+title)
while download_img_addr is not None:
# 下載圖片
downloadImg(download_img_addr,address,title,file_name)
# 獲取下一個頁面的地址
next_addr = getNextAddr(content)
if next_addr is None:
download_img_addr = None
else:
# 獲取下一個圖片的名稱,并賦值給 變量
file_name = getFileName(next_addr)
# 解析下一個頁面,并賦值給 變量
content = getContent(next_addr)
# 獲取下一個圖片的下載地址,并賦值給 變量
download_img_addr = getDownloadImgAddr(content)
print('新下載地址:'+download_img_addr)
print('已全部下載完成')
# 解析頁面
def getContent(address):
response = requests.get(address)
return BeautifulSoup(response.content, 'html.parser')
# 獲取圖片的地址
def getDownloadImgAddr(content):
target_parent = content.find('dd', class_='p')
target = target_parent.p.img
img_address = target['src']
return img_address
# 獲取下一個頁面的地址
def getNextAddr(content):
index = content.find('a', class_='c')
next_target = index.next_sibling
if next_target is None:
print('沒有下一個了')
return None
else:
print('下一個')
next_addr = 'https://www.walltu.com' + next_target['href']
print(next_addr)
return next_addr
# 獲取文件的名稱
def getFileName(address):
end_index = address.rfind('.')
start_index = address.rfind('/')
return address[start_index + 1:end_index]
# 下載圖片
def downloadImg(imgAddress,fromAddr,dir,file_name):
print('正在下載:'+file_name)
img = open(dir+'/'+file_name+'.jpg', 'wb')
headers = {
'Referer': fromAddr
}
img_response = requests.get(imgAddress, headers=headers)
img.write(img_response.content)
img.close()
print('下載完成:'+imgAddress)
# 調(diào)用,傳入要下載的圖片的地址
downloadAllImg('https://www.walltu.com/tuku/201801/212736.html')
代碼到這里就完成了,想要下載其他組圖,只要換一下,最后調(diào)用的地址就可以了。
最后,我們看一下效果吧。成功下載到了一整組圖。
大家快去試一下吧!
"美國國家航空航天局已發(fā)出近10億 Dell的新款Precision 7000系列移 蘇寧中華第一店的“倒退”顯示出 Microsoft Surface go 2已通過En 如何連接裝修工人的訂單接收平臺 這21個應(yīng)用程序是非法的! 您可 YouTube每分鐘產(chǎn)生32000美元的廣 頻頻挖角高管抱怨午夜,魅族的應(yīng) 當場推翻原版! AI不承認上帝, 數(shù)字基礎(chǔ)共享視頻介紹了VRS可變 北通云企業(yè)照明站,3分鐘發(fā)布一 100智能大廈 新聞:2020年13英寸Macbook Pro 閱讀對最近查詢的回應(yīng):全面推動 餐飲業(yè)的創(chuàng)新,變革和利潤保證 國家緊急響應(yīng)為2級或以下; 特斯 巴菲特:尚未找到感興趣的公司 Apple的新消息專利:重新編輯發(fā) 沒有贏得原始的跑步成績,并且沒 長鑫家用DDR4內(nèi)存芯片/顆粒處理 在原始的win10中搜索其他瀏覽器 巴菲特的Alpha:使用機器學習量 圖片預(yù)覽界面中的新增長焦點圖片 巴菲特:麝香做得很棒,但不會投 閱讀:作家座談會于5月6日啟動, 原始IOS 13.5 beta 3帶來了有關(guān) 中國人民銀行:恢復生產(chǎn)的狀況正 原裝國內(nèi)最差的手機系統(tǒng):華為的 比亞迪與華為合作! 趙長江:特 經(jīng)典gal“ MUV luv”將發(fā)布在Ste