閑來無事遵湖,我打算爬一下壁紙塑娇,選好wallheaven作為目標(biāo)之后仗哨,經(jīng)過一番折騰,我寫出了一段代碼铅辞,順利完成了目標(biāo)厌漂。
一.爬蟲第一步自然是上要爬到的網(wǎng)站,進入開發(fā)者模式斟珊,查看網(wǎng)頁結(jié)構(gòu)苇倡。我進入wallheaven網(wǎng)站之后,輸入關(guān)鍵詞“l(fā)ake”囤踩,只勾選選項“Anime”雏节,結(jié)果查找到36張動漫壁紙。在我看來這已經(jīng)足夠了高职。接著钩乍,打開F12打開開發(fā)者模式,查看代碼怔锌。
我的目標(biāo)是找到所搜到圖片的總數(shù)和圖片的鏈接地址寥粹。如圖所示
從這張圖片可以看到網(wǎng)頁節(jié)點之間的層次關(guān)系,而我們所需要的節(jié)點是body/main/header/h1,需要提取其中的文本“36 Wallpapers found for”埃元,在這里可以使用XPath來獲取節(jié)點信息涝涤,語句可以寫為://header[@class="listing-header"]/h1[1]/text()。
表達式 描述
nodename 選取此節(jié)點的所有子節(jié)點
/ 從當(dāng)前節(jié)點選取直接子節(jié)點
// 從當(dāng)前節(jié)點選取子孫節(jié)點不管隔了多少代
. 選取當(dāng)前節(jié)點
@ 選取屬性
由此看來//header[@class="listing-header"]/h1[1]/text()就是選取了class屬性為“l(fā)isting-header”的header的子節(jié)點h1的文本岛杀,那就是“36 Wallpapers found for”阔拳。
接下來,找圖片鏈接类嗤。
同理糊肠,要獲取的信息是"https://alpha.wallhaven.cc/wallpaper/148364",用xpath的話就要寫:
//a[@class="preview"]/@href 。
二遗锣,既然網(wǎng)頁已經(jīng)研究夠了货裹,那么可以寫代碼了。
1.導(dǎo)入需要的模塊精偿,具體什么模塊自己去查弧圆。
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 30 17:58:50 2019
@author: yuyuko
"""
#wallhaven爬取
import os
from urllib.parse import urlencode
import time
from requests import codes
import random
import requests
from lxml import etree
2.定義創(chuàng)建文件路徑函數(shù),將下載的文件存儲到該路徑笔咽。
def CreatePath(filepath):
if not os.path.exists(filepath):
os.makedirs(filepath)
3.定義獲取url函數(shù)搔预,這里是通過urlencode方法把url的各個部分拼接起來的,拼接起來的url像是這樣的:https://alpha.wallhaven.cc/search?q=lake&categories=010&purity=100&sorting=relevance&order=desc
def GetUrl(keyword,category):
params = {
'q': keyword,
'categories': category,
'purity': '110',
'sorting': 'relevance',
'order':'desc'
}
base_url='https://alpha.wallhaven.cc/search?'
url=base_url + urlencode(params)
return url
4.這里要用到上面說的東西了叶组,獲取查找到的圖片數(shù)拯田。
def GetPictureNum(url):
allpic=" "
try:
html = requests.get(url)
if codes.ok == html.status_code:
selector = etree.HTML(html.text)
pageInfo = selector.xpath('//header[@class="listing-header"]/h1[1]/text()')#提取出文本
string = str(pageInfo[0])#圖片數(shù)是文本中的第一個
numlist = list(filter(str.isdigit,string)) #有些數(shù)字是這樣的,11,123,所以需要整理扶叉。
for item in numlist:
allpic+=item
totalPicNum=int(allpic) #把拼接起來的字符串進行整數(shù)化
return totalPicNum
except requests.ConnectionError:
return None
5.定義函數(shù)獲取圖片鏈接勿锅。這里用到我們上面分析的xpath獲取圖片信息。
def GetLinks(url,number):
urls=url+'&page='+str(number)
try:
html=requests.get(urls)
selector=etree.HTML(html.text)
PicLink=selector.xpath('//a[@class="preview"]/@href')#這里尋找圖片的鏈接地址枣氧,以求得到圖片編號
except Exception as e:
print('Error',e.args)
return PicLink
6.現(xiàn)在可以定義一個下載函數(shù)了溢十。
def Download(filepath,keyword,url,count,headers):#其中count是你要下載的圖片數(shù)
#此函數(shù)用于圖片下載。其中參數(shù)url是形如:https://alpha.wallhaven.cc/wallpaper/510308的網(wǎng)址
#510308是圖片編號达吞,需要構(gòu)造html张弛,html是圖片的最終直接下載網(wǎng)址。
#因為wallheaven上只有兩種格式的圖片酪劫,分別是png和jpg吞鸭,所以設(shè)置兩種最終地址HtmlJpg和HtmlPng,通過status_code來進行判斷覆糟,狀態(tài)碼為200時請求成功刻剥。
string=url.strip('https://alpha.wallhaven.cc/wallpaper/')
HtmlJpg='http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-' + string+'.jpg'
HtmlPng='http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-' + string+'.png'
try:
pic=requests.get(HtmlJpg,headers=headers)
if codes.ok==pic.status_code:
pic_path=filepath+keyword+str(count)+'.jpg'
else:
pic=requests.get(HtmlPng,headers=headers)
pic_path=filepath+keyword+str(count)+'.png'
with open(pic_path,'wb') as f:
f.write(pic.content)
f.close()
print("Downloaded image:{}".format(count))
time.sleep(random.uniform(0,3))#這里是讓爬蟲在下載完一張圖片后休息一下,防被偵查到是爬蟲從而引發(fā)反爬蟲機制滩字。
except Exception as e:
print(repr(e))
7.主函數(shù)在這里造虏。
def main():
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5)\
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36",#請求頭,這個可以通過查看你自己的瀏覽器得到麦箍。
}
filepath = ('/home/yuyuko/Pictures/')#存儲路徑漓藕。
keyword=input('請輸入關(guān)鍵詞:')
category=input('請輸入圖片分類,共有三種挟裂,分別為Gneral,Anime,People三種\
享钞,如果你想要只想選擇Anime,就鍵入010,如果全選就鍵入111,以此類推:')
CreatePath(filepath) #創(chuàng)建保存路徑
url=GetUrl(keyword,category) #獲取url
PicNum=GetPictureNum(url)#總圖片數(shù)
pageNum=int(PicNum/24+1) #求出總頁面數(shù)
print("We found:{} images.".format(PicNum))
Num=int(input("請輸入你想要爬的圖片數(shù)诀蓉,不能超過已找到的圖片數(shù):"))
j=1
for i in range(pageNum):
PicUrl=GetLinks(url,i+1)
for item in PicUrl:
Download(filepath,keyword,item,j,headers)
j+=1
if(j>Num):#如果你下載的圖片夠用了栗竖,那就直接退出循環(huán),結(jié)束程序渠啤。
break
else:
pass
break
if __name__ == '__main__':
main()
運行結(jié)果是:
找到489張圖片划滋,下載三張圖片。