前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Fu*k meizitu

Fu*k meizitu

作者头像
BORBER
发布2019-08-06 17:30:36
1.4K0
发布2019-08-06 17:30:36
举报
文章被收录于专栏:BORBER

爬取妹子图全站图片

由于我没有提前记录过程 所以没有截图,以后尽量把自己的思考过程都全部截图发出来。

首先通过 首页 的的所有分页面爬取所有的图片的首页链接 (写完之后发现有另一个界面 更容易爬 但是已经写完了就没有改了 这里放上链接 全部

这一步是很简单的, 主要就是吧真正的套图的链接全部整理出来,放在 mongo/meizitu/home 这个表里面,准备二次加工。

代码语言:javascript
复制
#home_url.py

from toolkits.ip_proxies import get_proxies
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import requests
import pymongo
import time

client = pymongo.MongoClient('localhost', 27017)
meizitu = client['meizitu']
home = meizitu['home']

ua = UserAgent()

headers = {
    'User-Agent': ua.random,
    'Referer': 'https://www.mzitu.com'
}


def get_home_url(i=0):
    url = f'https://www.mzitu.com/page/{i}'
    wb_data = requests.get(url, proxies=get_proxies(), headers=headers, timeout=3)
    soup = BeautifulSoup(wb_data.text, 'lxml')
    real = soup.select('#pins > li > span > a')
    for index, each in enumerate(real):
        home.insert_one({'URL': each.get('href')})

接下来就是对爬去的链接做二次加工。

把每个链接对应的套图的 标题,链接,最大页码数 提取出来,因为妹子图的网页结构非常简单,每张图对应的URL 都是首页后面加页码,所以可以利用这个,减少储存的URL数。保存的 title 是作为以后的储存目录子文件夹名。

以及一个用于之后下载时提取每个界面图片的函数(get_imgs(url))

这里尤其要说 关于

代码语言:javascript
复制
for i in range(10):

的作用。

不知道是由于网站的反扒措施,还是我使用的代理ip池中有ip失效,总之会有request中断的现象,总会导致爬虫强制退出,这一退出就是浪费几十分钟的时间,所以加上 try 的报错处理之后,程序的鲁棒性会提高非常多,这个结构也出现在随后的几个py文件中,随后不在作解释。

这里也强烈建议使用 IP代理 可以参考我的上一篇博文。都打包好了可以直接使用。

代码语言:javascript
复制
#find_imgs.py

from toolkits.ip_proxies import get_proxies
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import requests
import pymongo
import time


client = pymongo.MongoClient('localhost', 27017)
meizitu = client['meizitu']
home = meizitu['home']
imgs = meizitu['imgs']

ua = UserAgent()


def get_title_and_pages(url):
    headers = {
        'User-Agent': ua.random,
        'Referer': 'https://www.mzitu.com'
    }
    for i in range(10):
        try:
            wb_data = requests.get(url, headers=headers, proxies=get_proxies())
            while wb_data != 200:
                wb_data = requests.get(url, headers=headers,proxies=get_proxies())
        except Exception:
            if i >= 9:
                print('Fuck!')
            else:
                time.sleep(0.5)
        else:
            break

    title = url[-6:]
    soup = BeautifulSoup(wb_data.text, 'lxml')
    titles = soup.select('div.main h2')
    for each in titles:
        title = each.get_text()
        break
    url_max = soup.select('div.pagenavi > a > span')[-2].get_text()
    imgs.insert_one({'title': title, 'url': url, 'url_max': int(url_max)})


def get_imgs(url):
    headers = {
        'User-Agent': ua.random,
        'Referer': 'https://www.mzitu.com'
    }
    for i in range(10):
        try:
            wb_data = requests.get(url, headers=headers, proxies=get_proxies())
            while wb_data.status_code != 200:
                wb_data = requests.get(url, headers=headers, proxies=get_proxies())
        except Exception:
            if i >= 9:
                print('Fuck!')
            else:
                time.sleep(0.5)
        else:
            break
    soup = BeautifulSoup(wb_data.text, 'lxml')
    img_url = soup.select('div.main-image img')[0].get('src')
    return img_url

接下来是下载模块

代码语言:javascript
复制
#download_imgs.py

from toolkits.ip_proxies import get_proxies
from fake_useragent import UserAgent
import requests
import os
import time

seq = '/'
ua = UserAgent()

headers = {
    'User-Agent': ua.random,
    'Referer': 'https://www.mzitu.com'
}


def downimg(index, url, path):
    print(url)
    filename = path + seq[0] + str(index) + url[-4:]
    print(filename)
    if os.path.exists(filename):
        return
    for i in range(10):
        try:
            r = requests.get(url, headers=headers, proxies=get_proxies(), stream=True)
        except Exception :
            if i >= 9:
                print('Fuck!')
            else:
                time.sleep(0.5)
        else:
            time.sleep(0.1)
            break
    with open(filename, 'wb') as code:
        for img_data in r.iter_content(128):
            code.write(img_data)

最后是主函数:

这里面有一个大坑,坑的无与伦比,这也是这个爬虫我学到的比较重要的东西之一,pymongo创造的链接,是有时效性的,及时加了 no_cursor_timeout=True 他本身的链接就是以后时效性的,所以,出了跑错处理,还需要进行重连。

代码语言:javascript
复制
def download_all():
    client_local = pymongo.MongoClient('localhost', 27017)
    meizitu_local = client_local['meizitu']
    imgs_local = meizitu_local['imgs']
    items = imgs_local.find(no_cursor_timeout=True)

这一段 就是在每一次进行 下载 调用时都进行一次重连。当然这一般就是在发生链接断开错误时才会再次调用的。(据网上资料,链接有效时间为10分钟)

代码语言:javascript
复制
#main.py

from test.home_url import get_home_url
from test.find_imgs import get_title_and_pages,get_imgs
from test.download_img import downimg
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import requests
import pymongo
import os
import time

client = pymongo.MongoClient('localhost', 27017)
meizitu = client['meizitu']
home = meizitu['home']
imgs = meizitu['imgs']

rootpath = '/home/x/BORBER/File/Tmp/meizitu' # 自己改
seq = '/'


def mkdir(path):
    folder = os.path.exists(path)
    if not folder:
        os.makedirs(path)


def home_all_url():
    for i in range(1, 226):
        get_home_url(i)
        print(f'Now in {i}')


def imgs_all_url():
    for index, each in enumerate(home.find(no_cursor_timeout=True)):
        print(f'Now in {index}')
        print(each['URL'])
        get_title_and_pages(each['URL'])
        home.delete_one({'URL': each['URL']})


def download_all():
    client_local = pymongo.MongoClient('localhost', 27017)
    meizitu_local = client_local['meizitu']
    imgs_local = meizitu_local['imgs']
    items = imgs_local.find(no_cursor_timeout=True)
    for item in items:
        filepath = rootpath + seq[0] + item['title']
        print(filepath)
        mkdir(filepath)
        for i in range(1, item['url_max']):
            downimg(i, get_imgs(item['url']+seq[0]+str(i)), filepath)
        imgs.delete_one({'url': item['url']})
    items.close()


def safe_download():
    for i in range(9999):
        try:
            download_all()
        except Exception:
            print('Fuck')
            time.sleep(0.5)
            download_all()
        else:
            break


def clear_all():
    meizitu.drop_collection('home')
    meizitu.drop_collection('imgs')


if __name__ == '__main__':
    home_all_url()
    imgs_all_url()
    safe_download()

此版本理论上可以一次运行成功 爬取全站 17万+图片 共计18.1G数据

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-07-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档