python为什么下载是英文版_如何用Python编程下载和解析英文版维基百科

这两标签间的内容(这个title就是维基百科文章标题,text就是文章内容)。SAX能直接让我们实现这样的功能——通过parser和ContentHandler这两个语句来控制信息如何通过解析器然后被处理。每次扫一行XML句子进解析器,Content Handler则帮我们提取相关的信息。

如果你不尝试做一下,可能理解起来有点难度,但是Content handler的思想是寻找开始标签和结束标签之间的内容,将找到的字符添加到缓存中。然后将缓存的内容保存到字典中,其中相应的标签作为对应的键。最后我们得到一个键是标签,值是标签中的内容的字典。下一步,我们会将这个字典传递给另一个函数,它将解析字典中的内容。

我们唯一需要编写的SAX的部分是Content Handler。全文如下:

在这段代码中,我们寻找标签为title和text的标签。每次解析器遇到其中一个时,它会将字符保存到缓存中,直到遇到对应的结束标签()。然后它会保存缓存内容到字典中--  self._values。文章由标签区分,如果Content Handler遇到一个代表结束的 标签,它将添加self._values 到文章列表(self._pages)中。如果感到疑惑了,实践观摩一下可能会有帮助。

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

# Object for handling xmlhandler = WikiXmlHandler()# Parsing objectparser = xml.sax.make_parser()parser.setContentHandler(handler)# Iteratively process filefor line in subprocess.Popen(['bzcat'],                              stdin = open(data_path),                              stdout = subprocess.PIPE).stdout:    parser.feed(line)        # Stop when 3 articles have been found    if len(handler._pages) > 2:        break

如果我们观察 handler._pages,我们将看到一个列表,其中每个元素都是一个包含一篇文章的标题和内容的元组:

handler._pages[0][('Carroll Knicely',  "'''Carroll F. Knicely''' (born c. 1929 in [[Staunton, Virginia]] - died November 2, 2006 in [[Glasgow, Kentucky]]) was [[Editing|editor]] and [[Publishing|publisher]] ...)]

此时,我们已经编写的代码可以成功地识别XML中的文章。现在我们完成了解析文件一半的任务,下一步是处理文章以查找特定页面和信息。再次,我们使用专为这项工作而创建的一个工具。

解析维基百科文章

维基百科运行在一个叫做MediaWiki的软件上,该软件用来构建wiki。这使文章遵循一种标准格式,这种格式可以轻易地用编程方式访问其中的信息。虽然一篇文章的文本看起来可能只是一个字符串,但由于格式的原因,它实际上编码了更多的信息。为了有效地获取这些信息,我们引进了强大的 mwparserfromhell, 一个为处理MediaWiki内容而构建的库。

如果我们将维基百科文章的文本传递给 mwparserfromhell,我们会得到一个Wikicode 对象,它含有许多对数据进行排序的方法。例如,以下代码从文章创建了一个wikicode对象,并检索文章中的 wikilinks()。这些链接指向维基百科的其他文章:

import mwparserfromhell# Create the wiki articlewiki = mwparserfromhell.parse(handler._pages[6][1])# Find the wikilinkswikilinks = [x.title for x in wiki.filter_wikilinks()]wikilinks[:5]['Provo, Utah', 'Wasatch Front', 'Megahertz', 'Contemporary hit radio', 'watt']

有许多有用的方法可以应用于wikicode,例如查找注释或搜索特定的关键字。如果您想获得文章文本的最终修订版本,可以调用:

wiki.strip_code().strip()'KENZ (94.9 FM,  " Power 94.9 " ) is a top 40/CHR radio station broadcasting to Salt Lake City, Utah '

因为我的最终目标是找到所有关于书籍的文章,那么是否有一种方法可以使用解析器来识别某个类别中的文章呢?幸运的是,答案是肯定的——使用MediaWiki templates。

文章模板

模板(templates)是记录信息的标准方法。维基百科上有无数的模板,但与我们的目的最相关的是信息框( Infoboxes)。有些模板编码文章的摘要信息。例如,战争与和平的信息框是:

维基百科上的每一类文章,如电影、书籍或广播电台,都有自己的信息框。在书籍的例子中,信息框模板被命名为Infobox book。同样,wiki对象有一个名为filter_templates()的方法,它允许我们从一篇文章中提取特定的模板。因此,如果我们想知道一篇文章是否是关于一本书的,我们可以通过book信息框去过滤。展示如下:

# Filter article for book templatewiki.filter_templates('Infobox book')

如果匹配成功,那我们就找到一本书了!要查找你感兴趣的文章类别的信息框模板,请参阅信息框列表。

如何将用于解析文章的mwparserfromhell 与我们编写的SAX解析器结合起来?我们修改了Content Handler中的endElement方法,将包含文章标题和文本的值的字典,发送到通过指定模板搜索文章文本的函数中。如果函数找到了我们想要的文章,它会从文章中提取信息,然后返回给handler。首先,我将展示更新后的endElement 。

def endElement(self, name):    """Closing tag of element"""    if name == self._current_tag:        self._values[name] = ' '.join(self._buffer)    if name == 'page':        self._article_count += 1        # Send the page to the process article function        book = process_article(**self._values,                               template = 'Infobox book')        # If article is a book append to the list of books        if book:             self._books.append(book)

一旦解析器到达文章的末尾,我们将文章传递到函数 process_article,如下所示:

def process_article(title, text, timestamp, template = 'Infobox book'):    """Process a wikipedia article looking for template"""      # Create a parsing object    wikicode = mwparserfromhell.parse(text)    # Search through templates for the template    matches = wikicode.filter_templates(matches = template)    if len(matches) >= 1:        # Extract information from infobox        properties = {param.name.strip_code().strip(): param.value.strip_code().strip()                      for param in matches[0].params                      if param.value.strip_code().strip()}        # Extract internal wikilinks

虽然我正在寻找有关书籍的文章,但是这个函数可以用来搜索维基百科上任何类别的文章。只需将模板替换为指定类别的模板(例如 Infobox language是用来寻找语言的),它只会返回符合条件的文章信息。

我们可以在一个文件上测试这个函数和新的ContentHandler 。

Searched through 427481 articles.Found 1426 books in 1055 seconds.

让我们看一下查找一本书的结果:

books[10]['War and Peace', {'name': 'War and Peace',  'author': 'Leo Tolstoy',  'language': 'Russian, with some French',  'country': 'Russia',  'genre': 'Novel (Historical novel)',  'publisher': 'The Russian Messenger (serial)',  'title_orig': 'Война и миръ',  'orig_lang_code': 'ru',  'translator': 'The first translation of War and Peace into English was by American Nathan Haskell Dole, in 1899',  'image': 'Tolstoy - War and Peace - first edition, 1869.jpg',  'caption': 'Front page of War and Peace, first edition, 1869 (Russian)',  'release_date': 'Serialised 1865–1867; book 1869',  'media_type': 'Print',  'pages': '1,225 (first published edition)'}, ['Leo Tolstoy',  'Novel',  'Historical novel',  'The Russian Messenger',  'Serial (publishing)',  'Category:1869 Russian novels',  'Category:Epic novels',  'Category:Novels set in 19th-century Russia',  'Category:Russian novels adapted into films',  'Category:Russian philosophical novels'], ['https://books.google.com/?id=c4HEAN-ti1MC',  'https://www.britannica.com/art/English-literature',  'https://books.google.com/books?id=xf7umXHGDPcC',  'https://books.google.com/?id=E5fotqsglPEC',  'https://books.google.com/?id=9sHebfZIXFAC'], '2018-08-29T02:37:35Z']

对于维基百科上的每一本书,我们把信息框中的信息整理为字典、书籍在维基百科中的wikilinks信息、书籍的外部链接和最新编辑的时间戳。(我把精力集中在这些信息上,为我的下一个项目建立一个图书推荐系统)。你可以修改process_article 函数和WikiXmlHandler类,以查找任何你需要的信息和文章!

如果你看一下只处理一个文件的时间,1055秒,然后乘以55,你会发现处理所有文件的时间超过了15个小时!当然,我们可以在一夜之间运行,但如果可以的话,我不想浪费额外的时间。这就引出了我们将在本项目中介绍的最后一种技术:使用多处理和多线程进行并行化。

并行操作

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

多线程与多处理

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

通常,多线程对于输入/输出绑定任务(例如读取文件或发出请求)更好(更快)。多处理对于cpu密集型任务更好(更快)。对于解析文章的过程,我不确定哪种方法是最优的,因此我再次用不同的参数对这两种方法进行了基准测试。

学习如何进行测试和寻找不同的方法来解决一个问题,你将会在数据科学或任何技术的职业生涯中走得更远。

相关报道:

https://towardsdatascience.com/wikipedia-data-science-working-with-the-worlds-largest-encyclopedia-c08efbac5f5c

【今日机器学习概念】

Have a Great Definition

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值