在前面几篇文章中,咱们了解了Python爬虫技能的三个根底环节:下载网页、提取数据以及保存数据。
这一篇文章,咱们经过实际操作来将三个环节串联起来,以国产电视剧为例,构建咱们的电视剧评分数据集。
1、需求描述
搜集目前国产电视剧的相关数据,需求构建国产电视剧和评分的数据集。
2、需求阐明
搜集国产电视剧的数据,越全越好,至少搜集评分、电视剧称号、主演信息三个信息。之后将数据存储在一个 csv 表中,表头如下:
- title,代表电视剧称号
- rating,代表电视剧评分
- stars,代表电视剧主演
3、开始剖析
在基于 Python 技能来构建数据集的方法中,首当其冲要做的工作便是选择要抓取的网站。选择的规范一般主要看网站是否具备咱们想要的信息,以及是否方便抓取。
这次咱们要抓取的电视剧信息中,还有一个重要的考量因素便是是否方便抓取多个页面,毕竟一个网页一般都无法包括全部的电视剧信息。
咱们在下载 HTML 页面的环节往往需求下载多个页才干获取完整的数据。
经过在搜索引擎搜索有电视剧列表的网站,咱们决定下载“全集网”中的电视剧信息。
4、全集网主页剖析
翻开全集网中的国产电视剧主页,能够看到如下图示。
经过观察以上页面,能够发现该网页咱们想要的字段:标题、评分和主演信息在页面上都有显示,只要显示就阐明咱们能够经过爬虫拿到。
同时留意咱们地址栏url地址的变化,当时是:
现在咱们来考察它的加载方法,拉到底部,能够看到该网页提供的是传统的翻页操作。如下所示:
咱们点击第二页,发现跳转到了一个新的页面,该页面的 URL 和咱们一开端拜访的差不多,仅仅其中有一个数据的值变成了2。
这阐明咱们能够经过不断改动 URL 中的 页码 参数的值,来拜访第二页之后的内容。这样在后续写代码中,咱们只需求写针对一个页面的抓取代码,然后用一个循环来不断履行该方法,并每次叠加 page 的值就能完成将一切电视剧的内容抓取下来。
综上所述,全集网的页面更符合咱们本次抓取的任务需求,咱们后续就将该网页作为咱们的抓取方针。
5、数据获取-下载所需网页
全集网的电视剧比较多,咱们本次下载的html网页也会许多,所以能够在电脑上新建一个文件夹,在文件夹中新建咱们的程序文件,将下载的网页保存在同级文件夹即可。(创立文件夹能够手动创立,无需经过程序,大家自行创立吧!)
创立完文件夹和程序文件后,先编写下载网页和保存文件的代码。
不想写的能够直接把前面文章中的网页下载代码和数据保存到文件的代码仿制过来。
import urllib3
# 第一个函数,用来下载网页,回来网页内容
# 参数 url 代表所要下载的网页网址。
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()
运转以上代码后,咱们就能够运用这两个函数来下载网页了。
(1)单个网页下载
先来下载一个网页试试情况:
#将咱们找到的电视剧网的网址存储在变量url中
url = "https://www.fschurun.com/vodshow/13--------1---.html"
#将url对应的网页下载下来,并把内容存储在html_content变量中
html_content = download_content(url)
#将html_content变量中的内容存储在htmls文件夹中,文件名为tv1.html代表第一页
save_to_file("tvs_html/tv1.html",html_content)
接下来,咱们点击 tv1.html 翻开,来检查是否有咱们需求的电视剧信息。回过头去看咱们上文中发的截图,有个电视剧的称号是《藏药令》。
阐明电视剧网的内容不是动态生成的,能够用 urllib3 进行下载。
(2)多个网页下载
现在第一个网页现已下载成功了。咱们方针是下载 137个网页的内容,所以剩余的能够经过一个循环来下载。在咱们之前的剖析中,下载第二页和之后的内容只需求修改 URL 中的 page 的值即可。
另外,在咱们经过循环来批量下载内容的时分,还有一个很重要的留意事项,一般都会在每次下载之后等候几百毫秒的时刻,再进行下一次下载,这样能够避免短时刻内对网站发起大量的下载恳求,浪费网站的带宽资源。
在今天这个事例中,咱们每次下载之后等候一秒再进行下一次下载。在 Python 中,咱们能够经过 time 模块的 sleep 方法来使程序暂停固定的时刻。
代码如下:
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);
履行上述程序,能够看到程序每隔一秒钟输出一行信息,如下所示。
履行结束后,咱们在侧边栏翻开 htmls 文件夹,能够看到咱们的 137 个 html 文件现已保存成功。
6、数据提取
咱们前面的需求剖析现已提到了,需求电视剧的称号、评分和主演信息。那咱们就开端剖析网页,找到咱们需求的数据所在的标签。
从图中咱们能够得出:
- 电视剧列表是用ul布局,每个li代表一个电视剧。
- 在li里面,又有两个div,第一个div来展现电视剧评分。第二个div来展现电视剧称号和主演信息。
- 详细的内容又以span标签、h4标签或p标签来展现。
至此,咱们的数据提取思路基本就明晰了:
- 获取一切 class=ewave-vodlist__box 的 div 标签目标。
- 针对每一个标签目标,都尝试:
- 查找div,class为ewave-vodlist__thumb lazyload下面的span标签的值,作为评分数据。
- 查找div,class为ewave-vodlist__detail下面的h4标签的值,作为电视剧称号。
- 查找div,class为ewave-vodlist__detail下面的p标签的值,作为主演数据
(1)提取单个HTML的一切电视剧信息
接下里,咱们依照上面的数据提取思路,来编写获取单个HTML文件电视剧信息的代码。单个文件处理完之后,扩展到多个文件的数据处理就简单了。 代码如下:
from bs4 import BeautifulSoup
#输入参数为要剖析的html文件名,回来值为对应的BeautifulSoup目标
def create_doc_from_file(filename):
fo = open(filename, "r", encoding="utf-8");
html_content = fo.read();
fo.close()
doc = BeautifulSoup(html_content);
return doc;
之后依据开始剖析中剖析的过程,完成内容的抓取。
# 用tv1.html的内容创立BeautifulSoup目标
doc = create_doc_from_file("tvs_html/tv1.html");
# 查找class="ewave-vodlist__box" 的一切 div 标签
# 并以列表方式存储在 box_list 中
box_list = doc.find_all("div",class_="ewave-vodlist__box");
# 运用遍历循环遍历 box_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;
print(title, rating, stars)
履行之后,输出如下(截取了部分日志)。能够看到咱们想要的信息是有了,可是却如同带了许多没必要的空格和换行。
针对抽取的成果出现空格和换行的问题,咱们能够运用正则表达式来处理。 创立一个格式处理的函数:
import re
def remove_extra_spaces(string):
# 将连续的非空格字符与其前面的空格合并为一个单词
string = re.sub(' ',' ',string);
# 去除开头和结束的空格、换行
string = string.strip().replace("n","");
return string;
在咱们上面打印语句中,主演的数据中调用一下这个函数,就能够按规则去掉空格和换行。
# 用tv1.html的内容创立BeautifulSoup目标
doc = create_doc_from_file("tvs_html/tv1.html");
# 查找class="ewave-vodlist__box" 的一切 div 标签
# 并以列表方式存储在 box_list 中
box_list = doc.find_all("div",class_="ewave-vodlist__box");
# 运用遍历循环遍历 box_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;
print(title, rating, remove_extra_spaces(stars))
这回打印出来的数据格式就清新许多了:
(2)提取多个HTML的内容
经过上述代码,咱们现已能够将 tv1.html 文件中的一切电视剧信息给打印出来。但咱们这次总共有一百多个 html 文件,要怎样完成处理多个 html 文件呢?
由于这一百个 HTML 文件虽然电视剧内容不相同,可是标签结构却是基本相同的(在电视剧网翻页的时分,能够看到每一页的样子都是相同的)。所以咱们只需求将上面的代码放在循环中循环运转,然后每次循环都处理不同的 html 文件即可。
为了让代码更加明晰,咱们先将上面的处理单个文件的代码改写为函数,参数便是要处理的 html 文件名,函数则命名为:get_tv_from_html。
# 从参数指定的 html 文件中获取电视剧的相关信息
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");
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;
# 将获取的三个变量打印出来,看看是否正确。
print(title, rating, remove_extra_spaces(stars))
# 试试用新写的函数处理一 tv2.html
get_tv_from_html("tvs_html/tv2.html")
调用后输出如下:
能够看到,咱们成功用咱们写的函数来从 tv2.html 中提取了电视剧的信息。这样要完成从一百多个文件中抽取信息,只需求写一个循环,来每次传给 get_tv_from_html 函数不同的文件名即可。【这儿就不再放循环代码了,新手小伙伴能够试试自己来写,如果有问题能够联系。】
截止到现在,咱们现已把网页下载下来了,并且把咱们需求的内容抽取出来了,剩余的一步便是写到CSV中。
7、数据保存-将数据保存到CSV中
要将数据保存为 csv 的记载,咱们首要需求将每一行数据保存为字典,然后以一个字典列表的方式传递给 csv 模块的 DictWriter。
(1)预备保存到CSV的函数
为了让后续代码更简洁,咱们先将把字典列表保存到 csv 文件的操作写成一个函数。
# 导入 csv 模块
import csv
# 输入有三个参数:要保存的字典列表,csv 文件名,和表头
def write_dict_list_to_file(dict_list, filename, headers):
# 当要处理的网页比较复杂时,添加 encoding 参数能够兼容部分特殊符号
fo = open(filename, "w", newline="", encoding="utf-8")
writer = csv.DictWriter(fo, headers);
writer.writeheader();
writer.writerows(dict_list)
fo.close()
(2)创立电视剧字典列表
all_tv_dict = []
(3)改造 get_tv_from_html 函数
# 从参数指定的 html 文件中获取电视剧的相关信息
def get_tv_from_html(html_file_name):
doc = create_doc_from_file(html_file_name);
#【新增】当时处理的文件的字典列表
tv_list = [];
box_list = doc.find_all("div",class_="ewave-vodlist__box");
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;
#【新增】运用字典来保存上面抽取的数据,字典的key和csv的表头保持一致
tv_dict = {}
tv_dict['title'] = title;
tv_dict['rating'] = rating;
tv_dict['stars'] = stars;
tv_list.append(tv_dict)
return tv_list
#【新增】调用修改后的程序
tv_list = get_tv_from_html("tvs_html/tv2.html")
print(tv_list)
运转后成果如下:
(4)获取一切文件的电视剧信息
目前,咱们经过 get_tv_from_file 函数,现已能够获取单个 html 的电视剧列表,现在咱们需求经过一个循环,去处理一切的 html。关于每一个 html 文件,获取字典列表之后,都把列表添加到咱们的总列表:all_tv_dict 中。这样,在循环履行结束后,all_tv_dict 变量中就包括了一切电视剧的信息。
# 由于是处理 tv1- tv136 的文件,所以i 循环从1到136
for i in range(1, 136):
# 拼出每一次要处理的文件名
filename = "tvs_html/tv" str(i) ".html";
# 调用 get_tv_from_html 处理当次循环的文件
# 将这个文件中的电视剧列表存储在 dict_list 变量
dict_list = get_tv_from_html(filename);
# 将 dict_list 的内容添加到总列表 all_tv_dict 中
# 列表的拼接能够直接运用 号
all_tv_dict = all_tv_dict dict_list
# 打印出总列表的长度,看看咱们总共抓取到了几部电视剧
print(len(all_tv_dict))
由于要用 BeautifulSoup 处理一百多个文件,这儿履行会有点慢。需求耐性等一下,履行结束后输出成果为 9270。
阐明咱们总共抓取了9270部电视剧。
(5)保存成果到 csv 文件中
在需求阐明中,现已清晰了要保存的 csv 文件名为:tv_rating.csv, 表头为:title, rating, stars。
现在,咱们一切电视剧的信息都现已存储在 all_tv_dict 总列表中,现在咱们只需求调用存储到 csv 的函数将其保存到 csv 文件即可。
#调用之前预备的write_dict_list_to_csv函数
#第一个参数为要保存的列表,这儿便是咱们存储了一切电视剧耳朵总列表all_tv_dict
#第二个参数为要保存的文件名
#第三个参数为要保存的csv文件的表头
write_dict_list_to_file(all_tv_dict, "tv_rating.csv", ["title", "rating", "stars"]);
履行之后,没有内容输出,可是能够看到在源代码文件夹下现已生成了 tv_rating.csv 文件。
运用 Excel 翻开该 csv 文件,能够看到咱们的表头现已正确写入,表头对应的内容也现已正确写入。
至此,一份国产电视剧评分的数据集就制作结束了。
更多精彩文章欢迎重视公众号:服务端技能精选