PPLAX 发表于 2026-2-20 09:14:35

【花马金裘】分享e621网站爬虫编写过程(以Sollyz为例)

本帖最后由 PPLAX 于 2026-2-20 15:26 编辑

想必有很多和我一样的人只有把喜欢的图片视频下载下来才能感觉到安心,下面分享一个e621网站的爬虫编写过程
首先看看关键词查询时url是如何构造的https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/69980ab9eeb64.webp这是直接关键词搜索的情况https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/69980aba20070.webp这是分页查询的情况url参数显然page代表页码,tags代表关键词/标签
然后再分析一下网站,现在首次进入会出现18+界面,刚开始以为需要进行认证才能获取页面(也就是伪造token)https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/69980abb34848.webp
不过通过分析源码发现,其实这个界面只是类似遮罩的效果,如果删除这个元素,其实是可以直接看到网页内容的,这个data-file-url就是我们要找的下载链接https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/6997cbebe4afe.webp
这里我们可以通过正则表达式data-file-url="(?P<url>.*?)".*?\nID: (?P.*?)\n​提取出图片的地址
众所周知,这种页面的图片肯定是循环堆砌相同元素呈现的,也就是只要用上面的正则匹配一下,就能获得这个页面的所有地址
代码如下:# 获得页面中的文件信息
# page_text 页面的文本内容
def getPageDatas(page_text):
    files = []

    obj = re.compile(r'data-file-url="(?P<url>.*?)".*?\nID: (?P<id>.*?)\n', re.S)
    results = obj.finditer(page_text)
    for result in results:
      url = result.group("url")
      id = result.group("id")
      name = url.split('/')[-1]
      file = {
            "url": url,
            "id": id,
            "name": name
      }
      files.append(file)
    return files

当然,某个关键词的图片不一定只有一页所以我们需要找到所有页码,然后经过一番分析,也很容易找到class为last page​的a标签内部文本就是页码长度,所以到时候请求的时候只需要进行14次分页请求,如果有想要尝试的可以去找找这段https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/6997cbec99c5e.webp这个文本应该如何提取呢,通过分析发现,在整个页面中,class="last page"只出现了一次,也就是说,使用bs4的find即可找到这个标签
代码如下:# 获得页面数量
# url 链接
# headers 请求头
# data 请求表单
def getLastPage(url, headers, data):
    try:
      with requests.get(url=url, headers=headers, data=data) as resp:
            bs = BeautifulSoup(resp.content, "html.parser")
            a = bs.find(name="a", attrs={"class": "page last"})
            last_page = (int) (a.text)
    except IndexError:
      last_page = 1

    return last_page

既然网页已经分析完毕,下面可以编写整体自动爬取的代码了import re
import requests
from bs4 import BeautifulSoup


# 获得页面数量
# url 链接
# headers 请求头
# data 请求表单
def getLastPage(url, headers, data):
    try:
      with requests.get(url=url, headers=headers, data=data) as resp:
            bs = BeautifulSoup(resp.content, "html.parser")
            a = bs.find(name="a", attrs={"class": "page last"})
            last_page = (int) (a.text)
    except IndexError:
      last_page = 1

    return last_page

# 获得页面中的文件信息
# page_text 页面的文本内容
def getPageDatas(page_text):
    files = []

    obj = re.compile(r'data-file-url="(?P<url>.*?)".*?\nID: (?P<id>.*?)\n', re.S)
    results = obj.finditer(page_text)
    for result in results:
      url = result.group("url")
      id = result.group("id")
      name = url.split('/')[-1]
      file = {
            "url": url,
            "id": id,
            "name": name
      }
      files.append(file)
    return files

# 获得下载的多线程任务数组,要await
# keyword 搜素的关键词
# path 下载路径
def resolve(keyword, path):
    # 若关键词为空,返回空数组,防止请求到一堆数据
    if keyword == '':
      return []
    # 请求头
    headers = {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36 Edg/104.0.1293.54"
    }
    # 链接
    url = "https://e621.net/posts?"
    # 表单
    data = {
      "page": 1,
      "tags": keyword
    }
    # 获得最后一页的页码
    lastPage = getLastPage(url=url, headers=headers, data=data)
    print("获取到总页数为{}".format(lastPage))
    # 获得页面文本
    print("目前正在处理:e621...")
    page_texts = []
    while data["page"] <= lastPage:
      print("正在抓取获取第" + str(data["page"]) + "个页面的内容")
      with requests.get(url=url, headers=headers, data=data) as resp:
            page_texts.append(resp.text)
      data["page"] += 1
    # 创建任务列表
    for page_text in page_texts:
            files = getPageDatas(page_text)
            i = 0
            for file in files:
                url = file["url"]
                with requests.get(url=url, headers=headers) as response:
                  if response.status_code == 200:
                        # 以二进制写入模式保存文件到本地
                        with open('{}/{}-{}'.format(path, file["id"], file["name"]), 'wb') as file:
                            file.write(response.content)
                            i = i+1
                        print("文件下载成功!")
                  else:
                        print("下载失败,状态码:", response.status_code)

if __name__ == '__main__':
    resolve('Sollyz', 'C:\\Users\\14586\Desktop\\test')

当然我们知道,requests​库是阻塞式的,当要下载的图片有成百上千个时,下载的等待时间甚至不如自己手动点击去下载,这时候就需要多线程出马了,于是我请ai老师帮我生成了一套使用场景是qt5且能够多线程进行的请求库:字数满了,果咩......并让他基于以上两套代码编写了对应的图形化界面爬虫代码
最终效果如图,如果重复下载的话会自动跳过这一条:https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/6997cbed664b2.webp

https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/69980c36f0462.webp

工具和本次爬取结果在附件,请查收

凯诺斯 发表于 2026-2-20 09:26:14

能够直接爬取图片并下载确实要方便很多呀{:6_165:}

娱乐法师火布偶 发表于 2026-2-20 09:30:08

网页自动爬取也是需要研究CSS的结构层次的

枫_Age 发表于 2026-2-20 09:45:42

教程写得明明白白,有技术宅好安心{:4_99:}

Chare 发表于 2026-2-20 09:52:43

虽然说现在有gallery-dl也可以下载像是e站或者fa站的资源,但是手写一个爬虫程序我觉得也很是不容易,尤其楼主这个还有界面还是方便不少。不过之前用gallery-dl确实会有些小问题,就是它会直接下载图片的原图,而这些原图一般会非常大,有时候下下来我还得再压缩一遍。挺好奇有没有办法可以下载这些网页的预览图而不是原图大小呢

lqiang1990 发表于 2026-2-20 09:59:29

这样的话就可以轻松保存图片了,谢谢

野生阿努厨 发表于 2026-2-20 10:27:55

很有技术佬的feel,技术细节和实现步骤已经掰扯得很清楚了{:6_200:}

Z_Long 发表于 2026-2-20 10:34:43

感谢楼主分享技术,很好用

Burry 发表于 2026-2-20 10:39:00

通过脚本来抓取想要的图吗,确实好方便呢。

notunicorna 发表于 2026-2-20 10:44:24

不知道为什么,看不到图形界面的展示图

Alicen2233 发表于 2026-2-20 10:46:46

楼主真的好厉害,真的试图教会坛友,真的好人啊

PPLAX 发表于 2026-2-20 10:54:42

https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/6997cbebe4afe.webp
https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/6997cbec99c5e.webp
https://youke.xn--y7xa690gmna.cn/s1/2026/02/20/6997cbed664b2.webp


源码分析图和最终效果图(第一次发帖,很多地方不太会用)

枫叶UC 发表于 2026-2-20 10:59:02

本帖最后由 枫叶UC 于 2026-2-20 11:00 编辑

可以使用组合词吗?+和-的那种
如果第二次爬取会跳过已有项目吗?

Sloanx 发表于 2026-2-20 11:17:55

谢谢楼主的分享 能直接爬取东西 然后下载 确实舒服多了

Xiaoshi 发表于 2026-2-20 11:22:53

非常详细的教程惹,这下子可以爬到想看的内容了

Cheng2025 发表于 2026-2-20 11:32:02

很有用的工具,感谢楼主分享

kook 发表于 2026-2-20 12:00:22

有爬虫能自动下载解放双手了:lol

KurisuV 发表于 2026-2-20 12:07:04

非常感谢楼主分享惹!爬虫脚本对于有一定基础的朋友而言还是挺实用的{:6_200:}

凯登 发表于 2026-2-20 12:43:35

啊哈,一般都是用扩展直接来爬的,感谢分享编写过程,又学到新知识捏~:lol

点击输入文字 发表于 2026-2-20 12:47:51

https://img.gamemale.com/album/202512/21/025159lywkirfumgftwuww.jpeg很好用的好东西惹,就是代码我完全看不懂XwX
页: [1] 2 3
查看完整版本: 【花马金裘】分享e621网站爬虫编写过程(以Sollyz为例)