如何使用 Python 和 BeautifulSoup 抓取网站
互联网上的信息如此之多,任何人穷其一生也无法全部消化吸收。你需要的不是访问这些信息,而是一种可伸缩的方式,可以用来收集、组织和分析这些信息。你需要的是Web爬取。Web爬取可以自动提取数据,并以一种让你可以轻松理解的格式显示出来。Web爬取可以用于许多场景,但本教程将重点介绍它在金融市场中的应用。
互联网上的信息如此之多,任何人穷其一生也无法全部消化吸收。你需要的不是访问这些信息,而是一种可伸缩的方式,可以用来收集、组织和分析这些信息。
你需要的是Web爬取。
Web爬取可以自动提取数据,并以一种让你可以轻松理解的格式显示出来。Web爬取可以用于许多场景,但本教程将重点介绍它在金融市场中的应用。
如果你是一名*的投资者,每天获取收盘价可能是一件比较痛苦的事情,尤其是当你需要的信息需要查看多个网页才能找到的时候。我们将通过构建一个网络爬取器,从互联网上自动检索股票指数,简化数据提取。
准备
我们将使用Python作为爬取语言,并使用一个简单而强大的库BeautifulSoup。
- 对于Mac用户而言,OS X预装了Python。打开终端,输入
python --version
。你应该可以看到Python的版本是2.7.x。 - 对于Windows用户,请通过官方网站安装Python。
接下来,我们需要使用pip(一个Python包管理工具)获取BeautifulSoup库。
在终端输入:
easy_install pip
pip install BeautifulSoup4
注意:如果你运行上述命令失败,试下在每一行前面加上sudo。
基本概念
在一头扎进代码之前,让我们先了解下HTML的基本概念和一些爬取规则。
HTML标签
如果你已经了解了HTML标签,大可以跳过这部分。
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1> First Scraping </h1>
<p> Hello World </p>
<body>
</html>
这是HTML页面的基本语法。每个<tag>
服务于网页里的一个块:
-
<!DOCTYPE html>
:HTML文档必须以类型声明开始。 - HTML文档包含在
<html>
和</html>
之间。 - HTML文档的meta和script声明位于
<head>
和</head>
之间。 - HTML的可视部分位于
<body>
和</body>
标签之间。 - 标题的定义通过标签
<h1>
到<h6>
。 - 段落使用
<p>
标签定义。
其他有用的标签还有超链接标签<a>
、表格标签<table>
、表格行标签<tr>
、表格列标签<td>
。
此外,HTML标签有时带有id
或class
属性。id
属性为HTML标签指定一个惟一的id,并且该值在HTML文档中必须是惟一的。class
属性用于为具有相同class的HTML标签定义相同的样式。我们可以使用这些id
和class
帮助定位我们想要的数据。
要了解关于HTML标签、id和class的信息,请查阅W3Schools教程。
爬取规则
- 你应该在爬取之前检查网站的条款和限制。请仔细阅读关于合法使用数据的声明。通常,你收集的数据不应用于商业目的。
- 用你的程序从网站请求数据时不要过激(也称为滥发),因为这可能会对网站造成破坏。确保你的程序以一种合理的方式运行(即表现得像个人)。每秒请求一个页面是很好的做法。
- 网站的布局可能会不时发生变化,所以一定要重新访问网站,并根据需要重写代码。
查看页面
作为例子,让我们看一个来自Bloomberg Quote网站的页面。
作为关注股票市场的人,我们希望从这个页面上获取指数名称(标准普尔500)及其价格。首先,右键单击并打开浏览器检查器来查看网页。
尝试把鼠标悬停在价格上,你应该可以看到一个蓝框。单击它,就可以在浏览器控制台中选择相关的HTML。
从中我们可以看到,价格位于多层HTML标签之中,即<div class="basic-quote">
→ <div class="price-container up">
→ <div class="price">
。
类似地,如果你将鼠标悬停并单击名称“S&P 500 Index”,就会看到它位于<div class="basic-quote">
和<h1 class="name">
中。
现在,我们已经借助class标签知道了数据的唯一位置。
进入代码
现在,我们已经知道我们想要的数据在哪,我们可以开始编写Web爬取器了。现在,打开编辑器。
首先,我们需要导入我们将要用到的库。
# 导入库
import urllib2
from bs4 import BeautifulSoup
接下来,声明一个保存页面URL的变量。
# 指定URL
quote_page = ‘http://www.bloomberg.com/quote/SPX:IND'
然后,使用Python urllib2获取上述URL指向的HTML页面。
# 查询网站,将HTML返回给变量“page”
page = urllib2.urlopen(quote_page)
最后,将页面解析成BeautifulSoup的格式,这样我们就可以使用BeautifulSoup处理它了。
# 使用BeautifulSoup解析HTML页面,并将其保存在变量“soup”中
soup = BeautifulSoup(page, ‘html.parser’)
现在,我们有一个包含页面HTML的变量soup
。从这里开始我们可以编写提取数据的代码了。
还记得我们需要的数据所独有的标签层次吗?BeautifulSoup可以帮助我们进入这些层,并使用find()
提取内容。在本例中,由于HTML class属性的名称在这个页面上是惟一的,所以我们可以简单地查询<div class="name">
。
# 取得class为name的<div>并获取它的值
name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})
在找到标签之后,我们就可以通过获取其text
属性来获取数据。
name = name_box.text.strip() # strip()用于移除字符串头尾的字符
print name
类似地,我们也可以获取指数价格。
# 获取指数价格
price_box = soup.find(‘div’, attrs={‘class’:’price’})
price = price_box.text
print price
运行程序,你应该可以看到它给出了标准普尔500指数的价格。
导出到Excel CSV
现在我们要保存获取到的数据了。Excel逗号分隔格式是一个不错的选择。它可以在Excel中打开,这样你就可以看到数据并轻松地处理它。
但是首先,我们必须导入Python csv模块和datetime模块来获取记录日期。将以下代码插入导入部分。
import csv
from datetime import datetime
在代码底部添加将数据写入CSV文件的代码。
# 用追加方式打开一个CSV文件,这样原有的数据就不会被擦除
with open(‘index.csv’, ‘a’) as csv_file:
writer = csv.writer(csv_file)
writer.writerow([name, price, datetime.now()])
现在运行程序,你应该就可以导出到index.csv
文件,然后你就可以用Excel打开,其中应该包含如下这行数据。
这样,你每天运行下这个程序就可以轻松获得标准普尔500指数的价格了,就不用在网站上翻来翻去了。
进一步探究(高级用法)
多指数
对你而言,爬取一个指数并不够用,对吗?我们可以尝试下同时提取多个指数。
首先,将quote_page
改成URL数组。
quote_page = [‘http://www.bloomberg.com/quote/SPX:IND', ‘http://www.bloomberg.com/quote/CCMP:IND']
然后,将数据提取代码放入一个for循环,它会逐个处理数组中的URL并将所有数据以元组的形式保存到变量data
中。
# 用于循环
data = []
for pg in quote_page:
# 查询网站,将HTML返回给变量“page”
page = urllib2.urlopen(pg)
# 使用BeautifulSoup解析HTML页面,并将其保存在变量“soup”中
soup = BeautifulSoup(page, ‘html.parser’)
# 取得class为name的<div>并获取它的值
name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})
name = name_box.text.strip() # strip()用于移除字符串头尾的字符
# 获取指数价格
price_box = soup.find(‘div’, attrs={‘class’:’price’})
price = price_box.text
# 将数据以元组的形式保存
data.append((name, price))
修改数据保存部分,逐行保存数据
# 用追加方式打开一个CSV文件,这样原有的数据就不会被擦除
with open(‘index.csv’, ‘a’) as csv_file:
writer = csv.writer(csv_file)
# for循环
for name, price in data:
writer.writerow([name, price, datetime.now()])
运行这个程序,应该就可以同时提取两个指数了。
高级爬取技术
BeautifulSoup非常简单,适合于小规模Web爬取。但是,如果你对更大规模的数据爬取感兴趣,就应该考虑下下面这些选项:
- Scrapy是一个非常强大的Python爬取框架。
- 尝试在你的代码中集成一些公共API。数据检索的效率会远远高于爬取网页。例如,看看Facebook Graph API,它可以帮助你获得Facebook网页上没有显示的隐藏数据。
- 当数据变大时,考虑使用类似MySQL这样的数据库后端来存储数据。
采用DRY方法
DRY的意思是“不要重复你自己”,试着像这个人一样自动化你的日常任务。还可以考虑其他一些有趣的项目,比如跟踪Facebook上朋友的活动时间(当然要征得他们的同意),或者在论坛上列出一些话题,并尝试自然语言处理(这是目前人工智能的热门话题)!如果有任何问题,请在下面留言。
本文最初发布于Medium.com,经原作者授权由InfoQ中文站翻译并分享。
原文链接: How to scrape websites with Python and BeautifulSoup
推荐阅读
-
Python 知识点:如何使用 Google 云 IoT 和 Python 进行边缘计算
-
Python 知识:如何使用 Flink 和 Python 进行实时数据处理
-
使用Python解析磁力链接和网站内容
-
如何使用Adobe Acrobat 8 Professional将整个网站抓取并保存为PDF或CHM文件?
-
使用DW和MySQL创建网站的步骤:如何连接DW与MySQL?
-
如何使用Python抓取百度地图的瓦片图片方法
-
如何使用Python从网页和XCX获取数据并将其推送到微信和邮箱
-
使用Python+Selenium4和Edge浏览器,通过带上cookie避免登录验证直接访问网站的方法
-
如何使用HTML、CSS和JavaScript打造购书网站的前端界面
-
使用 Python 上手操作,利用反抓取策略抓取网站