使用 Python 获取 Wikipedia 文章

Posted

技术标签:

【中文标题】使用 Python 获取 Wikipedia 文章【英文标题】:Fetch a Wikipedia article with Python 【发布时间】:2010-09-12 07:31:59 【问题描述】:

我尝试使用 Python 的 urllib 获取 Wikipedia 文章:

f = urllib.urlopen("http://en.wikipedia.org/w/index.php?title=Albert_Einstein&printable=yes")           
s = f.read()
f.close()

但是,我得到以下响应而不是 html 页面:错误 - 维基媒体基金会:

Request: GET http://en.wikipedia.org/w/index.php?title=Albert_Einstein&printable=yes, from 192.35.17.11 via knsq1.knams.wikimedia.org (squid/2.6.STABLE21) to ()
Error: ERR_ACCESS_DENIED, errno [No Error] at Tue, 23 Sep 2008 09:09:08 GMT 

***似乎阻止了不是来自标准浏览器的请求。

有人知道如何解决这个问题吗?

【问题讨论】:

***不会阻止来自标准浏览器的请求,它会阻止来自标准库的请求而不更改其用户代理。 【参考方案1】:

您需要使用在python std library 中取代urllib 的urllib2 来更改用户代理。

直接来自examples

import urllib2
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
infile = opener.open('http://en.wikipedia.org/w/index.php?title=Albert_Einstein&printable=yes')
page = infile.read()

【讨论】:

***试图阻止屏幕抓取工具是有原因的。当有更简单的方法来获取文章内容时,他们的服务器必须做很多工作才能将 wikicode 转换为 HTML。 en.wikipedia.org/wiki/… 您不应该尝试使用像Mozilla/5.0 这样的用户代理来模拟浏览器。相反,you should use an informative user agent with some contact information.【参考方案2】:

这不是针对特定问题的解决方案。但是,您可能会觉得使用 mwclient 库 (http://botwiki.sno.cc/wiki/Python:Mwclient) 会很有趣。那会容易得多。特别是因为您将直接获取文章内容,从而无需您解析 html。

我自己用过两个项目,效果很好。

【讨论】:

使用第三方库可以通过几行代码轻松完成内置库,这不是一个好建议。 由于 mwclient 使用 mediawiki api,它不需要解析内容。而且我猜原始海报想要内容,而不是带有菜单和所有内容的原始 html。【参考方案3】:

与其试图欺骗***,不如考虑使用他们的High-Level API。

【讨论】:

这反过来仍然会使用库默认的用户代理标头阻止来自urllib 的请求。所以 OP 仍然会遇到同样的问题,尽管 API 可能是一种更简单的方式来连接 wiki 内容,这取决于 OP 的目标是什么。 它们对我来说很好用。他们不为你工作吗?例如:en.wikipedia.org/w/… 或 en.wikipedia.org/w/…【参考方案4】:

如果您尝试访问 Wikipedia 内容(并且不需要有关页面本身的任何特定信息),您应该只使用 'action=raw' 调用 index.php 来获取wikitext,例如:

'http://en.wikipedia.org/w/index.php?action=raw&title=Main_Page'

或者,如果您想要 HTML 代码,请使用 'action=render',如下所示:

'http://en.wikipedia.org/w/index.php?action=render&title=Main_Page'

您还可以定义一个部分来获取部分内容,例如“section=3”。

然后您可以使用 urllib2 模块访问它(如所选答案中所建议的那样)。 但是,如果您需要有关页面本身的信息(例如修订),您最好使用上面建议的 mwclient。

如果您需要更多信息,请参阅MediaWiki's FAQ。

【讨论】:

您好,如果我不知道节编号为 3,但我知道节标题为“名词”,如何获取该特定节?【参考方案5】:

我对任何网站使用的一般解决方案是使用 Firefox 访问该页面,并使用 Firebug 等扩展程序记录 HTTP 请求的所有详细信息,包括任何 cookie。

在您的程序中(在本例中为 Python),您应该尝试发送一个与 Firefox 类似的 HTTP 请求。这通常包括设置 User-Agent、Referer 和 Cookie 字段,但可能还有其他字段。

【讨论】:

【参考方案6】:

requests 太棒了!

以下是使用requests 获取html 内容的方法:

import requests
html = requests.get('http://en.wikipedia.org/w/index.php?title=Albert_Einstein&printable=yes').text

完成!

【讨论】:

【参考方案7】:

尝试将您在请求中发送的用户代理标头更改为: 用户代理:Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008072820 Ubuntu/8.04 (hardy) Firefox/3.0.1 (Linux Mint)

【讨论】:

【参考方案8】:

您无需模拟浏览器用户代理;任何用户代理都可以工作,而不是空白。

【讨论】:

urllib 和 urllib2 都发送一个用户代理 s/blank/blank or default/ — 这个想法正是您应该通过用户代理标头以某种方式识别您的机器人。这就是他们阻止urllib 默认的原因。【参考方案9】:

使用?printable=yes 请求页面会给你一个完整的相对干净的HTML 文档。 ?action=render 只为您提供正文 HTML。使用 action=parse 请求通过 MediaWiki 操作 API 解析页面同样只为您提供正文 HTML,但如果您想要更好的控制,see parse API help 会很好。

如果您只想要页面 HTML 以便可以呈现它,那么使用新的RESTBase API 会更快更好,它会返回页面的缓存 HTML 表示。在这种情况下,https://en.wikipedia.org/api/rest_v1/page/html/Albert_Einstein。

自 2015 年 11 月起,您无需设置用户代理,而是设置 it's strongly encouraged。此外,几乎所有 Wikimedia wiki require HTTPS,因此请避免 301 重定向并发出 https 请求。

【讨论】:

【参考方案10】:
import urllib
s = urllib.urlopen('http://en.wikipedia.org/w/index.php?action=raw&title=Albert_Einstein').read()

这似乎对我有用,而无需更改用户代理。没有“action=raw”,它对我不起作用。

【讨论】:

以上是关于使用 Python 获取 Wikipedia 文章的主要内容,如果未能解决你的问题,请参考以下文章

使用 Wikipedia API 获取特定时间范围内阅读次数最多的文章?

如何使用Wikipedia的API获取Wikipedia内容?

Android Wikipedia 文章搜索无法在我的 web 视图中正确显示?

wikipedia 维基百科 语料 获取 与 提取 处理 by python3.5

从 Wikipedia 获取随机摘录(Javascript,仅限客户端)

从 Wikipedia 获取随机摘录(Javascript,仅限客户端)