Python 爬虫 – BeautifulSoup
Python 爬虫(Web Scraping)是指通过编写 Python 程序从互联网上自动提取信息的过程。
爬虫的基本流程通常包括发送 HTTP 请求获取网页内容、解析网页并提取数据,然后存储数据。
Python 的丰富生态使其成为开发爬虫的热门语言,特别是由于其强大的库支持。
一般来说,爬虫的流程可以分为以下几个步骤:
- 发送 HTTP 请求:爬虫通过 HTTP 请求从目标网站获取 HTML 页面,常用的库包括
[requests](https://www.runoob.com/python3/python-requests.html)。 - 解析 HTML 内容:获取 HTML 页面后,爬虫需要解析内容并提取数据,常用的库有
BeautifulSoup、lxml、Scrapy等。 - 提取数据:通过定位 HTML 元素(如标签、属性、类名等)来提取所需的数据。
- 存储数据:将提取的数据存储到数据库、CSV 文件、JSON 文件等格式中,以便后续使用或分析。
本章节主要介绍 BeautifulSoup,它是一个用于解析 HTML 和 XML 文档的 Python 库,能够从网页中提取数据,常用于网页抓取和数据挖掘。

BeautifulSoup
BeautifulSoup 是一个用于从网页中提取数据的 Python 库,特别适用于解析 HTML 和 XML 文件。
BeautifulSoup 能够通过提供简单的 API 来提取和操作网页中的内容,非常适合用于网页抓取和数据提取的任务。
安装 BeautifulSoup
要使用 BeautifulSoup,需要安装 beautifulsoup4 和 lxml 或 html.parser(一个 HTML 解析器)。
我们可以使用 pip 来安装这些依赖:
pip install beautifulsoup4
pip install lxml # 推荐使用 lxml 作为解析器(速度更快)
如果你没有 lxml,可以使用 Python 内置的 html.parser 作为解析器。
基本用法
BeautifulSoup 用于解析 HTML 或 XML 数据,并提供了一些方法来导航、搜索和修改解析树。
BeautifulSoup 常见的操作包括查找标签、获取标签属性、提取文本等。
要使用 BeautifulSoup,需要先导入 BeautifulSoup,并将 HTML 页面加载到 BeautifulSoup 对象中。
通常,你会先用爬虫库(如 requests)获取网页内容:
实例
from bs4 import BeautifulSoup
import requests
# 使用 requests 获取网页内容
url = ‘https://cn.bing.com/’ # 抓取bing搜索引擎的网页内容
response = requests.get(url)
# 使用 BeautifulSoup 解析网页
soup = BeautifulSoup(response.text, ‘lxml’) # 使用 lxml 解析器
# 解析网页内容 html.parser 解析器
# soup = BeautifulSoup(response.text, ‘html.parser’)
获取网页标题:
实例
from bs4 import BeautifulSoup
import requests
# 指定你想要获取标题的网站
url = ‘https://cn.bing.com/’ # 抓取bing搜索引擎的网页内容
# 发送HTTP请求获取网页内容
response = requests.get(url)
# 中文乱码问题
response.encoding = ‘utf-8’
# 确保请求成功
if response.status_code == 200:
# 使用BeautifulSoup解析网页内容
soup = BeautifulSoup(response.text, ‘lxml’)
\# 查找<title>标签
title\_tag \= soup.find('title')\# 打印标题文本
if title\_tag: print(title\_tag.get\_text())
else: print("未找到<title>标签")
else:
print(“请求失败,状态码:”, response.status_code)
执行以上代码,输出标题为:
搜索 - Microsoft 必应
中文乱码问题
使用 requests 库抓取中文网页时,可能会遇到编码问题,导致中文内容无法正确显示,为了确保能够正确抓取并显示中文网页,通常需要处理网页的字符编码。
自动检测编码 requests 通常会自动根据响应头中的 Content-Type 来推测网页的编码,但有时可能不准确,此时可以使用 chardet 来自动检测编码。
实例
import requests
url = ‘https://cn.bing.com/’
response = requests.get(url)
# 使用 chardet 自动检测编码
import chardet
encoding = chardet.detect(response.content)[‘encoding’]
print(encoding)
response.encoding = encoding
执行以上代码,输出为:
utf-8
如果你知道网页的编码(例如 utf-8 或 gbk),可以直接设置 response.encoding:
response.encoding = 'utf-8' # 或者 'gbk',根据实际情况选择
查找标签
BeautifulSoup 提供了多种方法来查找网页中的标签,最常用的包括 find() 和 find_all()。
find()返回第一个匹配的标签find_all()返回所有匹配的标签
实例
from bs4 import BeautifulSoup
import requests
# 指定你想要获取标题的网站
url = ‘https://www.baidu.com/’ # 抓取bing搜索引擎的网页内容
# 发送HTTP请求获取网页内容
response = requests.get(url)
# 中文乱码问题
response.encoding = ‘utf-8’
soup = BeautifulSoup(response.text, ‘lxml’)
# 查找第一个 标签
first_link = soup.find(‘a’)
print(first_link)
print(“----------------------------”)
# 获取第一个 标签的 href 属性
first_link_url = first_link.get(‘href’)
print(first_link_url)
print(“----------------------------”)
# 查找所有 标签
all_links = soup.find_all(‘a’)
print(all_links)
输出结果类似如下:
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
----------------------------
http://news.baidu.com
----------------------------
[<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>,
获取标签的文本
通过 get_text() 方法,你可以提取标签中的文本内容:
实例
from bs4 import BeautifulSoup
import requests
# 指定你想要获取标题的网站
url = ‘https://www.baidu.com/’ # 抓取bing搜索引擎的网页内容
# 发送HTTP请求获取网页内容
response = requests.get(url)
# 中文乱码问题
response.encoding = ‘utf-8’
soup = BeautifulSoup(response.text, ‘lxml’)
# 获取第一个
标签中的文本内容
paragraph_text = soup.find(‘p’).get_text()
# 获取页面中所有文本内容
all_text = soup.get_text()
print(all_text)
输出结果类似如下:
百度一下,你就知道
...
查找子标签和父标签
你可以通过 parent 和 children 属性访问标签的父标签和子标签:
# 获取当前标签的父标签
parent_tag = first_link.parent# 获取当前标签的所有子标签
children = first_link.children
实例
from bs4 import BeautifulSoup
import requests
# 指定你想要获取标题的网站
url = ‘https://www.baidu.com/’ # 抓取bing搜索引擎的网页内容
# 发送HTTP请求获取网页内容
response = requests.get(url)
# 中文乱码问题
response.encoding = ‘utf-8’
soup = BeautifulSoup(response.text, ‘lxml’)
# 查找第一个 标签
first_link = soup.find(‘a’)
print(first_link)
print(“----------------------------”)
# 获取当前标签的父标签
parent_tag = first_link.parent
print(parent_tag.get_text())
输出结果类似如下:
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
----------------------------新闻 hao123 地图 视频 贴吧 登录 更多产品
查找具有特定属性的标签
你可以通过传递属性来查找具有特定属性的标签。
例如,查找类名为 example-class 的所有 div 标签:
# 查找所有 class="example-class" 的 <div> 标签
divs_with_class = soup.find_all('div', class_='example-class')# 查找具有 id="unique-id" 的 <p> 标签
unique_paragraph = soup.find('p', id='unique-id')
获取搜索按钮,id 为 su :

实例
from bs4 import BeautifulSoup
import requests
# 指定你想要获取标题的网站
url = ‘https://www.baidu.com/’ # 抓取bing搜索引擎的网页内容
# 发送HTTP请求获取网页内容
response = requests.get(url)
# 中文乱码问题
response.encoding = ‘utf-8’
soup = BeautifulSoup(response.text, ‘lxml’)
# 查找具有 id=“unique-id” 的 标签
unique_input = soup.find(‘input’, id=‘su’)
input_value = unique_input[‘value’] # 获取 input 输入框的值
print(input_value)
输出结果为:
百度一下
高级用法
CSS 选择器
BeautifulSoup 也支持通过 CSS 选择器来查找标签。
select() 方法允许使用类似 jQuery 的选择器语法来查找标签:
# 使用 CSS 选择器查找所有 class 为 'example' 的 <div> 标签
example_divs = soup.select('div.example')# 查找所有 <a> 标签中的 href 属性
links = soup.select('a[href]')
处理嵌套标签
BeautifulSoup 支持深度嵌套的 HTML 结构,你可以通过递归查找子标签来处理这些结构:
# 查找嵌套的 <div> 标签
nested_divs = soup.find_all('div', class_='nested')
for div in nested_divs:print(div.get_text())
修改网页内容
BeautifulSoup 允许你修改 HTML 内容。
我们可以修改标签的属性、文本或删除标签:
实例
# 修改第一个 标签的 href 属性
first_link[‘href’] = ‘http://new-url.com’
# 修改第一个
标签的文本内容
first_paragraph = soup.find(‘p’)
first_paragraph.string = ‘Updated content’
# 删除某个标签
first_paragraph.decompose()
转换为字符串
你可以将解析的 BeautifulSoup 对象转换回 HTML 字符串:
# 转换为字符串
html_str = str(soup)
BeautifulSoup 属性与方法
以下是 BeautifulSoup 中常用的属性和方法:
| 方法/属性 | 描述 | 示例 |
|---|---|---|
BeautifulSoup() | 用于解析 HTML 或 XML 文档并返回一个 BeautifulSoup 对象。 | soup = BeautifulSoup(html_doc, 'html.parser') |
.prettify() | 格式化并美化文档内容,生成结构化的字符串。 | print(soup.prettify()) |
.find() | 查找第一个匹配的标签。 | tag = soup.find('a') |
.find_all() | 查找所有匹配的标签,返回一个列表。 | tags = soup.find_all('a') |
.find_all_next() | 查找当前标签后所有符合条件的标签。 | tags = soup.find('div').find_all_next('p') |
.find_all_previous() | 查找当前标签前所有符合条件的标签。 | tags = soup.find('div').find_all_previous('p') |
.find_parent() | 返回当前标签的父标签。 | parent = tag.find_parent() |
.find_all_parents() | 查找当前标签的所有父标签。 | parents = tag.find_all_parents() |
.find_next_sibling() | 查找当前标签的下一个兄弟标签。 | next_sibling = tag.find_next_sibling() |
.find_previous_sibling() | 查找当前标签的前一个兄弟标签。 | prev_sibling = tag.find_previous_sibling() |
.parent | 获取当前标签的父标签。 | parent = tag.parent |
.next_sibling | 获取当前标签的下一个兄弟标签。 | next_sibling = tag.next_sibling |
.previous_sibling | 获取当前标签的前一个兄弟标签。 | prev_sibling = tag.previous_sibling |
.get_text() | 提取标签内的文本内容,忽略所有HTML标签。 | text = tag.get_text() |
.attrs | 返回标签的所有属性,以字典形式表示。 | href = tag.attrs['href'] |
.string | 获取标签内的字符串内容。 | string_content = tag.string |
.name | 返回标签的名称。 | tag_name = tag.name |
.contents | 返回标签的所有子元素,以列表形式返回。 | children = tag.contents |
.descendants | 返回标签的所有后代元素,生成器形式。 | for child in tag.descendants: print(child) |
.parent | 获取当前标签的父标签。 | parent = tag.parent |
.previous_element | 获取当前标签的前一个元素(不包括文本)。 | prev_elem = tag.previous_element |
.next_element | 获取当前标签的下一个元素(不包括文本)。 | next_elem = tag.next_element |
.decompose() | 从树中删除当前标签及其内容。 | tag.decompose() |
.unwrap() | 移除标签本身,只保留其子内容。 | tag.unwrap() |
.insert() | 向标签内插入新标签或文本。 | tag.insert(0, new_tag) |
.insert_before() | 在当前标签前插入新标签。 | tag.insert_before(new_tag) |
.insert_after() | 在当前标签后插入新标签。 | tag.insert_after(new_tag) |
.extract() | 删除标签并返回该标签。 | extracted_tag = tag.extract() |
.replace_with() | 替换当前标签及其内容。 | tag.replace_with(new_tag) |
.has_attr() | 检查标签是否有指定的属性。 | if tag.has_attr('href'): |
.get() | 获取指定属性的值。 | href = tag.get('href') |
.clear() | 清空标签的所有内容。 | tag.clear() |
.encode() | 编码标签内容为字节流。 | encoded = tag.encode() |
.is_empty_element | 检查标签是否是空元素(例如 <br>、<img> 等)。 | if tag.is_empty_element: |
.is_ancestor_of() | 检查当前标签是否是指定标签的祖先元素。 | if tag.is_ancestor_of(another_tag): |
.is_descendant_of() | 检查当前标签是否是指定标签的后代元素。 | if tag.is_descendant_of(another_tag): |
其他属性
| 方法/属性 | 描述 | 示例 |
|---|---|---|
.style | 获取标签的内联样式。 | style = tag['style'] |
.id | 获取标签的 id 属性。 | id = tag['id'] |
.class_ | 获取标签的 class 属性。 | class_name = tag['class'] |
.string | 获取标签内部的字符串内容,忽略其他标签。 | content = tag.string |
.parent | 获取标签的父元素。 | parent = tag.parent |
其他
| 方法/属性 | 描述 | 示例 |
|---|---|---|
find_all(string) | 使用字符串查找匹配的标签。 | tag = soup.find_all('div', class_='container') |
find_all(id) | 查找指定 id 的标签。 | tag = soup.find_all(id='main') |
find_all(attrs) | 查找具有指定属性的标签。 | tag = soup.find_all(attrs={"href": "http://example.com"}) |
相关文章:
Python 爬虫 – BeautifulSoup
Python 爬虫(Web Scraping)是指通过编写 Python 程序从互联网上自动提取信息的过程。 爬虫的基本流程通常包括发送 HTTP 请求获取网页内容、解析网页并提取数据,然后存储数据。 Python 的丰富生态使其成为开发爬虫的热门语言,特…...
【星云 Orbit-STM32F4】07. 用判断数据尾来接收据的串口通用程序框架
【星云 Orbit-STM32F4】用判断数据尾来接收一串数据的串口通用程序框架 摘要 本文介绍了一种基于STM32F407微控制器的串口数据接收通用程序框架。该框架通过判断数据尾来实现一串数据的完整接收,适用于需要可靠数据传输的应用场景。本文从零开始,详细讲…...
授权与认证之jwt(一)创建Jwt工具类
JWT的Token要经过加密才能返回给客户端,包括客户端上传的Tokn,后端项目需要验证核 实。于是我们需要一个WT工具类,用来加密Token和验证Token的有效性。 一、导入依赖 <dependency><groupId>com.auth0</groupId><artifactId>jav…...
Kubernetes Service服务发现dns之CoreDNS
文章目录 背景什么是Service、服务发现、Endpoint什么是CoreDNSCoreDNS 的工作原理 常用命令coredns 运行状态根据服务名,判断某个服务dns解析是否正常 背景 Kubernetes 集群内部的服务发现是微服务架构的核心基础,而 DNS 服务则是实现这一机制的关键组…...
Spring Boot 测试:单元、集成与契约测试全解析
一、Spring Boot 分层测试策略 Spring Boot 应用采用经典的分层架构,不同层级的功能模块对应不同的测试策略,以确保代码质量和系统稳定性。 Spring Boot 分层架构: Spring Boot分层架构 A[客户端] -->|HTTP 请求| B[Controller 层] …...
用友NC系列漏洞检测利用工具
声明!本文章所有的工具分享仅仅只是供大家学习交流为主,切勿用于非法用途,如有任何触犯法律的行为,均与本人及团队无关!!! 目录标题 YongYouNcTool启动及适配环境核心功能界面预览一键检测命令执…...
PostgreSQL 创建表格
PostgreSQL 创建表格 在数据库管理中,表格(Table)是数据存储的基础。PostgreSQL作为一款强大的开源对象关系型数据库管理系统(ORDBMS),创建表格是其最基本的功能之一。本文将详细讲解如何在PostgreSQL中创…...
一周一个Unity小游戏2D反弹球游戏 - 球的死区及球重生
前言 本文将实现当球弹到球板下方的死亡区域后,球会被重置到球板上发射点,并且重置物理状态的逻辑。 创建球的死亡区 之前创建的在屏幕下方的空气墙碰撞体可以将其Is Trigger勾选上,让其成为一个触发器,用来检测球是否进入该区域,如下。 创建一个脚本名为Deadzone…...
本地部署 DeepSeek:从 Ollama 配置到 Spring Boot 集成
前言 随着人工智能技术的迅猛发展,越来越多的开发者希望在本地环境中部署和调用 AI 模型,以满足特定的业务需求。本文将详细介绍如何在本地环境中使用 Ollama 配置 DeepSeek 模型,并在 IntelliJ IDEA 中创建一个 Spring Boot 项目来调用该模型…...
vue3:三项目增加404页面
一、路由添加 1、官网地址 带参数的动态路由匹配 | Vue Routerhttps://router.vuejs.org/zh/guide/essentials/dynamic-matching.html 2、复制核心语句 { path: /:pathMatch(.*)*, name: NotFound, component: NotFound } 3、粘贴到路由index.js中 4、建立页面 在view文件夹…...
MCAL(Microcontroller Abstraction Layer)介绍
目录 MCAL的核心作用 MCAL的模块组成 1. 微控制器驱动(Microcontroller Drivers) 2. I/O驱动(DIO, PWM, ADC等) 3. 通信驱动(Communication Drivers) 4. 存储驱动(Memory Drivers…...
爬虫:PhantomJS的详细使用和实战案例
文章目录 一、PhantomJS介绍1.1 什么是 PhantomJS1.2 PhantomJS 的特点与优势二、PhantomJS 的安装2.1 在 macOS 上安装 PhantomJS2.2 在 Linux 上安装 PhantomJS2.3 在 Windows 上安装 PhantomJS2.4 验证安装三、PhantomJS 的基本使用3.1 示例 1:打开网页并截图3.2 示例 2:获…...
目标检测——数据处理
1. Mosaic 数据增强 Mosaic 数据增强步骤: (1). 选择四个图像: 从数据集中随机选择四张图像。这四张图像是用来组合成一个新图像的基础。 (2) 确定拼接位置: 设计一个新的画布(输入size的2倍),在指定范围内找出一个随机点(如…...
深度学习工程师的技术图谱和学习路径
在构建一个深度学习工程师的技术图谱时,按照“技能树与能力模型”的结构可以帮助清晰地展示出技术体系的层次化关系,帮助学习者更好地理解每个技术点的依赖与顺序。 深度学习工程师的技术图谱和学习路径 以下是深度学习工程师的技能树,包括从基础到进阶的学习路径,以及对…...
Qt 文件操作+多线程+网络
文章目录 1. 文件操作1.1 API1.2 例子1,简单记事本1.3 例子2,输出文件的属性 2. Qt 多线程2.1 常用API2.2 例子1,自定义定时器 3. 线程安全3.1 互斥锁3.2 条件变量 4. 网络编程4.1 UDP Socket4.2 UDP Server4.3 UDP Client4.4 TCP Socket4.5 …...
如何使用ArcGIS Pro制作横向图例:详细步骤与实践指南
ArcGIS Pro,作为Esri公司推出的新一代地理信息系统(GIS)平台,以其强大的功能和灵活的操作界面,在地理数据处理、地图制作和空间分析等领域发挥着重要作用。 在地图制作过程中,图例作为地图的重要组成部分&…...
Kotlin 嵌套类和内部类
在Kotlin中,嵌套类(Nested Class)和内部类(Inner Class)是两种不同的类,它们在定义和使用上有一些区别。 1.嵌套类(Nested Classes)默认是静态的(即等同于Java中的stati…...
蓝蝶(BlueStacks)模拟器Root、Magisk、LSPosed及Shamiko框架安装与过应用检测指南
蓝蝶(BlueStacks)模拟器Root、Magisk、LSPosed及Shamiko框架安装与过应用检测指南 蓝蝶bluestacks模拟器root和magisk以及Lsposed和shamiko框架的安装过应用检测 一、引言 蓝蝶(BlueStacks)模拟器是一款广受欢迎的安卓模拟器&…...
OpenCV计算摄影学(6)高动态范围成像(HDR imaging)
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 高动态范围成像(HDR imaging)是一种图像处理技术,旨在通过增加图像的动态范围来更准确地表示真实世界的亮度差…...
[ComfyUI][AI生图]如何在Comfyui中安装插件管理器
如何在ComfyUI便携版中安装插件管理器 在现代软件环境中,图形用户界面(GUI)提供了一种直观的方式来与应用程序交互。ComfyUI是一个出色的GUI框架,它使用户能够通过图形化方式配置和管理他们的应用程序。特别是ComfyUI的便携版,它允许用户在没有安装的情况下使用这一工具,…...
基于MAX 10 FPGA的Z80与8051双核单板计算机设计与实现
1. 项目概述与核心价值最近在整理工作室的旧物,翻出了一堆老古董——Z80和8051的芯片。看着这些曾经叱咤风云的处理器,一个念头冒了出来:能不能用现代的技术,把它们“复活”在一块板子上,做一个集成的单板计算机&#…...
3步搞定M3U8视频下载:N_m3u8DL-CLI-SimpleG图形界面终极指南
3步搞定M3U8视频下载:N_m3u8DL-CLI-SimpleG图形界面终极指南 【免费下载链接】N_m3u8DL-CLI-SimpleG N_m3u8DL-CLIs simple GUI 项目地址: https://gitcode.com/gh_mirrors/nm3/N_m3u8DL-CLI-SimpleG 你是否曾经遇到过在线视频无法保存的烦恼?特别…...
【顶级EI复现】基于去噪概率扩散模型(DDPM)的电动汽车充电行为场景生成研究( Python + PyTorch实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 🎁…...
免费文档下载终极方案:如何优雅获取百度文库等30+平台资源
免费文档下载终极方案:如何优雅获取百度文库等30平台资源 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为…...
Vue-Tree-List 实战指南:构建现代化树形结构的终极方案
Vue-Tree-List 实战指南:构建现代化树形结构的终极方案 【免费下载链接】vue-tree-list 🌲A vue component for tree structure 项目地址: https://gitcode.com/gh_mirrors/vu/vue-tree-list 在现代前端开发中,树形结构是处理层级数据…...
软件测试职业天花板真相:不是岗位不行,是你没找对方向
在软件行业高速发展的今天,打开任何一个技术论坛,总能刷到软件测试从业者的焦虑:“干了5年功能测试,薪资卡在15k再也上不去”“35岁还在写测试用例,是不是要被淘汰了”“AI都能自动生成测试脚本了,我们还有…...
AI落地实战指南:场景锚定、能力分层与人机协同五步法
1. 项目概述:这不是一场技术发布会,而是一份从业者手绘的路线图 “AI: The Journey Ahead”——这个标题乍看像某场科技峰会的宣传语,或是某本畅销书的副标题。但在我过去十二年跑遍制造业产线、教育机构机房、中小律所档案室、社区卫生站HIS…...
云飞云 + SolidWorks服务器 = 10人研发共享方案,附硬件配置清单
10人研发团队用SolidWorks搞设计,是中小制造企业最常见的场景——模型要画、装配要搭、渲染要跑、图纸要存,每天8小时高强度运转。传统模式下每台工作站动辄2~3万元,10台就是25万起步;软件授权10套License,年费轻松30~…...
Monk AI小样本分类实战:用几十张图快速构建可用AI模型
1. 项目概述:用 Monk AI 做分类,但只喂它一小块数据——这到底在解决什么问题?“Classification Using Monk AI by Using a Slice of the Dataset”这个标题乍看平平无奇,甚至有点拗口,但如果你在工业质检、医疗影像初…...
Unity WebGL性能优化实战:内存管理、WASM调优与Shader变体精简
1. 这不是“把游戏搬上网”那么简单:为什么《疯狂特技赛车2》的Web化是Unity引擎能力边界的试金石 你肯定见过那种“Unity WebGL导出一键搞定”的教程,点几下Build Settings,勾上WebGL,等十分钟编译完,拖进浏览器——然…...
