引言
最近有点忙,没怎么学习python,心中无限的罪恶感油然而生,趁着周末打算沉下心学习学习,爬点好玩的东西给single dog发福利
装点工具库
pip对win似乎并不是那么友好,如果安装一些库失败的话,可以尝试升级pip或是以管理员身份运行
- requests (一款网络请求特别棒的库)
- BeautifulSoup (爬数据需要用到的库,如何使用)
- lxml (增快BeautifulSoup解析页面的速度)
分析mzitu页面
mzitu链接http://www.mzitu.com/all
我们用postman或是debug当前页面来查看一下页面节点,找找有没有规律
我们看看画红线的部分,每一个跳转查看妹子的图片都有一个规律,那就是a标签都有一个target属性,我们来编码试试
定义一个获取页面的方法,这里面需要注意的是请求头中的Referer,这个是在论坛里面找到的,如果没加的话,爬取的时候获取到的图片全是请勿盗链的图
def downHtml(url):
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240",
'Connection': 'Keep-Alive',
'Referer': "http://www.mzitu.com/99566"
}
return requests.get(url, headers=headers).text
定义一个解析妹子总页面的方法,来获取单个妹子的链接
def parseHtml(html):
soup = BeautifulSoup(html, "lxml")
list = soup.select("a[target='_blank']")
count=0 #添加一个统计链接的数量
for a in list:
print(a["href"], a.get_text())
print(count)
运行
html = downHtml("http://www.mzitu.com/all")
parseHtml(html)
效果图
多达1901个妹子,我的天,这下爽到爆了
分析mzitu单个妹子页面
既然我们拿到所有妹子的url了,那么,我们随便点击一个url去分析一下页面
根据页面的分析,请看上图两处标红的位置,第一处是妹子的图片,第二处是总共的页码,我们可以看到,第二处标红是一个分页,每一个查看详情页的链接后面跟着的是页码,他是有规律的
我们先看第二处标红的地方,因为拿到所有的url也就意味着可以拿到妹子所有的图片,贴一点关键代码来分析
<div class="pagenavi">
<a href='http://www.mzitu.com/108361'>
<span>«上一组</span>
</a>
<span>1</span>
<a href='http://www.mzitu.com/108330/2'>
<span>2</span>
</a>
<a href='http://www.mzitu.com/108330/3'>
<span>3</span>
</a>
<a href='http://www.mzitu.com/108330/4'>
<span>4</span>
</a>
<span class='dots'>…</span>
<a href='http://www.mzitu.com/108330/30'>
<span>30</span>
</a>
<a href='http://www.mzitu.com/108330/2'>
<span>下一页»</span>
</a>
</div>
根据这段代码来看,每张图片的详情页都是由主链接加页码形成,也就是说,我们只要拿到页码,然后遍历这个页码添加到主链接的后面,我们就可以拿到每张图片,所以,页码数量30才是我们最关心的地方,我们首先可以根据div class=”pagenavi”来获取整个页码代码,获取到整个页码代码后,我们可以看到,页码30永远都是在倒数第二个span标签,这个时候,我们可以来编码了
编码
def get_pic_num(html):
soup = BeautifulSoup(html, "lxml")
list = soup.find("div", class_="pagenavi").find_all("span")
return int(list[-2].string)
运行
html = downHtml("http://www.mzitu.com/108330")
num = get_pic_num(html)
print(num)
效果图
好了,现在已经拿到图片数量了,然后,我们只需要遍历数量,将页码添加到妹子链接的后面形成妹子详情页url,然后我们在遍历的过程中,每访问一个url就去取出图片的url,那么,接下来如何取图片又是重中之重了
我们先想怎么取图片吧,截取一段代码
<div class="main-image">
<p>
<a href="http://www.mzitu.com/108330/2" >
<img src="http://i.meizitu.net/2017/11/08a01.jpg" alt="夏美酱:好玩不过黑丝腿,最美不如兔女郎" />
</a>
</p>
</div>
这个地方有个div class=”main-image”,我们可以先从他入手,先找到该节点,然后去找他所有的子节点是img标签的节点,因为img标签只有一个,所以自然而然的就可以定位到图片
编码
拼接url
for i in range(num):
str = "{}{}{}".format(pic, "/", i + 1)
html = downHtml(str)
t = threading.Thread(target=get_pic, args=(html,))
t.start()
t.join()
这个地方我开了个线程去处理,因为我们需要将这个图片下载到本地
获取图片
def get_pic(html):
soup = BeautifulSoup(html, "lxml")
img = soup.find("div", class_="main-image").find_all("img")
print(img[0]["src"], img[0]["alt"])
download_pic(img[0]["src"]) #下载图片
下载图片
def download_pic(url):
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240",
'Connection': 'Keep-Alive',
'Referer': "http://www.mzitu.com/99566"
}
img = requests.get(url, headers=headers)
t = time.time()
nowTime = lambda: int(round(t * 1000))
with open("{}.jpg".format(nowTime()), 'ab') as f:
f.write(img.content)
这个地方用了time库,以时间戳来给存储在本地的图片命名
效果图
all code
import threading
import time
import requests
from bs4 import BeautifulSoup
url = "http://www.mzitu.com/all"
pic = "http://www.mzitu.com/108528"
''' 获取html页面'''
def downHtml(url):
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240",
'Connection': 'Keep-Alive',
'Referer': "http://www.mzitu.com/99566"
}
return requests.get(url, headers=headers).text
''' 解析获取所有的妹子url '''
def parseHtml(html):
soup = BeautifulSoup(html, "lxml")
list = soup.select("a[target='_blank']")
count = 0 # 添加一个统计链接的数量
for a in list:
print(a["href"], a.get_text())
print(count)
''' 获取妹子所有图片的数量 '''
def get_pic_num(html):
soup = BeautifulSoup(html, "lxml")
list = soup.find("div", class_="pagenavi").find_all("span")
return int(list[-2].string)
''' 获取妹子的图片 '''
def get_pic(html):
soup = BeautifulSoup(html, "lxml")
img = soup.find("div", class_="main-image").find_all("img")
print(img[0]["src"], img[0]["alt"])
download_pic(img[0]["src"])
''' 下载妹子的图片 '''
def download_pic(url):
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240",
'Connection': 'Keep-Alive',
'Referer': "http://www.mzitu.com/99566"
}
img = requests.get(url, headers=headers)
t = time.time()
nowTime = lambda: int(round(t * 1000))
with open("{}.jpg".format(nowTime()), 'ab') as f:
f.write(img.content)
# 获取所有妹子的url
# html = downHtml(url)
# parseHtml(html)
#获取妹子所有的图片
html = downHtml(pic)
num = get_pic_num(html)
for i in range(num):
str = "{}{}{}".format(pic, "/", i + 1)
html = downHtml(str)
t = threading.Thread(target=get_pic, args=(html,))
t.start()
t.join()
总结
由于图片太多,代码部分我是分了两个部分,第一个部分我是获取所有妹子的url,第二个部分随便拿了一个妹子的url去获取她所有的图片,整体分析下来不是太难
爬虫是一个很有意思的技术,我们可以将这些数据爬下来存进数据库,然后进行数据分析,接下来,朝这个目标迈进,最后附上福利图。
哎呀,羞羞