1. 程式人生 > >Python爬取煎蛋妹子圖

Python爬取煎蛋妹子圖

煎蛋妹子圖網站

最近一直在通過爬蟲的練習,來鞏固自己的所學習到的 python 基礎,和爬蟲一些框架的使用。今天的程式就是最近在學習的 selenium 庫,通過利用 requests + beautifulsoup + selenium 庫來進行網站的抓取。抓取的物件是煎蛋網中的妹子板塊,圖片的質量還是很高的,我放幾張妹子圖大家感受下。

正所謂妹子驅動學習,今天就給大家詳細解析下我是如何一步步的完成妹子圖片的抓取。

爬取結果

先看下最後的爬取結果,通過執行 demo.py 程式碼,程式就會把網站上的妹子圖片,儲存到當前工程目錄下。在此程式中我建立了「jiandan」資料夾,並以當前的進度條為新的資料夾名,即「0.0」「1.0」「2.1」等等。最後把爬取到的圖片,儲存到相應的檔案裡。

程式結構

程式主要是由 6 個函式組成

get_one():是利用 webdriver 來請求對應的網站

pares_one():解析沒帶進度條的網站

pares_one_of_num():解析有帶進度條的網站

write_to_file():把抓取到的圖片儲存到本地檔案

next():進行翻頁

main():程式執行的主函式

程式思路

如果你對爬蟲比較熟悉的話,就會知道爬蟲的步驟其實很簡單,總結下主要有三部分:

1 目標站點分析,利用合適的請求庫進行請求。

2 解析原始碼,提取出相應的資料。

3 儲存資料。

爬蟲程式核心部分就這三個。我們順著這個思路來看看這次的程式碼。

目標站點分析

首先要對目標網站進行結構分析,看看它的網頁結構是如何,以及網頁返回的資料是什麼,是否有反爬機制,有些資料是否是通過 js 進行渲染,是否要進行翻頁等等。

通過谷歌瀏覽器的開發者模式可以看到,網站的返回結果裡是一堆 html 程式碼,但並沒有我們想要的圖片連結資訊。如果你用常規的 requests 進行請求,返回的資料是不會有我們想要的圖片資訊。

所以這裡我就想到,網站的圖片資源應該是通過 js 載入的。對於需要 js 才能加載出來的網站,我們就可以利用 selenium 自動化測試請求庫來進行載入。通過 selenium 請求庫,我們就可以模擬一個真實的瀏覽器,請求網站,載入 js,返回我們想要的資料。這裡對應的程式碼如下,需要你去網上下載對應的 chrome 驅動。

browser= webdriver.Chrome()

# 設定網站等待時間

wait= WebDriverWait(browser,10)

圖片資訊提取

隨後就可以利用 beautifulsoup 這個解析庫進行解析,把想要的資訊提取出來。在這裡我們需要的是圖片資訊,所以我通過 select() 函式進行提取,程式碼如下:

soup= BeautifulSoup(html,'lxml')

imgs= soup.select('img')

返回的是一個列表,然後再利用 for 把每個圖片的連結,提取出來,並下載,程式碼如下:

forimginimgs:

img_url = re.findall('src="(.*?)"', str(img))

ifnotimg_url[0][-3:] =='gif':

ifnotimg_url[0][-3:] =='png':

ifimg_url[0][-3:]:

print('正在下載:%s 第 %s 張'% (img_url[0], count))

write_fo_file(img_url[0], percent_num, count)

count +=1

這裡需要注意的是,我最開始在爬取的過程中遇到有些圖片不是 jpg 格式,以及有些圖片是 gif 格式。所以我加了一些判斷來保證,獲取到的圖片連結是 jpg 格式,程式才能把圖片下載下來。所以這裡就有優化的地方,大家可以去再查詢一些資料,看看是否可以把 png 或 gif 格式的圖片一起儲存。

解析原始碼

當前進度條

為了控制程式爬取的次數,我們就需要找到一些條件來進行判斷。一般的網站是會返回總的條數,但這次的網站通過觀察並沒有返回總條數的資訊。並且在最開始進入妹子圖板塊,上方是沒有進度條資訊。

但當點選下一頁的時候,網站就有顯示出當前的進度條。

我們就可以利用這個當前瀏覽的位置,來控制程式爬取的次數。隨後通過網站的原始碼分析,就很容易得到這部分的資訊,對應的程式碼如下:

num= soup.select('#body #comments .comments .page-meter-title')[0].getText()

percent= re.findall('\d+', num)

percent_num= percent[0] +'.'+ percent[1]

然後定義一個 next() 函式,來判斷當前的進度條是否達到 100.0%,如果沒有則繼續爬取,對應的程式碼如下:

defnext(url):

html = get_one(url)

percent_num, next_url = pares_one_of_num(html)

whilepercent_num !='100.0':

next(next_url)

下一頁連結

進一步的觀察我們可以看到,下一頁的連結地址,是儲存在 a 標籤當中,所以我們獲取到 a 標籤的內容,我們就有了跳轉的能力,就可以爬取下一頁的內容。對應的程式碼如下:

url= soup.select('#body #comments .comments .cp-pagenavi a')[1]

href= re.findall('href="(.*?)"', str(url))

next_url='https:'+ href[0]

針對最開始的頁面沒有當前瀏覽位置資訊,我分別寫了兩個解析函式:pares_one()、pares_one_of_num()。對應的程式碼如下:

defpares_one(html):

soup = BeautifulSoup(html,'lxml')

imgs = soup.select('img')

url = soup.select('#body #comments .comments .cp-pagenavi a')[1]

href = re.findall('href="(.*?)"', str(url))

next_url ='https:'+ href[0]

count =0

forimginimgs:

img_url = re.findall('src="(.*?)"', str(img))

ifnotimg_url[0][-3:] =='gif':

ifnotimg_url[0][-3:] =='png':

print('正在下載:%s 第 %s 張'% (img_url[0], count))

write_fo_file(img_url[0],'0.0', count)

count +=1

returnnext_url

defpares_one_of_num(html):

soup = BeautifulSoup(html,'lxml')

imgs = soup.select('img')

num = soup.select('#body #comments .comments .page-meter-title')[0].getText()

percent = re.findall('\d+', num)

url = soup.select('#body #comments .comments .cp-pagenavi a')[1]

href = re.findall('href="(.*?)"', str(url))

percent_num = percent[0] +'.'+ percent[1]

next_url ='https:'+ href[0]

count =0

forimginimgs:

img_url = re.findall('src="(.*?)"', str(img))

ifnotimg_url[0][-3:] =='gif':

ifnotimg_url[0][-3:] =='png':

ifimg_url[0][-3:]:

print('正在下載:%s 第 %s 張'% (img_url[0], count))

write_fo_file(img_url[0], percent_num, count)

count +=1

returnpercent_num, next_url

儲存資料

最後就是把圖片儲存到檔案中,這部分的程式碼如下:

defwrite_fo_file(url, num, count):

dirName =u'{}/{}'.format('jiandan', num)

ifnotos.path.exists(dirName):

os.makedirs(dirName)

filename ='%s/%s/%s.jpg'% (os.path.abspath('.'), dirName, count)

print(filename)

withopen(filename,'wb+')asjpg:

jpg.write(requests.get(url).content)

優化改進

本次的程式還有一些不足的地方,比如利用 selenium 庫在解析的時候非常的慢,這部分是可以優化的。還有程式在爬取到 80.6% 的時候,程式報錯了,並沒能把圖片全部爬取完。這就說明還有一些情況,我沒有考慮到。有待以後進一步優化。

這波教程不點個贊,不關注一下說不過去吧?這個網站有很多福利,我只能說大家注意身體。