网页信息爬取已经成为现在科学研究获取数据的重要方式之一,也是基于大数据的人工智能技术发展的基础之一。在本教程中,我们将介绍如何自动从网站获取数据。大多数网站都是以受众为中心创建的,您可以使用搜索引擎或在网络浏览器中输入网址,来查看页面上显示的信息。有时候,我们希望自动提取和处理这些数据,这时就需要网络抓取帮助我们免于无聊的重复劳动。我们可以创建自定义爬虫程序来访问网站,提取特定数据并以特定方式处理这些数据。
本文将仅演示从bbc.com新闻网站中提取新闻数据,但您应该能够通过一些试验和纠错来调整它以从任何您想要的网站中提取信息。
例如,您可能需要:
从每周在线发布的报告中提取数据
获取你最喜欢的运动队的日程时间表
找到您喜爱类型的所有即将上映的电影的发布日期
在网站有更新时获取自动通知
Web抓取还有许多其他用例。但是,您还应注意,版权法和网络抓取法律很复杂,因国家/地区而异。虽然人们通常不介意你复制他们的内容甚至是为了商业利益进行网络信息爬取,但是有一些法律案件涉及了从LinkedIn抓取数据、从OKCupid抓取数据等,网络抓取可能会违反法律、违反特定网站的服务条款或违反道德准则。所以在抓取信息之前,要确定其是否合法。
1. 概要与环境
在本教程中我们将介绍:
网站到底是什么以及HTML如何运作
在Web浏览器中查看HTML
使用Python下载网页
使用BeautifulSoup提取数据
我们将使用在线编程环境repl.it,因此您无需在本地安装任何软件即可逐步进行操作。如果您想根据自己的需要对本教程中的代码进行调整,您可以在repl.it按照注册流程创建一个免费帐户。
2. 网页:美女与野兽
毫无疑问,我们都使用过Web浏览器访问过网页。网站有两种形式:
您习惯使用的那个,您可以在其中看到文本,图像和其他媒体。不同的字体,大小和颜色用于以有用和美学方式显示信息。
网页源码。这是一个计算机代码,可以告诉您的Web浏览器(例如Mozilla Firefox或Google Chrome)显示什么以及如何显示它。
网站通常使用三种计算机语言进行编码:HTML,CSS和JavaScript。这本身就是一个庞大而复杂的领域,基本了解其中的一些工作原理是有效进行自动化网页抓取的必要条件。您在浏览器中打开任何网站并右键单击网站的某个页面,您将看到一个菜单,其中应包含“查看源”选项。
如下图所示:左侧是普通网页和打开的页面右键菜单(通过右键单击页面显示)。单击查看源码按钮会生成右侧的结果,我们可以看到包含Web浏览器显示完整页面所需的所有数据和支持信息的代码。虽然左边的页面易于阅读和使用,并且看起来很好,但右边的页面则看起来像是怪物,一般人较难理解,但是如果我们想编写自定义Web抓取器,了解它是必要的。
3. 使用源代码页面使用“查找”功能
首先要弄清楚这两个页面的对应方式:正常显示的网站的哪些部分与代码的哪些部分相匹配。您可以在源代码视图中使用“查找”(Ctrl + F)来查找在普通视图中可见的特定文本片段以帮助完成此操作。在左边的文章中,我们可以看到以“Getting a TV job”这个短语开头。 如果我们在代码视图中搜索此短语,我们可以在代码中找到相应的文本,在第805行。
高亮显示部分之前的
是HTML代码,用于指定段落(HTML中的
)从此处开始,并且这是一种特殊的段落(故事简介)。该段继续到符号。您不必完全理解HTML,但您应该知道它包含的构成新闻文章的文本数据和有关如何显示文章的其他数据。网页抓取的很大一部分工作是查看网页代码,以识别我们感兴趣的数据,并将其与其他代码分开。
在大多数页面中,有很多代码用于定义网页的结构,布局,交互性和其他功能,而相对较少的代码包含我们通常查看的实际文本和图像。对于特别复杂的页面,即使在查找功能的帮助下,也很难找到负责页面特定部分的代码。为了解决这个问题,大多数Web浏览器都带有所谓的“开发人员工具”,主要针对程序员协助创建和维护Web站点,但这些工具对于Web抓取也非常有用。
4. 使用开发人员工具
您可以从主菜单打开浏览器的开发者工具,左侧显示Google Chrome,右侧显示Mozilla Firefox。 如果您使用的是其他网络浏览器,应该能够找到类似的设置。
打开开发人员工具会在Web浏览器中显示一个新面板,通常位于底部或右侧。 该工具包含一个“Inspector”面板和一个选择器工具,可以通过按下下面的红色图标来选择。 选择器工具激活后,您可以单击网页的某些部分以查看相应的源代码。在下图中,我们在普通视图中选择了相同的第一段,我们可以在下面的面板中再次看到
代码。
开发人员工具比使用简单的源代码查找工具更强大,但它们也更复杂。 您应该根据自己的经验和尝试分析的页面的复杂性选择一种方法。
5. 使用Python获取网页
现在我们已经看到了关于如何在浏览器中构建网页的内容,我们可以开始使用Python检索和操作它们。 Python不是Web浏览器,因此我们不会通过Python获得网页的“正常”表示。相反,我们只能检索和操作HTML源代码。
我们将使用requests库通过一个Python Repl执行此操作。打开repl.it并选择创建一个新的Python repl。
这将带您进入一个可以编写和运行Python代码的Python编译环境。首先,我们将从BBC新闻主页下载内容,并打印出HTML源代码的前1000个字符。
您可以使用以下四行Python来完成此操作:
import requests
url= "https://bbc.com/news"
response= requests.get(url)
print(response.text[:1000])
将此代码放在Repl自动为您创建的main.py文件中,然后按“Run”按钮。在短暂的延迟之后,您便可在输出窗格中看到输出的HTML源代码,类似于我们在上面的Web浏览器中查看的内容。
每行代码功能分析:
在第1行中,我们导入了Python的requests库,这是一个发出Web请求的库。
在第3行中,我们定义了一个包含BBC新闻网站的URL的变量。您可以在Web浏览器中访问此URL以查看BBC新闻主页。
在第4行中,我们将我们定义的URL传递给requests.get函数,该函数将访问URL指向的网页并获取HTML源代码。我们将其加载到一个名为response的新变量中。
在第5行中,我们访问响应对象的text属性,该属性包含所有HTML源代码。我们只获取前1000个字符,并将它们传递给print函数,该函数只是将生成的文本转储到输出窗格。
我们现在已经自动爬取了一个网页,并可以显示部分内容。我们不太可能对网页的完整源代码转储感兴趣(除非我们出于存档的原因存储它),所以让我们提取页面的一些符合我们需要的部分而不是前1000个字符。
6. 使用Beautifulsoup获取新闻URL
我们现在想在BBC新闻主页上找到所有新闻文章,并获取他们的网址。如果我们查看下面的主页面,我们会看到主页上有很多故事,使用“检查”工具将光标置于任何标题之上,我们可以看到每个故事都有一个唯一的网址,它将我们带到那个新闻报道。例如,在下图中标题为“US and Canada agree new trade deal”的新闻的网址是https://www.bbc.com/news/business-45702609。
如果我们使用浏览器的开发人员工具检查该元素,我们可以看到它是一个元素,它是链接的HTML,其中标签指向URL。请注意,href部分仅指向URL的后半部分,省略了https://www.bbc.com部分。由于我们已经在BBC上,因此该网站可以使用相对URL而不是绝对URL。这意味着当您单击该链接时,您的浏览器将确定该URL未完成,并在其前面加上https://www.bbc.com。
我们可以尝试使用Python的内置文本搜索功能(如find()或正则表达式)从BBC页面中提取所有URL,但实际上不可能可靠地执行此操作。幸运的是,有一个功能强大且易于使用的HTML解析库,名为BeautifulSoup,它将帮助我们从给定的HTML片段中提取所有链接。我们可以通过修改Repl中的代码来使用它,如下所示:
import requests
from bs4 import BeautifulSoup
url = "https://bbc.com/news"
response = requests.get(url)
html = response.text
soup = BeautifulSoup(html, "html.parser")
links = soup.findAll("a")
for link in links:
print(link.get("href"))
如果您运行此代码,您将看到它输出了几十个URL,每行一个。您可能会注意到代码现在比以前运行起来时间要长得多,BeautifulSoup不是内置于Python中,而是第三方模块。 这意味着在运行代码之前,Repl必须去获取此库并为您安装它。后续运行会更快。
代码分析:
在第2行,我们导入BeautifulSoup库,用于解析和处理HTML。
在第9行,我们将HTML转换为“soup”。这是BeautifulSoup对网页的表示,其中包含一系列有用的编程功能,用于搜索和修改页面中的数据。我们使用“html.parser”选项来解析默认包含的HTML,BeautifulSoup还允许您在此处指定自定义HTML解析器。例如,您可以安装并指定一个更快的解析器,如果您需要处理大量HTML数据,这可能很有用。
在第10行,我们在HTML中找到所有元素并将它们提取到列表中。请记住,当我们使用Web浏览器查看URL时,我们注意到HTML中的元素用于定义链接,href属性用于指定链接的去向。该行找到所有HTML 元素。
在第11行中,我们循环遍历所有链接,在第12行中我们打印出href部分。
最后两行显示了BeautifulSoup的优势。在没有它的情况下尝试找到并提取这些元素真的很难,但现在我们可以用两行可读代码来完成它!
如果我们查看输出窗格中的URL,我们会看到很多结果。我们有绝对URL(以“http”开头)和相对URL(以“/”开头)。他们中的大多数都转到一般页面而不是特定的新闻文章。我们需要在我们感兴趣的链接中找到一个模式(转到新闻文章),这样我们才能只提取我们感兴趣的那些。
我们可以对代码进行一些小改动,只输出与此模式匹配的URL。用以下四行替换上述代码的最后两行:
forlink in links:
href = link.get("href")
if href.startswith("/news") andhref[-1].isdigit():
print(href)
代码运行结果:
7. 获取所有文章
现在我们已经获取到BBC新闻主页上的每篇文章的链接,可以进一步获取这些文章每一篇的数据。作为一个实验项目,让我们从每篇文章中提取专有名词(人物,地点等)并打印出最常见的名词,以了解今天新闻所讨论的内容。
调整我们的代码如下:
import requests
import string
from collections import Counter
from bs4 import BeautifulSoup
url= "https://bbc.com/news"
response = requests.get(url)
html = response.text
soup = BeautifulSoup(html, "html.parser")
links = soup.findAll("a")
news_urls = []
forlink in links:
href = link.get("href")
if href.startswith("/news") andhref[-1].isdigit():
news_url = "https://bbc.com"+ href
news_urls.append(news_url)
all_nouns = []
forurl in news_urls[:10]:
print("Fetching {}".format(url))
response = requests.get(url)
html = response.text
soup = BeautifulSoup(html,"html.parser")
nouns = [word for word in words ifword.isalpha() and word[0] in string.ascii_uppercase]
all_nouns += nouns
print(Counter(all_nouns).most_common(100))
这段代码比我们之前编写的代码更复杂,所以如果你不了解所有这些代码,请不要担心。主要变化是:
在顶部,我们添加了两个新的导入。一个用于字符串,它是标准的Python模块,包含一些有用的单词和字母快捷方式。我们将使用它来识别字母表中的所有大写字母。第二个模块是一个计数器,一旦我们建立了所有名词的列表,我们就可以在列表中找到词频最高的名词。
我们在第一个for循环的顶部添加了news_urls= []。我们将其标识为“news URL”后,不是打印出每个URL,而是将其添加到此列表中,以便我们以后可以下载每个页面。在for循环内部向下两行,我们将根域(“http://bbc.com”)与每个href属性组合在一起,然后将完整的URL添加到news_urls列表中。
然后我们进入另一个for循环,在那里我们遍历前10个新闻URL(如果你有更多时间,你可以删除[:10]部分来遍历所有新闻页面,但为了提高效率,我们只是用前10个)。
下一行循环遍历该给定文章中的所有单词,并仅保留由数字字符组成的单词,并以大写字母开头(string.ascii_uppercase只是大写字母)。这也是一种非常粗略的提取名词的方式,我们会得到很多单词(比如句子开头的那些单词),这些单词实际上并不是专有名词,但现在又是一个很好的近似值。
最后,我们将所有看起来像名词的单词添加到我们的all_nouns列表中,然后转到下一篇文章来做同样的事情。下载解析所有页面之后,我们可以使用Python中内置的Counter来统计词频。
您应该看到类似于下图的输出(尽管您的文字会有所不同,因为新闻每隔几个小时就会发生变化)。我们有最常见的名词,然后计算这个名词出现在我们所看到的所有10篇文章中的频率。
我们可以看到我们的原始提取和解析方法远非完美,由于每篇文章底部的社交媒体链接,大多数文章都会出现像“Twitter”和“Facebook”这样的词,因此它们的存在并不意味着Facebook和Twitter本身就在今天的新闻中。类似地,诸如“From”之类的单词不是名词,并且还包括诸如“BBC”,“Optimizely”和“Business”之类的其他单词,因为它们主要出现在页面上文章之外的文本上。
8. 后续
我们已经学习了网页信息抓取的基础知识,并研究了网络的工作原理,如何从网页中提取信息,以及如何进行一些非常基本的文本提取。你可能想要做一些与BBC提取单词不同的东西!您可以从https://repl.it/@GarethDwyer1/beginnerwebscraping中fork此Repl并对其进行修改以更改它所搜索的站点以及它提取的内容。
好用的Python网页抓取工具:
Scrapy:想要爬取百万甚至数十亿网页的人使用的框架。Scrapy允许您构建“蜘蛛”程序化机器人,根据您指定的规则收集数据。
Newspaper:我们上文谈到将在线新闻文章的主要文本与页面上的所有其他内容分开比较困难。Newspaper使用手动指定的规则和一些算法的组合来从每篇文章中删除非核心文本。
Selenium:现代网页的许多部分都是动态的,例如它们仅在您向下滚动页面时加载,或者单击按钮以显示更多内容。这些动态站点很难自动抓取,但是selenium允许您启动真实的Web浏览器并模拟真人操作,帮助您自动访问这种动态内容。
还有许多其他工具,只需将它们相互结合使用即可完成很多工作。如果您有好的建议或问题,请留言评论。
END
本公众号原创作品,未经授权禁止转载,特此声明,谢谢合作!
领取专属 10元无门槛券
私享最新 技术干货