老司机带你用python来爬取妹子图

一:Python爬虫入门-利用requsets库爬取煎蛋网妹子图

其实之前是想利用煎蛋网来联系一下scrapy的ImagesPipeline爬取煎蛋网的妹子图并下载下来保存到本地,无奈这个ImagePipeline一点都不给面子一直报404错误,而且我还不知道问题出在哪里,所以一怒之下就不用框架了,直接爬一下。

**源码视频书籍练习题等资料进群984632579 即可免费获取

更多python记得关注我的公众号 从0到1Python之路**

先来一张:

《老司机带你用python来爬取妹子图》

从下图可以看出总的页数:

《老司机带你用python来爬取妹子图》

在翻页的过程中URL中只有页数是在发生改变的,这个就比较好构建URL了,而且图片的信心在原始的请求里面就能够找到图片的链接地址,这个也比较好办:

《老司机带你用python来爬取妹子图》

于是可以开始写代码了:

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)])

运行结果如下:

《老司机带你用python来爬取妹子图》

总共下载下来3560几张图片:

《老司机带你用python来爬取妹子图》

二:Python使用BeautifulSoup爬取妹子图

获取首页分类标签地址,传入下一步

《老司机带你用python来爬取妹子图》

获取每个分类下内容页面地址

《老司机带你用python来爬取妹子图》

获取内容页面图片地址以及标题,以页面标题作为文件夹名

《老司机带你用python来爬取妹子图》

最后保存图片就好了
代码

所需包

import os      
import sys    
import urllib2
from bs4 import BeautifulSoup  
import requests  
import lxml
import uuid

获取地址

首先说BeautifulSoup真的是爬虫利器,不过需要注意这里返回的list,还需要通过for循环读取每个地址。贴一段官方解释:

《老司机带你用python来爬取妹子图》

下面给出的代码是从首页获取每个分类的地址,其他的获取包括图片地址,内容页地址也都是大同小异,然后一直嵌套就可以了。

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来爬取妹子图》

**源码视频书籍练习题等资料进群984632579 即可免费获取

更多python记得关注我的公众号 从0到1Python之路**

    原文作者:编程新视野
    原文地址: https://www.jianshu.com/p/cd327ea72489
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞