使用 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