szsnk144864 发表于 2022-5-8 16:49

Python爬虫爬取美女写真

本帖最后由 szsnk144864 于 2022-5-11 18:49 编辑

我有一个朋友告诉我发现一个美女写真网站,要把分类里的图偏爬下来欣赏,


赶巧的是我最近正好在学爬虫,入手搞了一下,只是多线程搞不定


代码仅供参考学习,如造成其它后果请自行负责





import time
import requests
from lxml import etree
import os# 创建文件夹

print('请确保输出的是 1 或者是 2 ,否则会报错')
out_name = input('请输入数字1或者2:         1、清新美女    2、清纯少女          ')
url1 = 'https://www.vmgirls.com/fresh/'
url2 = 'https://www.vmgirls.com/pure/'
if int(out_name) == 1:
    url = url2
elif int(out_name)== 2:
    url = url1


# 获取响应函数
def send_request(address):
    headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
    }
    response = requests.get(url=address, headers=headers)
    response.encoding = 'utf-8'
    return response# 不知道为啥要这么做,如果不做这步,后面会出错


def save_img(si1, si2, si3, si4):       # si1 = 图片名称   si2 = 图片数量   si3 = 图片存储地址       si4 = resp 响应
    with open((si3 + '//' + si1), mode='wb') as f:
      print('共「' + (str(si2)) + '」张图片' + '正在保存图片:' + si1 + '   到:「' + si3 + '」文件夹里')# + '剩余' + str(get_img_num - 1),这里不会写,就注释了
      f.write(si4.content)


resp_1 = send_request(url)
tree_1 = etree.HTML(resp_1.text)
get_page_num = tree_1.xpath('/html/body/main/div/nav/div/a/text()')[-1]# 精准获取所有页面地址

collout = []# 用来存储所有的页面url
for s1 in range(1, int(get_page_num) + 1):# 第一次循环:拼接url。主要是从第二页开始,url需要在后面加 代码
    if s1 == 1:# 因为页面的不同,在第一页的时候,不需要在后面加编号
      get_long_url = url
    else:
      get_long_url = url + f'page/{s1}/'# 将长链接与短链接拼接在一起
    collout.append(get_long_url)# 将获取到的全部页数,添加到数组里,方便后面循环

for s2 in collout:# 第二次循环:获取每页每个图片的地址。通过所有的页面,for循环来获取每个页面,每个图片的链接
    resp_2 = send_request(s2)# 获取每个页面的响应
    tree_2 = etree.HTML(resp_2.text)
    get_one_url = tree_2.xpath('/html/body/main/div/div//div/div/a/@href')# 精准获取每一页,每个图片的链接

    # 这个s3 这个for 循环需要写在 s2 里面,因为s2 代表的是所有页面,然后每个页面里有24个图片,这时候for循环就会分别获取这24个图片地址
    # 全部获取之后在跳出此循环,进入到s4循环里
    for s3 in get_one_url:# 第三次循环:获取每个页面的图片地址。
      time.sleep(1)
      resp_3 = send_request(s3)
      tree_3 = etree.HTML(resp_3.text)
      get_img_url = tree_3.xpath('/html/body/main/div/div/div/div/div/div/div/a/img/@src')# 精准获取页面里所有图片地址
      get_img_num = (len(get_img_url))# 获取每个页面有多少张图片,通过len来获取列表数量
      get_img_name_folder = tree_3.xpath('/html/body/main/div/div/div/div/div/h1/text()')# 精准获取该页面的名称,方便后面创建文件夹

      # 创建目录
      img_path = 'e://img//' + get_img_name_folder# 用于存储文件放入之后的位置,修改'e://img//',可以选择保存后的位置
      if not os.path.exists(img_path):# 如果没有这个文件,创建文件夹
            os.makedirs(img_path)
            print(get_img_name_folder + '   目录创建成功,准备开始保存图片')

      #第四次循环:保存图片。
      for s4 in get_img_url:# 通过获取的每一个图片url,进行for循环,这个循环是需要放在s3里的,因为s3是一个列表,包括了该页面所有的图片
            time.sleep(1)
            resp_4 = send_request(s4)
            get_img_name = s4.split('/')[-1] # 通过切割url地址,来获取保存的图片名字,用于输出后的图片名字
            # 保存文件
            save_img(get_img_name, get_img_num, img_path, resp_4)

            send_request(s4)# 关闭每个页面获取到的图片url响应
      print('❤   '+get_img_name_folder + '   图片爬取完毕,准备爬取下一个.......')
    send_request(s3)# 关闭每个图片页面的响应
send_request(s2)# 关闭获取所有页面url的响应
send_request(url)# 关闭获取所有页面url的响应



话痨司机啊 发表于 2022-5-9 20:53

本帖最后由 话痨司机啊 于 2022-5-9 20:58 编辑

from collections import namedtuple
from concurrent.futures import ThreadPoolExecutor
from typing import Dict, List
import re
import requests
import os
from datetime import datetime
import keyboard
from fake_useragent import UserAgent
from lxml import etree
from rich.console import Console

console = Console()
headers = {'User-Agent':UserAgent().random}
DATA = namedtuple('DATA',['year','month','day','title','href'])
url = 'https://www.vmgirls.com/archives.html'
img_list = ['jpg','png','gif','jpeg']

def start_requests():
    res = requests.get(url,headers=headers)
    et = etree.HTML(res.text)
    # 获取全部年份
    y = et.xpath('//div[@id="archives"]/h4/text()')
    for year in range(1,len(y)+1):
      # 每个月
      m = et.xpath(f'//div[@id="archives"]//ul[{year}]/li/span/text()')
      for month in range(1,len(m)+1):
            # 每天
            d = et.xpath(f'//div[@id="archives"]//ul[{year}]/li[{month}]/ul/li')
            for day in range(1,len(d)+1):
                # 每天的网址
                _day = et.xpath(f'//div[@id="archives"]//ul[{year}]/li[{month}]/ul/li[{day}]/text()')
                _href = et.xpath(f'//div[@id="archives"]//ul[{year}]/li[{month}]/ul/li[{day}]/a/@href')
                _title = et.xpath(f'//div[@id="archives"]//ul[{year}]/li[{month}]/ul/li[{day}]/a/text()')
                yield DATA(y,m,_day,_title,_href)


def get_data(yield_func):
    '''
    转换数据
    '''
    yield from yield_func


def save_img(url,path,title):
    '''
    保存图片
    '''
    imgcs = requests.get(url,headers=headers)
    et = etree.HTML(imgcs.text)
    IMG = et.xpath('//div[@class="nc-light-gallery"]//@href')
    for i in range(0,len(IMG)):
      if IMG.split('.')[-1] in img_list:
            res = requests.get(IMG,headers=headers)
            with open(f'{path}/{title}_{i}.jpg','wb') as f:
                f.write(res.content)
                nowdate = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                console.print(f'创建时间:{nowdate}\n保存路径:{path}\n文件:{title}_{i}.jpg 保存成功!\n提示:按esc退出')
                console.print('-'*70)
      if keyboard.read_key() == 'esc':
            raise KeyboardInterrupt


def mkdir_path(path):
    '''
    创建路径
    '''
    path = re.sub(r'[\s]','',path)
    if not os.path.exists(path):
      os.makedirs(path)
    return path

def main():
    '''
    多线程主函数
    '''
    with ThreadPoolExecutor(max_workers=5) as executor:
      try:
            for data in get_data(start_requests()):
                path = mkdir_path(os.path.join(os.getcwd(),'美女壁纸',data.year,data.month,data.day[:-2]))
                img_name = data.title
                url = data.href
                executor.submit(save_img,url,path,img_name)
      except Exception as e:
            console.print('程序即将退出!')
            os._exit(0)            

if __name__ == '__main__':
    main()

也是这个网站,写个多线程的给你参考,我爬了一点,小姐姐不太高清

py学徒 发表于 2022-5-8 22:31

return response# 不知道为啥要这么做,如果不做这步,后面会出错
---这是返回值,必须有的,给后面的爬取提供页面。
---request.get().text,把text加入进来,完全可以。

爬取,Bs4、正则,得搞定。Bs4,好用;但正则是王道。

哈,加油,起点很高。很赞!

澶╅殢浠佺紭 发表于 2022-5-8 20:04

谢谢分享,虽然不懂

sifan785622020 发表于 2022-5-8 20:23

感觉跟我刚学爬虫写的差不多

10072 发表于 2022-5-8 20:23

真不错 十分钟爬了一百张

yzxqhdx 发表于 2022-5-8 20:58

还有很大 的优化空间

layuai 发表于 2022-5-8 21:24

爬取规则最好直接正则来写,这样写稍微网站一改就不行了

szsnk144864 发表于 2022-5-8 21:53

sifan785622020 发表于 2022-5-8 20:23
感觉跟我刚学爬虫写的差不多

哈哈,我就是刚学的爬虫

szsnk144864 发表于 2022-5-8 21:54

10072 发表于 2022-5-8 20:23
真不错 十分钟爬了一百张

坚持下去,一定能爬完的:lol

szsnk144864 发表于 2022-5-8 21:55

yzxqhdx 发表于 2022-5-8 20:58
还有很大 的优化空间

大佬能给点建议吗{:1_918:}

szsnk144864 发表于 2022-5-8 21:56

layuai 发表于 2022-5-8 21:24
爬取规则最好直接正则来写,这样写稍微网站一改就不行了

原来如此,感谢大佬指点
页: [1] 2 3
查看完整版本: Python爬虫爬取美女写真