【问题标题】:Fetch a Wikipedia article with Python使用 Python 获取 Wikipedia 文章
【发布时间】: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 

维基百科似乎阻止了不是来自标准浏览器的请求。

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

【问题讨论】:

  • 维基百科不会阻止来自标准浏览器的请求,它会阻止来自标准库的请求而不更改其用户代理。

标签: python urllib2 user-agent wikipedia http-status-code-403


【解决方案1】:

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

直接来自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()

【讨论】:

【解决方案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”,它对我不起作用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-05-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多