Python大作业:HTML解析之莎士比亚戏剧

为非计算机专业设计

Posted by JTChen on April 12, 2019

为非计算机专业同学设计的题目,为避免过多意外,提供要解析网页的离线版本

任务简述

本任务需利用正则表达式解析给定《The Merchant of Venice》HTML网页文件,并将剧本按markdown格式存储至文件中。

主要考察学生以下几个方面:

  • 程序设计能力及Python编程模式的理解
  • 运算符、表达式、内置对象及序列结构的运用能力
  • Python分支结构、循环结构及函数设计的掌握情况
  • 运用正则表达式处理字符串的能力
  • Python读写文本文件

背景

超级文本标记语言(英文缩写:HTML)是为“网页创建和其它可在网页浏览器中看到的信息”设计的一种标记语言。HTML是一种规范,一种标准,它通过标记符号来标记要显示的网页中的各个部分。网页文件本身是一种文本文件,通过在文本文件中添加标记符,可以告诉浏览器如何显示其中的内容(如:文字如何处理,画面如何安排,图片如何显示等)。一般右键点击网页页面打开菜单,选择查看网页源代码,即可查看网页对应HTML代码。

HTML文本示例

1
2
3
4
5
<p>
Act 1, Scene 1: <a href="./merchant/merchant.1.1.html">Venice. A street.</a><br>
Act 1, Scene 2: <a href="./merchant/merchant.1.2.html">Belmont. A room in PORTIA'S house.</a><br>
Act 1, Scene 3: <a href="./merchant/merchant.1.3.html">Venice. A public place.</a><br>
</p>

对应网页浏览器显示如下


Act 1, Scene 1: Venice. A street.
Act 1, Scene 2: Belmont. A room in PORTIA'S house.
Act 1, Scene 3: Venice. A public place.


HTML 标记标签通常被称为 HTML 标签 (HTML tag)。详细标签含义可查阅HTML 参考手册或其他网络资料。

  • HTML 标签是由尖括号包围的关键词,比如 <html>
  • HTML 标签通常是成对出现的,比如 <p></p>
  • 标签对中的第一个标签是开始标签,第二个标签是结束标签。
  • HTML 标签不区分大小,即<a><A>等同。

任务说明

程序流程

首先,程序询问用户要解析的剧本网页目录文件路径, 用户根据提示输入Merchant of Venice_ List of Scenes.html文件的路径, 之后程序询问剧本输出文件名, 用户根据提示输入The Merchant of Venice.md 程序根据输入的HTML目录文件位置开始解析出各章节所在的文件路径, 然后读取章节所在的HTML文件将《威尼斯商人》剧本文字提取出来, 对提取出的剧本文字进行字符串处理以符合markdown格式。最后根据用户给定的输出文件名,将其存储。 具体格式请参考下面剧本输出格式,同时打印输出在解析的所有文件中出现最多的三个标记及其出现次数。 注:对于成对的标签,如<p> </p>仅记做<p>出现一次

注:代码中请不要出现 ”The Merchant of Venice“等仅《威尼斯商人》剧本中会出现的关键词,评分时程序对莎士比亚其他剧本的兼容性也是考察的一点。

交互示例

1
2
3
4
5
6
7
8
9
10
11
12
请输入需要解析剧本的目录网页路径:
Merchant of Venice_ List of Scenes.html //这里可选择输入相对路径或绝对路径
请输入剧本输出文件名:
The Merchant of Venice.md
正在解析中...
剧本已保存至 The Merchant of Venice.md
解析过程中出现最多的三种标记情况如下
<p>:100次
<a>:40次
<br>20次

附件说明·附件下载链接

附件包含二级结构的《The Merchant of Venice》的网页文件,其一级网页即为目录,文件名为Merchant of Venice_ List of Scenes.html,即需要输入到程序中的文件名,该网页记载了各场景剧本文件的相对路径,可用浏览器打开预览,也可使用记事本方式打开查看源码。附件的merchant文件夹中存放着各场景的剧本网页,这些文件禁止直接输入文件名访问,需从Merchant of Venice_ List of Scenes.html网页中的<a>标记中获取场景剧本网页的路径及文件名。

有兴趣的同学可以尝试直接从原始网站直接爬取。

剧本输出格式

使用markdown格式,本作业说明也是使用markdown格式排版,有兴趣的同学可以深入了解

程序需要从网页文件中提取剧本并存入 The Merchant of Venice.md 文件中。

  1. 剧本名单独一行,且前后各空一行,即被空行包围,并在名称前加一个 # ,并以空格分隔。
  2. 幕号 ACT 单独一行,且前后各空一行,即被空行包裹,作为二级标题,即在名称前加 ## 即可,同样使用空格同文字分隔,仅在每一幕的开头添加。可从 Merchant of Venice_ List of Scenes.html 文件中提取。
  3. 场名 SCENE 单独一行,且前后各空一行,即被空行包裹,作为三级标题,即在名称前加 ### ,同样使用空格同文字分隔。场名可从子级剧本网页文件中提取,通常在 <h3> 标记内,如 <h3>SCENE I. Venice. A street.</H3>
  4. 人物名单独一行,作为 ** 包裹,即 **NAME** 。使用 <a> 标记内,如 <A NAME=speech1><b>ANTONIO</b></a> ,此时 NAME=speech1 代表设置标记的 NAME 属性为 speech1
  5. 台词根据提取文本分行,一个标记内的一段话即为一行,直接输出即可。使用 <a> 标记内,如 <A NAME=1>In sooth, I know not why I am so sad:</A> ,此时 NAME=11 代表设置标记的 NAME 属性为 1 ,代表台词序号。 注:人物名与台词均使用<a>标记,区别在于 NAME 属性设置值不同,详细情况可将剧本幕的网页通过记事本的方式打开查看。
  6. 舞台说明又叫舞台提示,单独一行,且前后各空一行。舞台提示为斜体,使用 <i> 标记,如 <i>Enter ANTONIO, SALARINO, and SALANIO</i>

注:

  • 关于何标记代表何内容的详细情况,请自行打开HTML文件寻找规律。
  • 字符串中\n代表换行。
  • 关于空行包围说明,即除台词进行换行外,其他内容所在行的前后需均为空行,具体可以看下面示例。
输出文件示例

附件 Example for The Merchant of Venice.md 展示了两场 ACT 剧本的输出格式。Example for Markdown to PDF.pdf 是通过 .md 文件生成,这里不作为要求,仅作展示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# The Merchant of Venice

## ACT 1

### SCENE 1: Venice. A street.

*Enter ANTONIO, SALARINO, and SALANIO*

**ANTONIO**

In sooth, I know not why I am so sad:
It wearies me; you say it wearies you;
But how I caught it, found it, or came by it,
What stuff 'tis made of, whereof it is born,
I am to learn;
And such a want-wit sadness makes of me,
That I have much ado to know myself.

*Enter BASSANIO, LORENZO, and GRATIANO*

### SCENE 2: Belmont. A room in PORTIA'S house.

功能函数

根据解析流程,可将程序划分为不同函数。在把函数连接成一个大程序之前,请仔细测试每个函数。

  1. get_list_scene(file_path: str) -> list: 读取路径名称对应的HTML目录文件,并解析出各幕SCENE网页文件的路径,并以 list 类型作为函数返回。
  2. get_scene_script(file_path: str) -> str: 读取路径名称对应的HTML文件,解析出该幕SCENE中的剧本,并将按格式存储的剧本以 str 格式作为函数返回。
  3. write_script(file_name: str, content: str): 传入file_name,并以追加写入的方式打开,并将 str 写入.
  4. get_list_tags(file_path: str) -> set: 读取路径名称对应的HTML文件,并解析出内含的所有标记名,注意不区分大小写,并以 set 类型存储作为函数返回。
  5. get_tagnum(file_path: str, tag_name: str) -> int: 读取路径名称对应的HTML文件,并统计传入值 str 代表的标记数量,并将该值作为返回。

以上仅列出部分功能函数,请同学们根据需要,自行添加更多功能函数。

反馈意见

如果您有任何意见、评论以及建议,请发送邮件至me@jtchen.cn进行反馈,或下方评论。

反馈意见包括但不限于:

  • 打字错误
  • 描述错误
  • 评论
  • 建议