写点什么

如何使用 Python 和 BeautifulSoup 爬取网站

  • 2019-10-21
  • 本文字数:3456 字

    阅读完需:约 11 分钟

如何使用Python和BeautifulSoup爬取网站

本文最初发布于Medium.com,经原作者授权由 InfoQ 中文站翻译并分享。


互联网上的信息如此之多,任何人穷其一生也无法全部消化吸收。你需要的不是访问这些信息,而是一种可伸缩的方式,可以用来收集、组织和分析这些信息。你需要的是 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>服务于网页里的一个块:


  1. <!DOCTYPE html>:HTML 文档必须以类型声明开始。

  2. HTML 文档包含在<html></html>之间。

  3. HTML 文档的 meta 和 script 声明位于<head></head>之间。

  4. HTML 的可视部分位于<body></body>标签之间。

  5. 标题的定义通过标签<h1><h6>

  6. 段落使用<p>标签定义。


其他有用的标签还有超链接标签<a>、表格标签<table>、表格行标签<tr>、表格列标签<td>


此外,HTML 标签有时带有idclass属性。id属性为 HTML 标签指定一个惟一的 id,并且该值在 HTML 文档中必须是惟一的。class属性用于为具有相同 class 的 HTML 标签定义相同的样式。我们可以使用这些idclass帮助定位我们想要的数据。


要了解关于 HTML标签idclass的信息,请查阅 W3Schools教程


爬取规则


  1. 你应该在爬取之前检查网站的条款和限制。请仔细阅读关于合法使用数据的声明。通常,你收集的数据不应用于商业目的。

  2. 用你的程序从网站请求数据时不要过激(也称为滥发),因为这可能会对网站造成破坏。确保你的程序以一种合理的方式运行(即表现得像个人)。每秒请求一个页面是很好的做法。

  3. 网站的布局可能会不时发生变化,所以一定要重新访问网站,并根据需要重写代码。

查看页面

作为例子,让我们看一个来自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 urllib2from bs4 import BeautifulSoup
复制代码


接下来,声明一个保存页面 URL 的变量。


# 指定URLquote_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.textprint price
复制代码


运行程序,你应该可以看到它给出了标准普尔 500 指数的价格。


导出到 Excel CSV

现在我们要保存获取到的数据了。Excel 逗号分隔格式是一个不错的选择。它可以在 Excel 中打开,这样你就可以看到数据并轻松地处理它。


但是首先,我们必须导入 Python csv 模块和 datetime 模块来获取记录日期。将以下代码插入导入部分。


import csvfrom 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 爬取。但是,如果你对更大规模的数据爬取感兴趣,就应该考虑下下面这些选项:


  1. Scrapy是一个非常强大的 Python 爬取框架。

  2. 尝试在你的代码中集成一些公共 API。数据检索的效率会远远高于爬取网页。例如,看看Facebook Graph API,它可以帮助你获得 Facebook 网页上没有显示的隐藏数据。

  3. 当数据变大时,考虑使用类似MySQL这样的数据库后端来存储数据。

采用 DRY 方法


DRY 的意思是“不要重复你自己”,试着像这个人一样自动化你的日常任务。还可以考虑其他一些有趣的项目,比如跟踪 Facebook 上朋友的活动时间(当然要征得他们的同意),或者在论坛上列出一些话题,并尝试自然语言处理(这是目前人工智能的热门话题)!如果有任何问题,请在下面留言。


原文链接:


How to scrape websites with Python and BeautifulSoup


2019-10-21 08:002720

评论 1 条评论

发布
用户头像
小心被抓
2019-10-21 21:49
回复
没有更多了
发现更多内容

不使用Raft算法,就能简单做集群leader选举

架构师修行之路

分布式 架构师

从一段 Dubbo 源码到 CPU 分支预测的一次探险之旅

yes

dubbo cpu

我们该怎么保护手机屏幕前的父母?

徐说科技

手机 短视频

SpringCloud轻松集成Dubbo实现RPC调用

Barry的异想世界

微服务 dubbo nacos RPC spring cloud alibaba

区块链激励层——区块链生态建设的驱动力量

CECBC

区块链技术 驱动力量

Golang领域模型-实体

奔奔奔跑

架构 微服务 领域驱动设计 DDD Go 语言

计算机的时钟(三):向量时钟

ElvinYang

业务架构学习内容有哪些?

周金根

BIZBOK 业务架构

我理解的面向对象(ObjectiveSql 实践)

Braisdom

Java ORM框架 ORM

【高并发】面试官:讲讲什么是缓存穿透?击穿?雪崩?如何解决?

冰河

缓存 穿透 击穿 雪崩 签约计划第二季

区块链应用层——生态体系的上层建筑

CECBC

区块链技术 生态体系

Spring Security 主要类解释

哈库拉玛塔塔

springsecurity

重新学习了一遍ThreadLocal

熊斌

学习

金沙账号审核不通过维护不给提现风控怎么回事?怎么办

过山太阳

内容审核 提现不了

HashMap将cpu打满始末

hashmap 线程安全 cpu 100% cpu飙满

以大数据为依托提升基层治理效能

CECBC

大数据 信息化管理

认证、授权、鉴权和权限控制

哈库拉玛塔塔

spring security 用户权限 鉴权 权限

华为与第四范式,正在酝酿一个帮企业跳出AI悖论的“秘密计划”

脑极体

浮点数的秘密

C语言与CPP编程

c c++ 编程语言 浮点数

week11--作业

Geek_165f3d

布式系统消息异常该何去何从

架构师修行之路

分布式 异步

企业中台化落地:从战略分析到战术实践及架构演进过程

Barry的异想世界

架构设计 策略模式 模板方法模式 中台架构 领域驱动设计DDD

Java四种引用类型:强引用、软引用、弱引用、虚引用

简爱W

为什么每个微服务要有自己独立的数据库?

码猿外

数据库 架构 微服务

oeasy教您玩转 linux 010212 管道 pipe

o

LeetCode 169. Majority Element

liu_liu

算法 LeetCo

Go: 理解 Sync.Pool 的设计

陈思敏捷

sync sync.pool pool Go 语言

记录问题 INSERT INTO table ... SELECT ... FROM dual WHERE not exists (...)问题

转山转水

sql SQL语法 sql查询

spark总结

纯纯

不草率,你只管下载资料,剩下的交给「哇哦」

小Q

Java 学习 架构 面试 分布式

一文带你了解微服务架构和设计(多图)

Phoenix

架构 分布式 微服务

如何使用Python和BeautifulSoup爬取网站_语言 & 开发_Justin Yek_InfoQ精选文章