200字
Python爬虫实战:手把手教你批量抓取高清美女图片
2025-12-16
2025-12-16

image-GxZa.png

Python爬虫实战:手把手教你抓取彼岸桌面高清美女壁纸

在学习Python爬虫的过程中,实战是最好的老师。今天我们将通过一个具体的案例——抓取 彼岸桌面 (netbian.com) 的美女分类壁纸,来学习如何使用 requestsre(正则表达式)模块编写一个简单的图片爬虫。

彼岸桌面是一个质量非常高的壁纸网站,结构清晰,非常适合作为爬虫新手的练习对象。

1. 准备工作

在开始编写代码之前,我们需要确保安装了必要的Python库。本次实战主要使用 requests 发送网络请求,使用 re 进行数据解析。

如果你的环境中还没有安装 requests,可以通过以下命令安装:

pip install requests

2. 爬虫思路分析

编写爬虫通常遵循以下步骤:

  1. 分析目标网站:确定要抓取的URL规律,查看网页源代码结构。
    • 目标URLhttp://www.netbian.com/meinv/
    • 编码格式:该网站使用 GBK 编码,解码时需要注意。
    • 反爬策略:该网站有基础的反爬虫机制,必须设置 User-Agent,最好也带上 Referer
  2. 获取列表页内容:访问分类首页,获取包含壁纸详情页链接的HTML。
  3. 提取详情页链接:从列表页中解析出每一个壁纸的详情页面URL(例如 /desk/12345.htm)。
  4. 进入详情页:遍历每一个详情页,获取大图的真实下载地址。
  5. 下载图片:请求大图地址并保存到本地。
  6. 翻页处理:处理多页抓取逻辑(index_2.htm, index_3.htm 等)。

3. 代码实现与详解

下面我们将逐步实现这个爬虫。

3.1 引入库与配置

首先引入必要的库,并设置全局配置。

import re
import requests
import os
import time
import random

# 配置部分
BASE_URL = "http://www.netbian.com"
START_URL = "http://www.netbian.com/meinv/"
SAVE_DIR = os.path.join(os.getcwd(), "images_netbian") # 图片保存路径

# 设置请求头,必须带上 User-Agent,否则会被拦截
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Referer': 'http://www.netbian.com/',
}

3.2 获取网页源码

我们需要一个通用的函数来获取网页内容,并处理编码和异常。

def get_html(url, retries=3):
    """获取网页源码,包含重试机制"""
    for i in range(retries):
        try:
            response = requests.get(url, headers=HEADERS, timeout=10)
            # 关键点:彼岸桌面使用 gbk 编码
            response.encoding = "gbk" 
            if response.status_code == 200:
                return response.text
            print(f"请求失败 (状态码 {response.status_code}): {url}")
        except requests.RequestException as e:
            print(f"请求异常 (尝试 {i+1}/{retries}): {e}")
            time.sleep(random.uniform(1, 3))
    return None

3.3 提取详情页链接

列表页中包含了许多缩略图和指向详情页的链接。我们需要提取出形如 /desk/xxxxx.htm 的链接。

def get_detail_links(html):
    """从列表页提取详情页链接"""
    if not html:
        return []
    
    # 正则匹配 href="/desk/..."
    links = re.findall(r'href="(/desk/\d+\.htm)"', html)
    
    # 去重
    unique_links = list(set(links))
    print(f"本页发现 {len(unique_links)} 个壁纸链接")
    return unique_links

3.4 核心逻辑:遍历与下载

这是爬虫的主循环。我们先遍历列表页,再进入详情页抓取大图。

def main():
    # 创建保存目录
    if not os.path.exists(SAVE_DIR):
        os.makedirs(SAVE_DIR)
    
    global_count = 0
    
    # 爬取前 3 页 (range(1, 4) 表示 1, 2, 3)
    for page in range(1, 4):
        if page == 1:
            url = START_URL
        else:
            # 翻页规律: index_2.htm, index_3.htm
            url = f"{START_URL}index_{page}.htm"
            
        print(f"\n>>> 正在访问列表页: {url}")
        list_html = get_html(url)
        
        if not list_html:
            continue
            
        detail_links = get_detail_links(list_html)
        
        for link in detail_links:
            detail_url = BASE_URL + link
            
            detail_html = get_html(detail_url)
            if not detail_html:
                continue
            
            # 提取大图链接
            # 策略:先定位 <div class="pic"> 区域,再提取里面的 img src
            pic_div_match = re.search(r'<div class="pic">.*?</div>', detail_html, re.S)
            
            img_url = ""
            if pic_div_match:
                pic_content = pic_div_match.group()
                # 匹配 http://img.netbian.com/file/...jpg
                img_match = re.search(r'src="(http://img\.netbian\.com/file/[^"]+\.jpg)"', pic_content)
                if img_match:
                    img_url = img_match.group(1)
            
            if img_url:
                global_count += 1
                print(f"正在下载第 {global_count} 张: {img_url}")
                
                try:
                    img_data = requests.get(img_url, headers=HEADERS, timeout=15).content
                    with open(os.path.join(SAVE_DIR, f"{global_count}.jpg"), "wb") as f:
                        f.write(img_data)
                except Exception as e:
                    print(f"下载失败: {e}")

                # 礼貌性延时
                time.sleep(random.uniform(0.5, 1.5))

if __name__ == "__main__":
    main()

4. 关键技术点总结

  1. 编码处理:很多中文老站使用 GBK 编码,如果直接使用默认编码会出现乱码,必须设置 response.encoding = 'gbk'
  2. 反爬虫
    • User-Agent:必须伪装成浏览器。
    • Referer:部分图片服务器会检查引用页,防止盗链。
    • 延时:使用 time.sleep 控制请求频率,既是为了防封,也是为了减轻对方服务器压力。
  3. 正则提取技巧
    • 先定位大块区域(如 <div class="pic">...</div>),再在区域内精确匹配,可以避免匹配到侧边栏或推荐位的无关图片。

完整代码

import re
import requests
import os
import time
import random

# 配置部分
BASE_URL = "http://www.netbian.com"
START_URL = "http://www.netbian.com/meinv/"
SAVE_DIR = os.path.join(os.getcwd(), "images_netbian")

# 必须带上 User-Agent,否则彼岸桌面会拦截
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Referer': 'http://www.netbian.com/',
}

def setup_directory(directory):
    """确保保存目录存在"""
    if not os.path.exists(directory):
        print(f"正在创建保存目录: {directory}")
        os.makedirs(directory)

def get_html(url, retries=3):
    """获取网页源码,包含重试机制"""
    for i in range(retries):
        try:
            response = requests.get(url, headers=HEADERS, timeout=10)
            # 彼岸桌面通常使用 gbk 编码
            response.encoding = "gbk" 
            if response.status_code == 200:
                return response.text
            print(f"请求失败 (状态码 {response.status_code}): {url}")
        except requests.RequestException as e:
            print(f"请求异常 (尝试 {i+1}/{retries}): {e}")
            time.sleep(random.uniform(1, 3))
    return None

def get_detail_links(html):
    """从列表页提取详情页链接"""
    if not html:
        return []
    
    # 提取形如 /desk/12345.htm 的链接
    # 注意:彼岸桌面的详情页链接通常是 /desk/数字.htm
    links = re.findall(r'href="(/desk/\d+\.htm)"', html)
    
    # 去重
    unique_links = []
    for link in links:
        if link not in unique_links:
            unique_links.append(link)
            
    print(f"本页发现 {len(unique_links)} 个壁纸链接")
    return unique_links

def download_image(img_url, count):
    """下载单张图片"""
    try:
        # 获取图片内容
        img_response = requests.get(img_url, headers=HEADERS, timeout=15)
        
        if img_response.status_code != 200:
            print(f"图片下载失败: {img_url}")
            return False
            
        file_path = os.path.join(SAVE_DIR, f"{count}.jpg")
        
        with open(file_path, "wb") as f:
            f.write(img_response.content)
            
        print(f"[成功] 保存第 {count} 张图片: {file_path}")
        return True
    except Exception as e:
        print(f"[失败] 下载图片出错 {img_url}: {e}")
        return False

def main():
    setup_directory(SAVE_DIR)
    
    global_count = 0
    
    # 爬取前 3 页 (可以根据需要修改 range)
    for page in range(1, 4):
        if page == 1:
            url = START_URL
        else:
            url = f"{START_URL}index_{page}.htm"
            
        print(f"\n>>> 正在访问列表页: {url}")
        list_html = get_html(url)
        
        if not list_html:
            continue
            
        detail_links = get_detail_links(list_html)
        
        for link in detail_links:
            detail_url = BASE_URL + link
            # print(f"  正在处理详情页: {detail_url}")
            
            detail_html = get_html(detail_url)
            if not detail_html:
                continue
            
            # 提取大图链接
            # 结构通常是: <div class="pic">...<img src="http://img.netbian.com/..." ...>
            # 我们先定位到 pic div,再提取 img
            # 简化正则: 寻找 class="pic" 附近的 img src
            # 或者直接匹配特定域名的图片,彼岸大图通常在 img.netbian.com/file/...
            
            # 策略:先尝试匹配 <div class="pic"> 区域,确保不抓到缩略图
            pic_div_match = re.search(r'<div class="pic">.*?</div>', detail_html, re.S)
            
            img_url = ""
            if pic_div_match:
                pic_content = pic_div_match.group()
                img_match = re.search(r'src="(http://img\.netbian\.com/file/[^"]+\.jpg)"', pic_content)
                if img_match:
                    img_url = img_match.group(1)
            
            if img_url:
                global_count += 1
                download_image(img_url, global_count)
                # 随机延时,防止对服务器造成过大压力
                time.sleep(random.uniform(0.5, 1.5))
            else:
                print(f"  未在页面 {detail_url} 找到大图")

    print(f"\n所有任务完成,共下载 {global_count} 张图片。")

if __name__ == "__main__":
    main()

5. 总结

通过这个脚本,我们成功实现了对彼岸桌面美女壁纸的批量抓取。相比于之前的代码,这个版本更加健壮,能够自动处理多页、自动创建目录,并加入了必要的反爬措施。

⚠️ 友情提示

  • 爬虫仅供学习交流,请勿用于商业用途。
  • 请合理控制爬取频率,做一个文明的爬虫工程师。

快运行代码试试吧!你的 images_netbian 文件夹很快就会被填满!

Python爬虫实战:手把手教你批量抓取高清美女图片
作者
一晌小贪欢
发表于
2025-12-16
License
CC BY-NC-SA 4.0

评论