维基百科中的数据科学:亲自教你阅读世界上最大的Python百科全书

大数据文摘

编译:狗小白,李家,张驰,魏自民

没有人否认维基百科是现代人类最惊人的发明之一。

几年前,谁会想到匿名投稿人的志愿工作创造了一个前所未有的巨大在线知识库维基百科不仅是你撰写大学论文的最佳信息渠道,也是一个极其丰富的数据源。

从自然语言处理到监督下的机器学习,维基百科帮助了许多数据科学项目。

维基百科是世界上最大的百科全书,但它也让数据工程师有点头疼。当然,有了正确的工具,数据量的大小不会成为大问题。

这篇文章将介绍“如何编写、下载和解析英语维基百科”。

在介绍过程中,我们还将提到数据科学中的以下重要问题:

1。搜索和程序从网络下载数据

2。使用Python库分析网络数据( HTML、XML、MediaWiki格式)

3 .多进程处理和并行化处理

这个项目最初是为了收集维基百科上的所有书籍,但我后来发现,这个项目中使用的解决方案可以得到更广泛的应用。这里提到并在Jupyter笔记本中展示的技术可以有效地处理维基百科上的所有文章,也可以扩展到其他网络数据源。

受Douwe OSI NGA优秀的深入学习手册的启发,本文中使用的Python代码注释被放置在Github中。前面提到的jupyter笔记本也可以免费获得。

GitHub链接:

https://github.com/WillKoehrsen/wikipedia - Data - Science / BLOB / MASTER / Notebook / Download % 20 and % 20 Resolve % 20 Wikipedia % 20 Articles

免费访问地址:

编程搜索和下载数据

任何数据科学项目的第一步都是获取数据。当然,我们可以一个接一个地去维基百科页面打包下载搜索结果,但是下载很快就会受到限制,也会给维基百科服务器带来压力。我们还有一种方法可以通过网站dumps.wikimedia.org (也称为dump )获得所有维基百科数据的定期快照结果。

使用下面的代码,我们可以看到数据库的可用版本:

The import request # library is used to parse HTML import requests from BS4. TextShop _ Index = Leaseoul ( Index,' HTML. Parser' ) # Found an IN SOP _ Index. Find _ All (' A' ) on page dump = [ A [' href' ), if A has a link .. /',' 2018 06 20 /',' 2018 07 01 /',' 2018 08 20 /',' 2018 09 01 /',' 2018 09 20 /',' latest /''

这段代码使用beatiful声音库来解析html。由于HTML是网页的标准标记语言,这个库是处理网络数据的无价之宝。

该项目使用2018年9月1日的转储(一些转储数据不完整,请确保选择您需要的转储数据)。我们使用以下代码查找转储中的所有文件。

转储网址=基本URL + ' 20180901 / ' #检索htmldump _ html =请求。获取(转储网址) .文本#转换为汤类_ dump = universup (转储_ html ),“html”。解析器' ) #查找具有类文件输出转储。find _ all ( ' Li ',{ ' )类:“文件”} )的列表元素[ : 3 ) [ & lt;李;& lt;a href = " / enwiki / 20180901 / enwiki - 20180901 -页-文章-多数据流恩维基- 20180901 - pages -文章-多数据流);15.2 GB & lt;/ Li >;,& lt;李;& lt;a href = " / enwiki / 20180901 / enwiki - 20180901 -页-文章-多数据流-索引恩维基- 20180901 - pages -文章-多数据流-索引);195.6 MB & lt;/ Li >;,& lt;李;& lt;a href = " / enwiki / 20180901 / enwiki - 20180901 -页-元历史1。XML - p10p 2101.7z”;恩维基- 20180901页-元历史1。XML - p10p 2101.7z & lt;/ a >;320.6 MB & lt;/ Li >;]

我们再次使用Beatiful汤来解析网络以找到文件。我们可以在https://dumps.wikimedia.org/enwiki/20180901/网页上手动下载文件,但是这还不够有效。网络数据如此庞杂,以至于了解如何解析HTML并在程序中与网页交互非常有用——学习网站检索的一些知识将使巨大的新数据源触手可及。

考虑下载什么

上面的代码已经找到了转储中的所有文件,并且你有一些下载选项:文章的当前版本、文章页面和当前讨论列表,或者文章的所有历史修订和讨论列表。如果你选择最后一个,那就是数万亿字节的数据!只有最新版本的文章被选择用于这个项目。

所有文章的当前版本都可以作为一个文档获得,但是如果我们下载并解析这个文档,浏览一篇文章会非常费力,效率非常低。更好的方法是下载多个分区文档,每个分区文档都是本文的一部分。之后,我们可以通过并行化一次解析多个文档来显著提高效率。

“当我处理文档时,我更喜欢多个小文档而不是一个大文档,这样我可以并行运行多个文档。"

分区文档格式是BZ2压缩XML (可扩展标记语言),每个分区的大小为300 - 400 MB,所有压缩包的大小为15.4 GB。没有必要解压缩,但是如果你想解压缩,大小大约是58GB。对于所有人类知识来说,这个尺寸似乎并不太大。

维基百科压缩文件大小

下载文件

Keras中的GET _ FILE语句在实际下载文件时非常有用。以下代码可以通过链接下载文件并保存到磁盘:

Import Get File from Keras. Utilities Save File Path = Get File ( File, URL )

下载的文件保存在~/。keras /数据集/,这也是keras的默认保存设置。一次下载所有文件需要2个多小时(你可以尝试并行下载,但是我在尝试同时执行多个下载任务时速度有限)

解析数据

我们必须先解压缩文件。但是事实上,我们发现这并不是获取所有文章数据所必需的。我们可以通过解压缩并一次运行一行来迭代文档。当内存不足以运行大量数据时,文件之间的迭代通常是唯一的选择。我们可以使用BZ2库迭代BZ2压缩文件。

然而,在测试期间,我发现了一种更快(两倍快)的方法,使用了系统实用程序BZCAT和Python模块的子流程。上面揭示了一个重要的观点:解决问题的方法通常有很多,找到最有效方法的唯一方法就是对我们的程序进行基准测试。这可以通过% % Time的Jupyter细胞魔法来轻松评估。

迭代解压缩文件的基本格式是:

Data path =' ~ /. Keras / datasets / en wiki - 2018 09 01 - pages - 15. XML - p 7744803. bz2 # iteratively compresses files line by line in the subprocess. Popen ( [' bzcat' ], stdin = open ( data path ), stdout = subprocess. Pipelines ). Standard Output: # Production Line

如果我们简单地阅读XML数据并将其附加到列表中,我们会得到如下所示的结果:

维基百科文章的源XML

维基百科文章的XML文件如上所示。每个文件中有数千篇文章,所以我们下载的文件包含数百万行这样的语句。如果我们真的想把事情复杂化,我们可以用正则表达式和字符串匹配来浏览文档,找到每篇文章。这效率极低,我们可以采取更好的方法:使用定制工具解析XML和维基百科文章。

分析法

我们需要在两个层次解析文档:

1。从XML中提取文章标题和内容

2。从文章内容中提取相关信息

幸运的是,Python对这两者都有很好的响应。

解析XML (可扩展标记语言)

为了解决第一个问题——定位文章,我们使用SAX ( XML的简单API )语法分析器。beatiful sound语句也可以用于解析XML,但是需要内存来加载整个文档并构建文档对象模型( DOM )。然而,SAX一次只运行XML中的一行字,这完全符合我们的应用场景。

基本思想是我们搜索XML文档并提取特定标签之间的相关信息。例如,给出以下XML语句:

& lt; Title >; Carol Knies Lee; / title >; & lt; Text XML: space = " preserve" >; Carroll F. K Nichely ( born in 1929 in Virginia [ [, Staunton ] ] - died on November 2, 2006 in Kentucky [ [, Glasgow ] ] as [ [ editor | editor ] ] and [ [ publisher | publisher ] ] of [ [ Glasgow Daily Times ] ] for nearly 20 years ( later, owner ), serving as commissioner and later commerce minister under three [ [ Kentucky Governor | Kentucky Governor ] ]. \ n ' & lt; / text >;

我们想在中筛选出来;和;两个标签之间的内容(这个标题是维基百科的文章标题,文本是文章内容)。SAX使我们能够直接实现控制信息如何通过解析器,然后通过解析器和内容处理程序语句处理的功能。一次将一行XML语句扫入解析器,内容处理程序将帮助我们提取相关信息。

如果不尝试,可能很难理解,但是内容处理程序的想法是在开始标记和结束标记之间找到内容,并将找到的字符添加到缓存中。然后,缓存的内容被保存到字典中,相应的标签作为相应的密钥。最后,我们得到了一个字典,其中密钥是标签,值是标签中的内容。接下来,我们将把这个字典传递给另一个函数,它将解析字典的内容。

我们需要编写的SAX的唯一部分是内容处理程序。全文如下:

在这个代码中,我们寻找标记标题和文本的标签。每次解析器遇到其中一个,它都会将字符保存在缓存中,直到遇到相应的结束标记(;) .然后它将缓存的内容保存在字典- self中。_ values。逐篇;如果内容处理程序遇到表示结尾的page >;标签,这将增加自我。_值到文章列表( self。_ pages )。如果你感到困惑,观察实践可能会有所帮助。

下面的代码展示了如何通过XML文件找到文章。现在,我们只是把它们保存到handler。_ pages,稍后我们将把文章发送到另一个函数进行解析。

# Object for processing XML Handler = WikixmlHandler # Parsing Object Resolver = XML. SAX. Make _ Parser. SetContentHandler ( Handler ) # iteratively processes files for rows in child processes. Popen ( [' bzcat' ], stdin = open ( data path ), stdout = subprocess. Pipelines ). When three articles are found, stop. _ pages ) >; 2: Rest

如果我们看看Handler。_ Pages,我们将看到一个列表,其中每个元素都是包含文章标题和内容的元组:

Processing program. _ Pages [ 0 ] [ (' Carol Knightley',' Carol Knightley'' ( born in 1929 in Virginia [ [ [ Staunton ] ] - died on November 2, 2006 in Kentucky [ [ [ Glasgow ] ] ) are [ [ editor | editor ] ] and [ [ publisher | publisher ] ] ] ) ]

此时,我们已经编写的代码可以成功地识别XML中的文章。既然我们已经完成了解析一半文件的任务,下一步就是处理这些文章,找到特定的页面和信息。同样,我们使用了专门为此工作创建的工具。

维基百科文章分析

维基百科运行在名为MediaWiki的软件上,该软件用于构建维基百科。这使得文章遵循一种标准格式,这种格式可以很容易地以编程方式访问其中的信息。尽管文章的文本看起来像一个字符串,但由于格式化的原因,它实际上编码了更多的信息。为了有效地获取这些信息,我们引入了功能强大的mwparserfromwell,这是一个用来处理mediawiki内容的库。

如果我们将维基百科文章的文本传递给mwparserfromwell,我们将得到一个包含许多数据排序方法的维基代码对象。例如,下面的代码从文章中创建一个wiki代码对象,并从文章中检索wiki链接。这些链接指向维基百科的其他文章:

Import mwparserfromwell # to create a wiki article. _ pages [ 6 ] [ 1 ] ) # find the title of wikilinkswikilink = [ x x x ] in the wiki. Filter _ Wiki Links ] Wiki Links [: 5 ] [' Provo, Utah',' Wasatch Front',' Megahertz',' Contemporary Hot Radio',' Watt' ]

有许多有用的方法可以应用于Wiki代码,例如查找注释或搜索特定关键字。如果你想得到文章文本的最终版本,你可以打电话给:

Strip' Kenz ( 94.9 FM, " Power 94.9" ) is a top 40 / CHR radio station broadcasting to Salt Lake City, Utah

因为我的最终目标是找到所有关于书籍的文章,有没有办法使用解析器来识别类别中的文章?幸运的是,答案是肯定的——使用MediaWiki模板。

文章模板

模板是记录信息的标准方式。维基百科上有许多模板,但与我们的目的最相关的是信息框。一些模板编码文章的摘要信息。例如,战争与和平的消息框是:

维基百科上的每一类文章,如电影、书籍或电台,都有自己的信息盒。在一本书的例子中,信息框架模板被命名为信息盒书。类似地,wiki对象有一种叫做filter _ templates的方法,它允许我们从文章中提取特定的模板。因此,如果我们想知道一篇文章是否与一本书有关,我们可以通过图书信息框过滤它。如下所示:

# Filter articles Wiki. Filter _ Templates ( " InfoBox Books" ) for book templates

如果比赛成功,我们会找到一本书!要找到你感兴趣的文章类别的信息框模板,请参考信息框列表。

如何将用于分析文章的mwparserfromwell与我们编写的sax解析器相结合,我们修改了内容处理程序中的end element方法,并将包含文章标题和文本值的字典发送给通过指定模板搜索文章文本的函数。如果函数找到我们想要的文章,它会从文章中提取信息并将其返回给处理程序。首先,我将向您展示更新后的End元素。

DEF END ELEMENT ( SELF, NAME ): " End tag of element" ( if NAME = = SELF ). _ current _ tag: self. _ Values [ Name ] =''. Join ( yourself ). _ buffer ) if the name = = " page": self. _ plice _ count + = 1 # send page to process _ plice function manual = process _ plice ( * * self ). _ Values, Template =' InfoBox Book' ) # Book: Self if the article is a book attached to the book list. _ books. additions ( books )

解析器到达文章末尾后,我们将文章传递给函数process _ plice,如下所示:

DEF PROCESS _ TILE ( Title, Text, Timestamp, Template = " InfoBox Book" ): " Processing Wikipedia Articles to Find Templates" # Create a Parsing Object Wiki Code = MWPARSERFromShell. Parse " # Search Template Match = Wiki Code. Filter _ Templates ( Match = Template ) ( If Len ( Match ) >; = 1: # Extract information from InfoBox attribute = { param. name. strip _ code. strip: param. value. strip _ code. matches [ strip of parameters in 0 ]. Parameter Value Extraction Internal WikiLeaks

虽然我在寻找关于书籍的文章,但是这个功能可以用来搜索维基百科上任何类别的文章。只需用指定类别的模板替换模板(例如,InfoBox语言用于查找语言),它将只返回合格的文章信息。

我们可以在文件上测试这个函数和新的内容处理程序。

Searched 427481 articles. 1426 books were found in 1055 seconds.

让我们看看找本书的结果:

[ 10 ] [' War and Peace' {' Name':' War and Peace' {' Author':' lev tolstoy',' Language':' Russian, with some French',' Country':' Russia',' Genre':' Novel ( Historical Novel )',' Publishers':' Russian Messenger ( Serialization )',' Title _ Orig':' Г Г Г',' Orig _ Lang _ Code':' Ru',' Translator':' The first English translation of War and Peace is' 1869 Book',' Media Type':' Printing',' Pages':' 1, 1 ID = C4 HEAN - TI1 MC',' HTTPS: / / WW. Britannica. COM / Art / English Literature', https://books.google.com/books? ? id = xf7umXHGDPcC,https://books.google.com/? ? id = E5fotqsglPEC,https://books.google.com/? ? id = 9 shebfzixfac ' ],' 2018 - 08 - 29t 02 : 37 : 35Z ' ]

对于维基百科上的每本书,我们将信息框中的信息组织成字典,维基百科中书籍的信息,书籍的外部链接和最新编辑的时间戳。(我专注于这些信息,并为我的下一个项目建立了一个图书推荐系统。) .您可以修改process _ plice函数和wiki xmlhandler类,以找到您需要的任何信息和文章!

如果你只看一个文档的处理时间,1055秒,然后乘以55,你会发现所有文档的处理时间都超过了15小时!当然,我们可以连夜跑,但是如果可以,我不想浪费额外的时间。这导致了我们将在这个项目中介绍的最后一项技术:使用多线程和多线程的并行化。

并行操作

与其一次解析一个文件,不如同时处理几个文件(这就是我们下载分区的原因)。我们可以通过多线程或多处理来使用并行化。

多线程和多处理

多线程和多处理是在一台计算机或多台计算机上同时执行许多任务的方法。我们磁盘上有许多文件,每个文件都需要以相同的方式解析。一个简单的方法是一次解析一个文件,但是这并没有充分利用我们的资源。因此,我们可以使用多线程或多进程同时解析多个文件,这将大大加快整个进程。

一般来说,多线程对于输入/输出绑定任务(如读取文件或发出请求)更好(更快)。对于CPU密集型任务,多处理更好(更快)。在分析文章的过程中,我不确定哪种方法是最好的,所以我再次用不同的参数对这两种方法进行了基准测试。

了解如何测试和找到解决问题的不同方法,你将在数据科学或任何技术领域更进一步。

相关报告:

志愿者介绍

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181020A0KR8200?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券