想要一份国产电视剧的数据集来练手?不如直接爬一个。这次的目标是'全集网',它的电视剧列表页面结构清晰,翻页逻辑也直白——改个页码参数就行。最终我们会拿到剧名、评分和主演信息,输出一个 CSV 文件。整个过程覆盖了爬虫的基本环节:下载、提取和保存,代码也都会贴出来,可以直接跑。

打开全集网的国产电视剧分类,可以看到页面上已经显示了剧名、评分和主演,这正是我们需要的数据。地址栏的 URL 有个特点:第一页是 vodshow/13--------1---.html,点第二页后,URL 中间的 1 变成了 2。很明显,只要循环改变这个数字,就能访问所有页面。底部也是传统的翻页,没搞什么异步加载,这使得我们的爬虫不用去模拟 XHR,直接用 urllib3 请求即可。



下载网页
先写两个基础函数:一个下载网页,一个保存到文件。这里沿用之前用过的 urllib3,不引入新依赖。
import urllib3
def download_content(url):
http = urllib3.PoolManager()
response = http.request("GET", url)
response_data = response.data
html_content = response_data.decode()
return html_content
def save_to_file(filename, content):
fo = open(filename, "w", encoding="utf-8")
fo.write(content)
fo.close()
单个页面测试一下,下载第一页并保存为 tv1.html:
url = "https://www.fschurun.com/vodshow/13--------1---.html"
html_content = download_content(url)
save_to_file("tvs_html/tv1.html", html_content)
打开保存的 HTML 文件,能看到诸如《藏药令》这样的电视剧信息,说明内容不是动态注入的,urllib3 下载没毛病。

接下来把 137 个页面都下载下来。在循环里每次暂停一秒,别太快给人家服务器添麻烦。文件名按 tv1.html 到 tv136.html 递增(实际有 136 页,我习惯留一页容错,后面提取时处理 1~136)。
import time
for i in range(2, 137):
url = "https://www.fschurun.com/vodshow/13--------" + str(i) + "---.html"
print("begin download:", url)
html = download_content(url)
filename = "tvs_html/tv" + str(i) + ".html"
save_to_file(filename, html)
print("download end")
time.sleep(1)
执行过程中,控制台会每隔一秒打印进度。跑完后,tvs_html 文件夹里就有了一百多个 HTML 文件。


提取数据
现在要从 HTML 里抓出我们需要的信息。用 BeautifulSoup 解析比较省事。先写个函数从文件创建 BeautifulSoup 对象。
from bs4 import BeautifulSoup
def create_doc_from_file(filename):
fo = open(filename, "r", encoding="utf-8")
html_content = fo.read()
fo.close()
doc = BeautifulSoup(html_content, "html.parser")
return doc
观察页面结构:每个电视剧是一个 li,外层是一个 div,class 为 ewave-vodlist__box。评分放在 class="ewave-vodlist__thumb lazyload" 的 div 里的 span 下;剧名是 class="ewave-vodlist__detail" 下的 h4;主演是同一个 detail div 里的 p。

第一次尝试直接提取文本,结果带了一堆换行和多余空格。

写个正则清理一下:
import re
def remove_extra_spaces(string):
string = re.sub(' +', ' ', string)
string = string.strip().replace("\n", " ")
return string
下面函数从一个 HTML 文件解析出所有电视剧的信息,返回字典列表。注意评分那个 span 有两个 class,我们用 find 定位。
def get_tv_from_html(html_file_name):
doc = create_doc_from_file(html_file_name)
box_list = doc.find_all("div", class_="ewave-vodlist__box")
tv_list = []
for box in box_list:
rating = box.find("div", class_="ewave-vodlist__thumb lazyload").find("span", class_="pic-tag pic-tag-h").text
title = box.find("div", class_="ewave-vodlist__detail").find("h4", class_="title text-overflow").text
stars = box.find("div", class_="ewave-vodlist__detail").find("p", class_="text text-overflow text-muted hidden-xs text-actor").text
tv_dict = {}
tv_dict['title'] = title
tv_dict['rating'] = rating
tv_dict['stars'] = remove_extra_spaces(stars)
tv_list.append(tv_dict)
return tv_list
用 tv1.html 试一下,打印出来干净多了:

再测试一下第二个文件,确认函数没问题:
tv_list = get_tv_from_html("tvs_html/tv2.html")
print(tv_list)

生成的字典列表也符合预期:

处理所有页面并保存 CSV
现在遍历所有本地文件,把结果汇总到一个大列表。
all_tv_dict = []
for i in range(1, 136): # 注意我们下载了 tv1~tv136
filename = "tvs_html/tv" + str(i) + ".html"
dict_list = get_tv_from_html(filename)
all_tv_dict = all_tv_dict + dict_list
print(len(all_tv_dict))
一共抓到了 9270 条电视剧记录。

最后一步,写入 CSV。表头用 title、rating、stars。
import csv
def write_dict_list_to_file(dict_list, filename, headers):
fo = open(filename, "w", newline="", encoding="utf-8")
writer = csv.DictWriter(fo, headers)
writer.writeheader()
writer.writerows(dict_list)
fo.close()
write_dict_list_to_file(all_tv_dict, "tv_rating.csv", ["title", "rating", "stars"])
代码运行完,当前目录就生成了 tv_rating.csv。

用 Excel 打开看看,9270 行数据整整齐齐。

这样,一份国产电视剧评分数据集就搞定了。从选目标、下载多页、提取清洗到保存 CSV,全流程跑通。如果你有自己的目标网站,调整选择器和翻页逻辑就行,剩下的代码基本可以复用。

