環(huán)境:windows7 + python2.7
相關(guān)庫:lxml + json + urllib
爬取的網(wǎng)站地址:http://www.mzitu.com/ (础芍。。数尿。捂臉)
本人是社會主義好青年仑性,本次抓取只將所有圖片的原始地址抓到后保存為json文件,并不下載圖片右蹦!
好了開始吧
首先需要一個可以抓取頁面的函數(shù)
#獲取網(wǎng)頁
def getHtml(url):
res = urllib.urlopen(url)
html = res.read().encode('utf8')
return html
打開網(wǎng)頁即可在首頁下方看到所有頁面的數(shù)诊杆,最大值就是我們所需要的
Paste_Image.png
審查元素發(fā)現(xiàn)這個值放在一個a標(biāo)簽下,要拿到這個頁面數(shù)值何陆,我們使用xpath解析網(wǎng)頁
#獲取一共有多少頁專題
def getAllPages(url):
html = etree.HTML(getHtml(url))
pages = html.xpath('/html/body/div[2]/div[1]/div[2]/nav/div/a[4]/text()')
pages = int(pages[0])
return pages
使用審查元素查看網(wǎng)頁代碼可以發(fā)現(xiàn),每一個頁面有多個專題晨汹,這些專題存放在id值為pins的ul列表里,每一個li標(biāo)簽存放一個專題
Paste_Image.png
想要得到每個專題中所有的圖片我們需要獲取每個專題的名稱和鏈接甲献,使用代碼
#根據(jù)傳進(jìn)來的頁面地址獲取當(dāng)頁所有專題的鏈接和名稱
def everyPage(page):
url = 'http://www.mzitu.com/page/%d'%page
html = etree.HTML(getHtml(url))
pins_list = html.xpath('//*[@id="pins"]/li') #獲取每個頁面所有專題xpath列表
for pins in pins_list:
mkdirs = pins.xpath('a/@href') #專題鏈接
mkdirs_name = pins.xpath('a/img/@alt') #專題名稱
得到專題的鏈接之后我們進(jìn)入專題
Paste_Image.png
可以發(fā)現(xiàn)每個妹子所擁有的圖片數(shù)量不一致宰缤,且每一個頁面只有一張圖。多瀏覽幾張圖片,可以看出專題內(nèi)的圖片很有規(guī)律慨灭,第二張的頁面地址是這樣的
http://www.mzitu.com/86102/2
朦乏,第三張的頁面地址http://www.mzitu.com/86102/3
,所以我們只要得出這個專題一共有多少頁面就能知道有多少張圖和每張圖所存放的地址了氧骤。
#獲取每個專題所有圖片的地址
def everySemImgUrls(sem_name,url):
html = etree.HTML(getHtml(url))
images = html.xpath('//div[@class="pagenavi"]/a[last()-1]/span/text()') #每個專題圖片數(shù)量
mmpags = [url+'/'+str(x) for x in range(1,int(images[0])+1)] #生成圖片頁面列表
拿到了每張圖所在的頁面地址呻疹,那么就剩下獲取圖片的原始地址了
Paste_Image.png
同樣使用xpath
#獲取單個頁面下的圖片地址
def getImageUrl(url):
html = etree.HTML(getHtml(url))
src = html.xpath('//div[@class="main-image"]/p/a/img/@src')
src = src[0]
return src #返回每張圖片的地址
最后就是保存到j(luò)son文件
所有代碼如下
#-*- coding:utf-8 -*-
import urllib
import threadpool
from lxml import etree
import json
#獲取網(wǎng)頁
def getHtml(url):
res = urllib.urlopen(url)
html = res.read().encode('utf8')
return html
#獲取一共有多少頁專題
def getAllPages(url):
html = etree.HTML(getHtml(url))
pages = html.xpath('/html/body/div[2]/div[1]/div[2]/nav/div/a[4]/text()')
pages = int(pages[0])
return pages
#獲取單個頁面下的圖片地址
def getImageUrl(url):
html = etree.HTML(getHtml(url))
src = html.xpath('//div[@class="main-image"]/p/a/img/@src')
try:
src = src[0]
except IndexError,e:
print e
print src
return src #返回每張圖片的地址
#獲取每個專題所有圖片的地址
def everySemImgUrls(sem_name,url):
html = etree.HTML(getHtml(url))
images = html.xpath('//div[@class="pagenavi"]/a[last()-1]/span/text()') #每個專題圖片數(shù)量
mmpags = [url+'/'+str(x) for x in range(1,int(images[0])+1)] #生成圖片頁面列表
sem_image = []
for jpgUrl in mmpags:
imgUrl = getImageUrl(jpgUrl)
sem_image.append(imgUrl)
pageMMurls = {}
pageMMurls[sem_name] = {}
pageMMurls[sem_name]['sem_url'] = url
pageMMurls[sem_name]['sem_images'] = sem_image
readed = {}
try:
readed = json.load(open('mzitu.json','r'))
except Exception,e:
pass
with open('mzitu.json','w') as f:
readed[sem_name] = pageMMurls[sem_name]
json.dump(readed,f,sort_keys=True,indent=4,separators=(',',': '),encoding="utf8",ensure_ascii=False)
print sem_name+' -'+images[0]+'-張'
#獲取一個頁面中所有專題名及連接
def everyPage(page):
url = 'http://www.mzitu.com/page/%d'%page
html = etree.HTML(getHtml(url))
pins_list = html.xpath('//*[@id="pins"]/li') #獲取每個頁面所有專題xpath列表
print '本頁共有專題--%d--個'%pins_list.__len__()
for pins in pins_list:
mkdirs = pins.xpath('a/@href') #專題鏈接
mkdirs_name = pins.xpath('a/img/@alt') #專題名稱
everySemImgUrls(mkdirs_name[0],mkdirs[0])
def main():
pages = getAllPages('http://www.mzitu.com/') #從主頁獲取所有頁面數(shù)量
print '共發(fā)現(xiàn)--%d--頁專題'%pages
for page in range(1,pages+1):
print '準(zhǔn)備下載第--%d--頁'%page
everyPageDict = everyPage(page)
if __name__ == '__main__':
main()
總結(jié):
1、本次爬蟲為單線程筹陵,速度慢且偶爾有中途停車現(xiàn)象刽锤。下次來玩兒再來優(yōu)化