老司机带你用python来爬取妹子图
一:Python爬虫入门-利用requsets库爬取煎蛋网妹子图
其实之前是想利用煎蛋网来联系一下scrapy的ImagesPipeline爬取煎蛋网的妹子图并下载下来保存到本地,无奈这个ImagePipeline一点都不给面子一直报404错误,而且我还不知道问题出在哪里,所以一怒之下就不用框架了,直接爬一下。
作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这是一个我的python交流群:831524055,不管你是小白还是大牛欢迎入驻 ,讨论技术, 大家一起交流学习成长!
先来一张:
从下图可以看出总的页数:
在翻页的过程中URL中只有页数是在发生改变的,这个就比较好构建URL了,而且图片的信心在原始的请求里面就能够找到图片的链接地址,这个也比较好办:
于是可以开始写代码了:
import requests
from pyquery import PyQuery as pq
from requests.exceptions import RequestException
import os
from hashlib import md5
from multiprocessing import Pool
headers={
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate, sdch',
'Referer':'http://jandan.net/ooxx',
'Referer':'http://jandan.net/ooxx',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'Cookie':'__cfduid=d0f8f8aef303ad3b55cd071a426e7a59c1504854664; _ga=GA1.2.986719823.1501079288; _gid=GA1.2.1585289570.1506061387',
}
def get_page(url):
response=requests.get(url,headers=headers)
try:
if response.status_code==200:
return response.text
return None
except RequestException:
return None
def parse_page(html):
doc=pq(html)
links=doc('.commentlist .row .text p a')
for link in links:
image_url='http:'+pq(link).attr('href')
yield image_url
def download_image(url):
response=requests.get(url,headers=headers)
try:
if response.status_code==200:
return response.content
return None
except RequestException:
return None
def save_image(content):
path_name='{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')
if not os.path.exists(path_name):
with open(path_name,'wb') as f:
f.write(content)
f.close()
def main(page):
print('===============开始抓取第%r页==============='%page)
url = 'http://jandan.net/ooxx/page-{}#comments'.format(page)
html=get_page(url)
if html:
urls=parse_page(html)
for url in urls:
print('正在下载:%r'%url)
content=download_image(url)
save_image(content)
if __name__=='__main__':
pool=Pool()
pool.map(main,[page*1 for page in range(1,137)])
运行结果如下:
总共下载下来3560几张图片:
二:Python使用BeautifulSoup爬取妹子图
获取首页分类标签地址,传入下一步
获取每个分类下内容页面地址
获取内容页面图片地址以及标题,以页面标题作为文件夹名
最后保存图片就好了
代码
所需包
import os
import sys
import urllib2
from bs4 import BeautifulSoup
import requests
import lxml
import uuid
获取地址
首先说BeautifulSoup真的是爬虫利器,不过需要注意这里返回的list,还需要通过for循环读取每个地址。贴一段官方解释:
下面给出的代码是从首页获取每个分类的地址,其他的获取包括图片地址,内容页地址也都是大同小异,然后一直嵌套就可以了。
def get_mei_channel(url):
web_data=requests.get(url)
web_data.encoding='gb2312'
soup=BeautifulSoup(web_data.text,'lxml')
channel=soup.select('body span a')
return channel
##获取分类地址
保存图片
这里需要注意的是保存图片的时候需要加上header,应该是网站更新了验证,去年爬妹子图直接保存就可以的。
文件命名的话我引入了uuid包来生成唯一guid,避免重名保存失败。
def save_pic(url,path):
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
request = urllib2.Request(url, None, header)
response = urllib2.urlopen(request)
filename = path +'/'+str(uuid.uuid1())+'.jpg'
with open(filename,"wb") as f:
f.write(response.read())
##保存图片,生成唯一guid作为文件名
嵌套
最后按照思路一步步嵌套起来就可以啦,贴完整代码:
# -*- coding: utf-8 -*-
import os
import sys
import urllib2
from bs4 import BeautifulSoup
import requests
import lxml
import uuid
def judge_folder(path):
if os.path.isdir(path):
return False
else:
os.mkdir(path)
return True
def save_pic(url,path):
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
request = urllib2.Request(url, None, header)
response = urllib2.urlopen(request)
filename = path +'/'+str(uuid.uuid1())+'.jpg'
with open(filename,"wb") as f:
f.write(response.read())
def get_mei_channel(url):
web_data=requests.get(url)
web_data.encoding='gb2312'
soup=BeautifulSoup(web_data.text,'lxml')
channel=soup.select('body span a')
return channel
def get_mei_info(url):
web_data=requests.get(url)
web_data.encoding='gb2312'
soup=BeautifulSoup(web_data.text,'lxml')
info=soup.select('body div.pic a')
return info
def get_mei_pic(url):
web_data=requests.get(url)
web_data.encoding='gb2312'
soup=BeautifulSoup(web_data.text,'lxml')
pic=soup.select('body p img')
titlelist=soup.select('body div h2 a')
for list in titlelist:
path_folder = format(list.get_text())
path = root_folder + path_folder.encode('utf-8')
print '创建文件夹>>>'+ path_folder.encode('utf-8') +'>>>'
if judge_folder(path):
print '***开始下载啦!!***'
else:
pic =[]
print '***文件夹已存在,即将开始保存下一个页面***'
return pic ,path
def MeiZiTuSpider(url):
channel_list = get_mei_channel(url)
for channel in channel_list:
channel_url = (channel.get('href'))
channel_title = (channel.get('title'))
print '***开始查找 '+channel_title.encode('utf-8') +' 分类下的妹子图***'
info_list = get_mei_info(channel_url)
for info in info_list:
info_url = (info.get('href'))
pic_list,path = get_mei_pic(info_url)
for pic in pic_list:
pic_url = (pic.get('src'))
save_pic(pic_url,path)
root_folder = 'MEIZITU/'
url='http://www.meizitu.com/'
if __name__ == "__main__":
if os.path.isdir(root_folder):
pass
else:
os.mkdir(root_folder)
MeiZiTuSpider(url)
print '****MeiZiTuSpider@Awesome_Tang****'
三、Python Scrapy爬取妹子图
得益于强大的scrapy框架,写个简单的爬虫还是很容易的,但是如果想写的通用和健全还是挺难的,不过对于爬图片来说,相对来说更简单,简单粗暴的做法就是爬取页面所有图片,然后在爬取页面所有a链接,再去这些a链接页面爬取所有图片,递归获取...但是这样容易陷入死循环,不过强大的scrapy框架有一个设置爬取深度的选项,设置一下即可!
直接上代码吧,scrapy框架的基本用法我就不介绍,这里只做一些关键点解析,请注意查看注释:
# -*- coding:utf-8 -*-
# ! /bin/bash/python3
from urllib.parse import urljoin
from scrapy.spiders import Spider
from scrapy.http import Request
from picScrapy.items import PicscrapyItem
class PicSpider(Spider):
name = "pic" # 定义爬虫名,启动爬虫的时候用到
start_url = 'http://www.win4000.com/wallpaper_2285_0_10_1.html' # 爬虫入口
# 设置爬虫的请求头,防止爬取失败
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36',
}
def start_requests(self):
# 据观察,爬取的页面url是有规律的,后面的数字从1到167变化
for i in range(1, 167):
url = 'http://www.win4000.com/wallpaper_2285_0_10_%d.html' % i
yield Request(url, headers=self.headers)
def parse(self, response):
item = PicscrapyItem()
# 获取页面所有的img标签地址,待下载
item['image_urls'] = response.xpath('//img/@src').extract()
yield item
# 提取界面所有的url,待爬取
all_urls = response.xpath('//a/@href').extract()
# 遍历获得的url,如果满足条件,继续爬取
for url in all_urls:
url = urljoin(self.start_url, url)
yield Request(url, callback=self.parse)
下载图片
上面的代码获取了页面所有img标签地址存在一个item对象里面,这个对象会被传递到pipelines里面进行处理,这里下载也是用到框架的组件,做了一些自定义设置:
# -*- coding: utf-8 -*-
import hashlib
import re
from scrapy.pipelines.images import ImagesPipeline
from scrapy import Request
from scrapy.utils.python import to_bytes
class PicscrapyPipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for url in item['image_urls']:
# 做了一下判断,排除一些无效链接
if re.match(r'http', url):
yield Request(url)
# 重新定义了一下存储路径,默认情况下是存在一个full文件夹里面
def file_path(self, request, response=None, info=None):
if not isinstance(request, Request):
url = request
else:
url = request.url
image_guid = hashlib.sha1(to_bytes(url)).hexdigest() # change to request.url after deprecation
return '%s.jpg' % image_guid
图片下载存储路径在settings里面配置,还可以配置图片大小,过滤掉不符合条件的图片
# 爬取深度
DEPTH_LIMIT = 3
# 图片存放位置
IMAGES_STORE = '/home/jwang/Videos/Pic'
# 图片最小宽度
IMAGES_MIN_WIDTH = 500
# 图片最小高度
IMAGES_MIN_HEIGHT = 500
还有一些选项需要注意:
# 下载延迟,别把别人人站点拖垮了,慢点
DOWNLOAD_DELAY = 0.2
# 爬虫并发数,默认是 16
CONCURRENT_REQUESTS = 20
最后,启动爬虫,收获一堆妹子..图
python3 -m scrapy crawl pic --loglevel INFO
此文有仿照其他作者的,若有侵权请联系小编更改!
作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这是一个我的python交流群:831524055,不管你是小白还是大牛欢迎入驻 ,讨论技术, 大家一起交流学习成长!