周二. 9 月 29th, 2026

?点击“博文视点Broadview”,获取更多书讯

你是否有这样的问题,学 Python 语言之后,能做什么?

Python的用途其实非常多,今天先来展示一个用Python采集漫画信息的实操案例。

01

目标站点数据源分析

▊ 爬去目标

本次要爬取的网站是一个漫画网站,打开站点,呈现在我们面前的是 15660 部漫画信息,我们的目标是全部“拿下”。

为了降低学习难度,本文只介绍针对列表页进行抓取的过程,里面涉及的目标数据结构如下。

1. 漫画标题

2. 漫画评分

3. 漫画详情页链接

4. 作者

同时,在案例代码中需要同步保存漫画封面,并以封面文件名为漫画命名。

漫画详情页还存在大量的标签,因不涉及数据分析,故不再提取。

▊ 涉及的Python模块

爬取模块requests,数据提取模块re,多线程模块 threading。

▊ 重点学习内容

爬虫编写流程。

数据提取,重点掌握行内 CSS 提取。

CSV 格式文件存储。

变换IP 规避反爬,该目标网站有反爬机制。

▊ 列表页分析

通过点击测试,得到的页码变化逻辑如下。

https://vol.moe/l/all,all,all,sortpoint,all,all,BL/1.htm

https://vol.moe/l/all,all,all,sortpoint,all,all,BL/2.htm

https://vol.moe/l/all,all,all,sortpoint,all,all,BL/524.htm

页面数据是服务器直接静态返回的,加载到 HTML 页面中。

目标数据所在的 HTML DOM 结构如下所示。

在正式编写代码前,可以先有针对性地处理一下正则表达式部分。

▊ 匹配封面图

在编写该部分正则表达式时,出现了下图所示的“折行+括号”问题。

正则表达式如下,这里重点需要注意 \s 可匹配换行符。

<div[.\s]*style=”background:url\((.*?)\)

▊ 匹配文章标题、作者、详情页地址

该部分内容所在的 DOM 行格式比较特殊,可以直接匹配出结果。下述正则表达式使用了分组命名的方法。

<a href=(?P<url>.*?)>(?P<title>.*?)</a> <br /> (?P<author>.*?) <br />

对于动漫评分部分的匹配就非常简单了,直接编写如下正则表达式即可。

<p style=“.*?”><b>(.*?)</b></p>02

整理出的需求

整理需求如下。 

1. 开启 5 个线程对数据进行爬取。

2. 保存所有的网页源码。

3. 依次读取源码,提取元素到 CSV 文件中。

本案例将优先保存网页源码到本地,然后对本地 HTML 文件进行处理。

03

编码时间

在编码测试的过程中,我们发现该网站存在反爬措施,会直接封杀爬虫程序的IP,导致程序还没有跑起来,就结束了。

再次测试,发现反爬技术使用重定向操作,即服务器发现是爬虫后,直接返回状态码 302,并重定向谷歌网站。

IP受限制的时间大概是 24 个小时,因此如果希望爬取到全部数据,需要通过不断切换 IP 和 UA ,将 HTML 静态文件保存到本地。

下述代码可以判断目标网站返回的状态码,如果为 302,则更换代理 IP,再次爬取。

import requestsimport reimport threadingimport timeimport random# 以下为UA列表,为节省篇幅只保留两项,完整版请联系作者获取USER_AGENTS = [ “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”, “Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)”,]# 循环获取 URLdef get_image(base_url, index): headers = { “User-Agent”: random.choice(USER_AGENTS) } print(f”正在抓取{index}“) try: res = requests.get(url=base_url, headers=headers, allow_redirects=False, timeout=10) print(res.status_code) # 当服务器返回 302状态码之后 while res.status_code == 302: # 可直接访问 http://118.24.52.95:5010/get/ 获得一个代理IP ip_json = requests.get(“http://118.24.52.95:5010/get/”, headers=headers).json() ip = ip_json[“proxy”] proxies = { “http”: ip, “https”: ip } print(proxies) # 使用代理IP继续爬取 res = requests.get(url=base_url, headers=headers, proxies=proxies, allow_redirects=False, timeout=10) time.sleep(5) print(res.status_code) else: html = res.text # 读取成功,保存为 html 文件 with open(f”html/{index}.html”, “w+”, encoding=“utf-8”) as f: f.write(html) semaphore.release() except Exception as e: print(e) print(“睡眠 10s,再去抓取”) time.sleep(10) get_image(base_url, index)if __name__ == __main__: num = 0 # 最多开启5个线程 semaphore = threading.BoundedSemaphore(5) lst_record_threads = [] for index in range(1, 525): semaphore.acquire() t = threading.Thread(target=get_image, args=( f”https://vol.moe/l/all,all,all,sortpoint,all,all,BL/{index}.htm”, index)) t.start() lst_record_threads.append(t) for rt in lst_record_threads: rt.join()

只开启了 5 个线程,爬取过程如下所示。

经过 20 多分钟的等待,524 页数据全部以静态页形式保存在了本地 HTML 文件夹中。

 

当文件全部存储到本地之后,再进行数据提取就非常简单了。编写如下提取代码,使用 os 模块。

import osimport reimport requestsdef reade_html(): path = r”E:\pythonProject\test\html” # 读取文件 files = os.listdir(path) for file in files: # 拼接完整路径 file_path = os.path.join(path, file) with open(file_path, “r”, encoding=“utf-8”) as f: html = f.read() # 正则提取图片 img_pattern = re.compile(<div[.\s]*style=”background:url\((.*?)\)) # 正则提取标题 title_pattern = re.compile(“<a href=(?P<url>.*?)>(?P<title>.*?)</a> <br /> \[(?P<author>.*?)\] <br />”) # 正则提取得到 score_pattern = re.compile(<p style=”.*?”><b>(.*?)</b></p>) img_urls = img_pattern.findall(html) details = title_pattern.findall(html) scores = score_pattern.findall(html) # save(details, scores) for index, url in enumerate(img_urls): save_img(details[index][1], url)# 数据保存成 csv 文件def save(details, scores): for index, detail in enumerate(details): my_str = “%s,%s,%s,%s\n” % (detail[1].replace(“,”, “,”), detail[0], detail[2].replace(“,”, “,”), scores[index]) with open(“./comic.csv”, “a+”, encoding=“utf-8”) as f: f.write(my_str)# 图片按照动漫标题命名def save_img(title, url): print(f”正在抓取{title}—{url}“) headers = { “User-Agent”: “Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52” } try: res = requests.get(url, headers=headers, allow_redirects=False, timeout=10) data = res.content with open(f”imgs/{title}.jpg”, “wb+”) as f: f.write(data) except Exception as e: print(e)if __name__ == __main__:reade_html()

代码提取到 csv 文件如下所示。

关于详情页,即动漫的更新信息,可以使用上述逻辑再次爬取。

04

总结

完全学会本文中的操作,不仅需要用到 Python 的基础知识,还要掌握Python requests 模块、正则模块 re 、文件读写、多线程模块的相关内容。

想要快速学习这些内容,可以从阅读《滚雪球学Python》这本书开始。

滚雪球学 Python,书如其名,教授大家用类似滚雪球的思维学习 Python,第一遍浏览 Python 核心内容,第二遍补齐周边知识,第三遍夯实,第四遍拔高。每一遍滚雪球式的学习,都能丰富自己的知识。

限时五折优惠,快快扫码抢购吧!

发布:刘恩惠

审核:陈歆懿

如果喜欢本文欢迎 在看丨留言丨分享至朋友圈 三连<  PAST · 往期回顾  >Python,30年上位之路! 点击阅读原文,查看本书详情!

Avatar photo

作者 UU

友情提示:现在网络诈骗很多,做跨境电商小心被骗。此号发布内容皆为转载自其它媒体或企业宣传文章,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。---无意冒犯,如有侵权请联系13723417500删除!

服务平台
跨境人脉通
专利检索
U选Market
选品平台
展会&沙龙
群通天下