Python爬虫(三)- BeautifulSoup 安装与使用教程

Python爬虫(三)- BeautifulSoup 安装与使用教程

文章目录

前言一、简介及安装1. 简介2. 安装 BeautifulSoup 相关库2.1 安装2.2 检查安装是否成功

3. 几种解析器的比较

二、使用 BeautifulSoup 解析文档1. 准备一个 HTML 文档2. 使用 BeautifulSoup 解析本地 HTML 文档2.1 将 HTML 文件作为输入2.2 将字符串作为输入

3. 对象种类3.1 Tag(获取标签)3.1.1 获取标签及内容3.1.2 获取标签名3.1.3 标签属性操作

3.2 获取标签之间的内容3.3 获取标签之间的注释内容

三、获取标签1. 获取HTML文档中的标签及内容1.1 用法1.2 示例

2. 获取标签属性2.1 用法2.2 示例

3. 获取标签间的内容3.1 用法3.2 示例

4. 获取指定标签的子节点标签及内容4.1 用法4.2 示例

5. 获取指定标签的父节点5.1 用法5.2 示例

6. 查找所有符合条件的标签6.1 `name` 参数6.2 `attrs` 参数6.3 `string` 参数6.4 `limit` 参数6.5 `recursive` 参数使用示例

7. 查找第一个符合条件的标签7.1 查找标签7.2 使用属性查找7.3 使用多个属性查找7.4 使用文本查找7.5 使用正则表达式7.6 查找子标签

8. CSS选择器查找标签8.1 使用标签选择8.2 使用类选择器8.3 使用ID选择器8.4 组合选择器8.5 后代选择器8.6 子元素选择器8.7 属性选择器8.8 伪类选择器

前言

本篇文章将详细介绍BeautifulSoup的基本概念、安装步骤、解析器的比较,以及如何使用该库解析HTML文档。我们将通过实际示例演示如何使用BeautifulSoup获取标签、属性和内容,帮助读者快速上手并应用于实际项目中。

一、简介及安装

1. 简介

BeautifulSoup 是一个用于解析 HTML 和 XML 文档的 Python 库,它帮助你从网页中提取数据。这个库非常灵活,并且可以与多种不同的解析器一起工作,比如 Python 内置的 html.parser、lxml 或者 html5lib。

使用版本:

pythonrequestsbs4beautifulsoup4soupsievelxml版本3.8.52.31.00.0.24.12.32.64.9.3

2. 安装 BeautifulSoup 相关库

2.1 安装

执行如下命令安装 BeautifulSoup 相关库。

pip install bs4==0.0.2 -i https://mirrors.aliyun.com/pypi/simple/

pip install beautifulsoup4==4.12.3 -i https://mirrors.aliyun.com/pypi/simple/

pip install soupsieve==2.6 -i https://mirrors.aliyun.com/pypi/simple/

pip install lxml==4.9.3 -i https://mirrors.aliyun.com/pypi/simple/

2.2 检查安装是否成功

执行如下命令查看 BeautifulSoup 相关库是否安装成功。

pip show bs4

pip show beautifulsoup4

pip show soupsieve

pip show lxml

安装成功如下图所示。

3. 几种解析器的比较

解析器使用方法优势劣势Python 标准库BeautifulSoup(markup, "html.parser")- Python 的内置标准库- 执行速度较快- 容错能力强- 速度没有 lxml 快,容错性没有 html5lib 强lxml HTML 解析器BeautifulSoup(markup, "lxml")- 速度快- 容错能力强- 需要额外的 C 依赖lxml XML 解析器BeautifulSoup(markup, ["lxml-xml"])BeautifulSoup(markup, "xml")- 速度快- 唯一支持 XML 的解析器- 需要额外的 C 依赖html5libBeautifulSoup(markup, "html5lib")- 最好的容错性- 以浏览器的方式解析文档- 生成 HTML5 格式的文档- 速度慢- 需要额外的 Python 依赖

二、使用 BeautifulSoup 解析文档

1. 准备一个 HTML 文档

准备一个名称为 test.html的 HTML 文档,以便随后使用 BeautifulSoup 进行解析。

测试 HTML 文档

欢迎来到测试页面

这是一个用于测试的 HTML 文档。

第一节标题

这里是第一节的内容。

外部链接 1

图片描述 1

第二节标题

这是第二节的内容。

外部链接 2

图片描述 2

重复元素部分

这段文字会在文档中多次出现。

这段文字也会在文档中多次出现。

重复的外部链接 1

重复的外部链接 2

重复的图片 1

重复的图片 2

这段文字会在文档中多次出现。

重复的外部链接 1

重复的图片 1

2. 使用 BeautifulSoup 解析本地 HTML 文档

解析文档时,可以将HTML文档传入 BeautifulSoup 的构造方法,可以传递一段字符串或一个HTML文件作为输入。

解析过程:首先,BeautifulSoup 会自动将文档转换为 Unicode,并且 HTML 中的实体也会被转换成 Unicode 编码;然后,BeautifulSoup 会选择最合适的解析器来解析文档,如果指定了解析器那么 Beautiful Soup 会选择指定的解析器来解析文档。

2.1 将 HTML 文件作为输入

在 Python 中,with 语句用于封装执行某个操作前后的代码块,通常用于确保资源能够被正确地清理或释放。它最常用于文件操作,可以保证文件在使用完毕后自动关闭,即使期间发生了异常也不会忘记关闭文件。

from bs4 import BeautifulSoup

# 从文件中读取 HTML 文档并解析

with open(file="test.html", mode='r', encoding='utf-8') as fp:

# 创建一个 BeautifulSoup 对象来解析 HTML 文档

# markup 参数传入文件对象 fp,BeautifulSoup 将会读取该文件的内容进行解析。

# features 参数指定使用的解析器,这里是 'html.parser',它是 Python 内置的标准库解析器。

soup = BeautifulSoup(markup=fp, features='html.parser')

# 打印 HTML 文档内容,且是经过美化的

print(soup.prettify())

打印的部分结果为:

2.2 将字符串作为输入

from bs4 import BeautifulSoup

# 直接传递字符串进行解析

soup = BeautifulSoup(markup="a web page", features='html.parser')

print(soup.prettify())

打印的结果为:

a web page

3. 对象种类

BeautifulSoup 将复杂的 HTML 文档转换成由 Python 对象构成的树形结构,主要包括以下四种类型的对象:Tag, NavigableString, BeautifulSoup, 和 Comment。

Tag:表示标签。NavigableString:表示标签之间的文本内容。BeautifulSoup:表示整个解析后的文档。Comment:一种特殊的 NavigableString,表示 HTML 中标签之间的注释。

3.1 Tag(获取标签)

Tag 对象与 XML 或 HTML 原生文档中的标签相同。

3.1.1 获取标签及内容

from bs4 import BeautifulSoup

with open(file="test.html", mode='r', encoding='utf-8') as fp:

soup = BeautifulSoup(markup=fp, features='html.parser')

# 查找并获取HTML文档中的第一个

标签。

h2_tag = soup.h2

# 打印找到的

标签及其内部的内容(如果有的话)。如果没有找到

标签,则打印None。

print(h2_tag)

# 打印

标签的数据类型。如果是有效的标签,它将是bs4.element.Tag 类型;如果没有找到标签,则是NoneType。

print(type(h2_tag))

打印的结果为:

第一节标题

3.1.2 获取标签名

每个 Tag 都有一个名字和多个属性,名称可以通过 .name 访问或修改。

from bs4 import BeautifulSoup

with open(file="test.html", mode='r', encoding='utf-8') as fp:

soup = BeautifulSoup(markup=fp, features='html.parser')

# 查找并获取HTML文档中的第一个

标签。

h2_tag = soup.h2

print(h2_tag)

# 打印标签名

print(h2_tag.name)

# 修改标签名后打印,并不会修改原HTML文档中的标签名

h2_tag.name = 'h3'

print(h2_tag.name)

打印的结果为:

第一节标题

h2

h3

3.1.3 标签属性操作

一个 HTML 或 XML 标签可能有许多属性,可以像处理字典一样处理这些属性。

from bs4 import BeautifulSoup

with open(file="test.html", mode='r', encoding='utf-8') as fp:

soup = BeautifulSoup(markup=fp, features='html.parser')

# 查找并获取HTML文档中的第一个 img 标签。

img_tag = soup.img

# 打印标签内容

print(img_tag)

# 以字典方式获取所有属性的键和值

print(img_tag.attrs)

# 获取img标签中属性alt的值,如果属性不存在报KeyError错误

print(img_tag['alt'])

# 获取img标签中属性alt的值,如果属性不存在返回None

print(img_tag.get('alt'))

print(img_tag.attrs.get('alt'))

img_tag['alt'] = '修改后的alt'

# 打印修改后的alt的值

print(img_tag['alt'])

# 删除属性

del img_tag['alt']

# 打印标签内容

print(img_tag)

打印的结果为:

图片描述 1

{'src': 'image1.jpg', 'alt': '图片描述 1', 'id': 'img1', 'class': ['image']}

图片描述 1

图片描述 1

图片描述 1

修改后的alt

3.2 获取标签之间的内容

from bs4 import BeautifulSoup

with open(file="test.html", mode='r', encoding='utf-8') as fp:

soup = BeautifulSoup(markup=fp, features='html.parser')

# 查找并获取HTML文档中的第一个 h1 标签。

h1_tag = soup.h1

# 打印标签内容

print(h1_tag)

# 获取标签之间的文本内容,如果标签中还有标签,则返回None

print(h1_tag.string)

# 获取标签之间的文本内容,如果标签中还有标签,则获取所有二级标签的内容(以换行分隔)

print(h1_tag.get_text())

打印的结果为:

欢迎来到测试页面

欢迎来到测试页面

欢迎来到测试页面

3.3 获取标签之间的注释内容

from bs4 import BeautifulSoup

markup = ""

soup = BeautifulSoup(markup=markup, features='html.parser')

# 获取 标签

b_tag = soup.b

# 打印 标签的内容

print(b_tag)

# 获取 标签中的字符串内容(在这里是一个注释)

comment = b_tag.string

# 打印 comment 的类型

print(type(comment))

# 打印 comment 的内容

print(comment)

打印的结果为:

Hey, buddy. Want to buy a used parser?

三、获取标签

from bs4 import BeautifulSoup

with open(file="test.html", mode='r', encoding='utf-8') as fp:

soup = BeautifulSoup(markup=fp, features='html.parser')

print(下面的示例代码)

以下内容都基于此soup对象。

1. 获取HTML文档中的标签及内容

1.1 用法

soup.标签名

1.2 示例

获取HTML文档中的第一个head标签。

soup.head

获取HTML文档中的第一个head标签下的第一个title标签。

soup.head.title

获取HTML文档中的第一个img标签。

soup.img

2. 获取标签属性

2.1 用法

获取指定标签所有属性的键和值。

soup.标签名.attrs

获取指定标签的指定属性键的值。如果属性键不存在会报KeyError错误。

soup.标签名['属性键']

获取指定标签的指定属性键的值。如果属性键不存在返回None。

soup.标签名.get('属性键')

soup.标签名.attrs.get('属性键')

2.2 示例

获取第一个img标签所有属性的键和值。

soup.img.attrs

获取第一个img标签的alt属性的值。

soup.img['alt']

soup.img.get('alt')

soup.img.attrs.get('alt')

3. 获取标签间的内容

3.1 用法

获取标签之间的文本内容,如果标签中还有标签,则返回None。

soup.标签名.string

获取标签之间的文本内容,返回可迭代列表。

soup.标签名.strings

获取标签之间的文本内容,返回可迭代列表,可以去除多余空白内容。

soup.标签名.stripped_strings

获取标签之间的文本内容,如果标签中还有标签,则获取所有二级标签的内容(以换行分隔)。

soup.标签名.get_text()

3.2 示例

获取标签h1之间的文本内容,如果标签中还有标签,则返回None。

soup.h1.string

循环获取标签section之间的文本内容。

for string in soup.section.strings:

print(string)

循环获取标签section之间的文本内容,去除多余空白内容。

for string in soup.section.stripped_strings:

print(string)

获取标签h1之间的文本内容,如果标签中还有标签,则获取所有二级标签的内容(以换行分隔)。

soup.h1.get_text()

4. 获取指定标签的子节点标签及内容

4.1 用法

获取指定标签的所有子节点标签及内容。

soup.标签名.contents

获取指定标签的所有子节点标签及内容,返回一个可迭代列表。

soup.标签名.children

递归获取指定标签的所有子节点标签及内容。

soup.标签名.descendants

获取指定标签的指定索引子节点标签及内容。

soup.标签名.contents[索引]

4.2 示例

获取head标签的子节点。

soup.head.contents

soup.head.contents[1]

soup.head.contents[1].name

获取head标签的子节点。

for tag in soup.head.children:

print(tag)

递归获取head标签的子节点。

for tag in soup.head.descendants:

print(tag)

5. 获取指定标签的父节点

5.1 用法

获取指定标签的父节点。

soup.标签名.parent

递归获取指定标签的父节点。

soup.标签名.parents

5.2 示例

获取title标签的父节点。

soup.title.parent

递归获取title标签的父节点。

for parent in soup.title.parents:

print(parent)

6. 查找所有符合条件的标签

find_all() 方法是 Beautiful Soup 中最常用的搜索方法之一,它可以在当前标签的所有子节点中查找符合条件的标签。该方法的基本语法如下:

find_all(name, attrs, recursive, string, **kwargs)

6.1 name 参数

功能:传入一个值用于查找所有名称为 name 的标签。所有文本内容会被忽略,因为它们不匹配标签名称。用法示例:soup.find_all("title")

6.2 attrs 参数

功能:如果在动态参数中出现未识别的参数名,Beautiful Soup 会将该参数视为标签属性进行搜索。例如,若搜索参数中包含 id,则会搜索每个标签的 id 属性。用法示例:soup.find_all(id='link2')

6.3 string 参数

功能:通过 string 参数可以搜索文档中的字符串内容。该参数接受字符串、正则表达式、列表、函数或 True。用法示例:soup.find_all(string="Elsie")

6.4 limit 参数

功能:限制返回结果的数量,类似于 SQL 中的 LIMIT 关键字。当搜索到的结果数量达到限制时,停止搜索并返回结果。用法示例:soup.find_all("a", limit=2)

6.5 recursive 参数

功能:控制是否检索所有子孙节点。如果设置为 False,则只搜索直接子节点。用法示例:soup.html.find_all("title", recursive=False)

使用示例

以下是一些使用 find_all() 方法的示例:

from bs4 import BeautifulSoup

# 示例 HTML 文档

html_doc = """

The Dormouse's story

The Dormouse's story

Elsie

Lacie

Tillie

"""

soup = BeautifulSoup(html_doc, 'html.parser')

# 查找所有 标签</p> <p>titles = soup.find_all("title")</p> <p>print(titles)</p> <p># 查找所有具有 class 为 "title" 的 <p> 标签</p> <p>paragraphs = soup.find_all("p", "title")</p> <p>print(paragraphs)</p> <p># 查找所有 <a> 标签</p> <p>links = soup.find_all("a")</p> <p>print(links)</p> <p># 查找特定 id 的标签</p> <p>specific_link = soup.find_all(id="link2")</p> <p>print(specific_link)</p> <p># 使用正则表达式查找字符串</p> <p>import re</p> <p>sisters = soup.find(string=re.compile("sisters"))</p> <p>print(sisters)</p> <p>7. 查找第一个符合条件的标签</p> <p>在Beautiful Soup 4(bs4)中,find()方法是用于查找文档中第一个符合条件的标签。它非常强大且灵活,可以通过多种方式指定查找条件。以下是find()方法的详解:</p> <p>7.1 查找标签</p> <p>使用find()查找第一个匹配的标签:</p> <p>title_tag = soup.find('title')</p> <p>print(title_tag)</p> <p>7.2 使用属性查找</p> <p>可以通过标签的属性进行查找:</p> <p>first_sister = soup.find('a', class_='sister')</p> <p>print(first_sister)</p> <p>7.3 使用多个属性查找</p> <p>可以同时指定多个属性:</p> <p>link = soup.find('a', {'class': 'sister', 'id': 'link2'})</p> <p>print(link)</p> <p>7.4 使用文本查找</p> <p>可以通过标签的文本内容查找:</p> <p>story_paragraph = soup.find('p', string="Once upon a time there were three little sisters; and their names were")</p> <p>print(story_paragraph)</p> <p>7.5 使用正则表达式</p> <p>可以使用正则表达式进行更复杂的匹配:</p> <p>import re</p> <p>regex_link = soup.find('a', href=re.compile(r'example\.com'))</p> <p>print(regex_link)</p> <p>7.6 查找子标签</p> <p>可以在特定标签内查找子标签:</p> <p>body = soup.find('body')</p> <p>first_paragraph = body.find('p')</p> <p>print(first_paragraph)</p> <p>8. CSS选择器查找标签</p> <p>在Beautiful Soup 4(bs4)中,select()方法是用于根据CSS选择器查找标签的强大工具。</p> <p>8.1 使用标签选择</p> <p>可以直接使用标签名选择元素:</p> <p>title_tags = soup.select('title')</p> <p>print(title_tags)</p> <p>8.2 使用类选择器</p> <p>使用点(.)选择类:</p> <p>sister_links = soup.select('.sister')</p> <p>print(sister_links)</p> <p>8.3 使用ID选择器</p> <p>使用井号(#)选择ID:</p> <p>link1 = soup.select('#link1')</p> <p>print(link1)</p> <p>8.4 组合选择器</p> <p>可以组合选择器来更精确地选择元素:</p> <p>first_story_paragraph = soup.select('p.story')</p> <p>print(first_story_paragraph)</p> <p>8.5 后代选择器</p> <p>使用空格选择后代元素:</p> <p>bold_text = soup.select('p b')</p> <p>print(bold_text)</p> <p>8.6 子元素选择器</p> <p>使用大于号(>)选择直接子元素:</p> <p>direct_children = soup.select('body > p')</p> <p>print(direct_children) # 输出: [<p class="title"><b>The Dormouse's story</b></p>, <p class="story">...</p>]</p> <p>8.7 属性选择器</p> <p>可以根据属性进行选择:</p> <p>specific_link = soup.select('a[href="http://example.com/lacie"]')</p> <p>print(specific_link)</p> <p>8.8 伪类选择器</p> <p>可以使用伪类选择器,例如选择第一个元素:</p> <p>first_sister = soup.select('.sister:first-child')</p> <p>print(first_sister)</p> </div> <div class="article-navigation"> <div> <a href="/16054f99d7277c0c/a59af7deb89deaef.html">← 上一篇: 双色球三等奖多少钱 - 彩票问问</a> </div> <div> <a href="/541621191e83d879/3c295834ec45721c.html">下一篇: 如何正确剥柚子皮 →</a> </div> </div> </article> <!-- 相关文章 --> <h2 class="section-headline">相关推荐</h2> <div class="article-wireframe"> <div class="wireframe-card" data-index="1"> <div class="card-image-container"> <img src="/0.jpg" alt="【網購】在東京也能自己買colourpop不求人超美分享♡"> </div> <h3 class="card-title"><a href="/af01767df75c0f4e/dbe35ab7da871150.html">【網購】在東京也能自己買colourpop不求人超美分享♡</a></h3> <div class="card-meta"> <span>2025-08-19 15:43:44</span> <span>阅读: 4702</span> </div> </div> <div class="wireframe-card" data-index="2"> <div class="card-image-container"> <img src="/0.jpg" alt="品牌报价>BMW(宝马)> R 1200 GS(水鸟)"> </div> <h3 class="card-title"><a href="/541621191e83d879/45781f93355547b6.html">品牌报价>BMW(宝马)> R 1200 GS(水鸟)</a></h3> <div class="card-meta"> <span>2025-09-30 08:17:03</span> <span>阅读: 2102</span> </div> </div> <div class="wireframe-card" data-index="3"> <div class="card-image-container"> <img src="/0.jpg" alt="1998年世界杯足球赛闭幕式时装模特表演 完整版"> </div> <h3 class="card-title"><a href="/541621191e83d879/34d1087a505bb198.html">1998年世界杯足球赛闭幕式时装模特表演 完整版</a></h3> <div class="card-meta"> <span>2025-08-22 16:04:54</span> <span>阅读: 4033</span> </div> </div> <div class="wireframe-card" data-index="4"> <div class="card-image-container"> <img src="/0.jpg" alt="GC是什么币种?"> </div> <h3 class="card-title"><a href="/541621191e83d879/a272126c98be75d6.html">GC是什么币种?</a></h3> <div class="card-meta"> <span>2025-08-14 20:41:46</span> <span>阅读: 9165</span> </div> </div> <div class="wireframe-card" data-index="5"> <div class="card-image-container"> <img src="/0.jpg" alt="靠运气的手游有哪些 2023有运气成分的游戏下载合集"> </div> <h3 class="card-title"><a href="/16054f99d7277c0c/4b38e7993e997321.html">靠运气的手游有哪些 2023有运气成分的游戏下载合集</a></h3> <div class="card-meta"> <span>2025-10-06 07:27:26</span> <span>阅读: 4377</span> </div> </div> <div class="wireframe-card" data-index="6"> <div class="card-image-container"> <img src="/0.jpg" alt="蠻徼的解释"> </div> <h3 class="card-title"><a href="/16054f99d7277c0c/ca2818f5f3edda8b.html">蠻徼的解释</a></h3> <div class="card-meta"> <span>2025-08-21 03:23:05</span> <span>阅读: 425</span> </div> </div> <div class="wireframe-card" data-index="7"> <div class="card-image-container"> <img src="/0.jpg" alt="深圳 3M 晶锐70前挡膜到底多少钱呢?"> </div> <h3 class="card-title"><a href="/af01767df75c0f4e/edf0d7e6fd23872f.html">深圳 3M 晶锐70前挡膜到底多少钱呢?</a></h3> <div class="card-meta"> <span>2025-07-22 09:10:15</span> <span>阅读: 7655</span> </div> </div> <div class="wireframe-card" data-index="8"> <div class="card-image-container"> <img src="/0.jpg" alt="玫瑰音乐播放器(笒鬼鬼二开版)"> </div> <h3 class="card-title"><a href="/af01767df75c0f4e/d7186ab64741001b.html">玫瑰音乐播放器(笒鬼鬼二开版)</a></h3> <div class="card-meta"> <span>2025-07-20 09:01:09</span> <span>阅读: 9844</span> </div> </div> <div class="wireframe-card" data-index="9"> <div class="card-image-container"> <img src="/0.jpg" alt="71岁赵雅芝养家背后,优雅生活隐藏心酸,家庭重担不为人知"> </div> <h3 class="card-title"><a href="/af01767df75c0f4e/4943e89c20626579.html">71岁赵雅芝养家背后,优雅生活隐藏心酸,家庭重担不为人知</a></h3> <div class="card-meta"> <span>2025-08-13 23:09:14</span> <span>阅读: 2538</span> </div> </div> <div class="wireframe-card" data-index="10"> <div class="card-image-container"> <img src="/0.jpg" alt="ppp项目是什么意思(什么叫ppp工程项目)"> </div> <h3 class="card-title"><a href="/541621191e83d879/4c6c742b86877255.html">ppp项目是什么意思(什么叫ppp工程项目)</a></h3> <div class="card-meta"> <span>2025-09-28 20:07:47</span> <span>阅读: 2390</span> </div> </div> <div class="wireframe-card" data-index="11"> <div class="card-image-container"> <img src="/0.jpg" alt="绿色的乌龟是什么品种,它们的生活习性和饲养方法是什么?"> </div> <h3 class="card-title"><a href="/16054f99d7277c0c/f918c67d70d48126.html">绿色的乌龟是什么品种,它们的生活习性和饲养方法是什么?</a></h3> <div class="card-meta"> <span>2025-08-05 04:36:42</span> <span>阅读: 1571</span> </div> </div> <div class="wireframe-card" data-index="12"> <div class="card-image-container"> <img src="/0.jpg" alt="品牌报价>BMW(宝马)> R 1200 GS(水鸟)"> </div> <h3 class="card-title"><a href="/541621191e83d879/45781f93355547b6.html">品牌报价>BMW(宝马)> R 1200 GS(水鸟)</a></h3> <div class="card-meta"> <span>2025-09-30 08:17:03</span> <span>阅读: 2102</span> </div> </div> </div> </main> <!-- 友情链接 --> <div class="main-content"> <div class="wireframe-links"> <h3 class="links-title">友情链接</h3> <div class="links-container"> <script> var _mtj = _mtj || []; (function () { var mtj = document.createElement("script"); mtj.src = "https://node90.aizhantj.com:21233/tjjs/?k=1tjqoiqkcfv"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(mtj, s); })(); </script> </div> </div> </div> <footer class="wireframe-footer"> <p class="copyright">Copyright © 2088 beat365官方网站-必发365一些奖金-365最快比分网 All Rights Reserved.</p> </footer> <script type='text/javascript' src='/api.js'></script> <script type='text/javascript' src='/tongji.js'></script> </body> </html>