煎蛋妹子圖網站
正所謂妹子驅動學習,今天就給大家詳細解析下我是如何一步步的完成妹子圖片的抓取。
爬取結果
先看下最後的爬取結果,通過運行 demo.py 代碼,程序就會把網站上的妹子圖片,保存到當前工程目錄下。在此程序中我創建了「jiandan」文件夾,並以當前的進度條為新的文件夾名,即「0.0」「1.0」「2.1」等等。最後把爬取到的圖片,保存到相應的文件裡。
程序結構
image
程序主要是由 6 個函數組成
- get_one():是利用 webdriver 來請求對應的網站
- pares_one():解析沒帶進度條的網站
- pares_one_of_num():解析有帶進度條的網站
- write_to_file():把抓取到的圖片保存到本地文件
- next():進行翻頁
- main():程序執行的主函數
通過谷歌瀏覽器的開發者模式可以看到,網站的返回結果裡是一堆 html 代碼,但並沒有我們想要的圖片鏈接信息。如果你用常規的 requests 進行請求,返回的數據是不會有我們想要的圖片信息。
所以這裡我就想到,網站的圖片資源應該是通過 js 加載的。對於需要 js 才能加載出來的網站,我們就可以利用 selenium 自動化測試請求庫來進行加載。通過 selenium 請求庫,我們就可以模擬一個真實的瀏覽器,請求網站,加載 js,返回我們想要的數據。這裡對應的代碼如下,需要你去網上下載對應的 chrome 驅動。
browser = webdriver.Chrome()# 設置網站等待時間wait = WebDriverWait(browser, 10)
圖片信息提取
這裡需要注意的是,我最開始在爬取的過程中遇到有些圖片不是 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%,如果沒有則繼續爬取,對應的代碼如下:
def next(url): html = get_one(url) percent_num, next_url = pares_one_of_num(html) while percent_num != '100.0': next(next_url)
下一頁鏈接
def pares_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 for img in imgs: img_url = re.findall('class="lazy" data-original="(.*?)"', str(img)) if not img_url[0][-3:] == 'gif': if not img_url[0][-3:] == 'png': print('正在下載:%s 第 %s 張' % (img_url[0], count)) write_fo_file(img_url[0], '0.0', count) count += 1 return next_urldef pares_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 for img in imgs: img_url = re.findall('class="lazy" data-original="(.*?)"', str(img)) if not img_url[0][-3:] == 'gif': if not img_url[0][-3:] == 'png': if img_url[0][-3:]: print('正在下載:%s 第 %s 張' % (img_url[0], count)) write_fo_file(img_url[0], percent_num, count) count += 1 return percent_num, next_url
保存數據
最後就是把圖片保存到文件中,這部分的代碼如下:
def write_fo_file(url, num, count): dirName = u'{}/{}'.format('jiandan', num) if not os.path.exists(dirName): os.makedirs(dirName) filename = '%s/%s/%s.jpg' % (os.path.abspath('.'), dirName, count) print(filename) with open(filename, 'wb+') as jpg: jpg.write(requests.get(url).content)
優化改進
image
本次的程序還有一些不足的地方,比如利用 selenium 庫在解析的時候非常的慢,這部分是可以優化的。還有程序在爬取到 80.6% 的時候,程序報錯了,並沒能把圖片全部爬取完。這就說明還有一些情況,我沒有考慮到。有待以後進一步優化。
閱讀更多 繁華落盡and曲終人散 的文章