Получите статью из Википедии с помощью Python

Я пытаюсь получить статью из Википедии с помощью urllib Python:

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 

Википедия, похоже, блокирует запросы, поступающие не из стандартного браузера.

Кто-нибудь знает, как это обойти?

Википедия не блокирует запросы не из стандартного браузера, а блокирует запросы из стандартных библиотек без изменения их пользовательского агента.

svick 05.08.2012 12:09
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
40
1
26 498
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Попробуйте изменить заголовок пользовательского агента, который вы отправляете в своем запросе, на что-то вроде: Пользовательский агент: Mozilla / 5.0 (X11; U; Linux i686; en-US; rv: 1.9.0.1) Gecko / 2008072820 Ubuntu / 8.04 (надежный) Firefox / 3.0.1 (Linux Mint)

Вам не нужно олицетворять пользовательский агент браузера; любой пользовательский агент будет работать, только не пустой.

urllib и urllib2 отправляют пользовательский агент

Teifion 23.09.2008 13:58

s/blank/blank or default/ - идея как раз в том, что вы должны каким-то образом идентифицировать своего бота через заголовок пользовательского агента. Вот почему они блокируют стандартный urllib.

njsg 16.02.2012 14:29

Это не решение конкретной проблемы. Но, возможно, вам будет интересно использовать вместо этого библиотеку mwclient (http://botwiki.sno.cc/wiki/Python:Mwclient). Это было бы намного проще. Тем более, что вы напрямую получите содержимое статьи, что избавит вас от необходимости разбирать HTML.

Я сам использовал его в двух проектах, и он работает очень хорошо.

Использование сторонних библиотек для того, что можно легко сделать с помощью встроенных библиотек, в пару строк кода - не лучший совет.

Florian Bösch 23.09.2008 14:18

Поскольку mwclient использует mediawiki api, он не требует синтаксического анализа содержимого. И я предполагаю, что исходному плакату нужен контент, а не необработанный HTML с меню и всем остальным.

Hannes Ovrén 23.09.2008 14:52
Ответ принят как подходящий

Вам необходимо использовать urllib2, который заменяет urllib в библиотека Python std, чтобы изменить пользовательский агент.

Прямо от Примеры

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()

Википедия не зря пытается заблокировать скребки экрана. Их серверам приходится проделать большую работу по преобразованию викикода в HTML, когда есть более простые способы получить содержание статьи. en.wikipedia.org/wiki/…

Cerin 12.08.2010 21:49

Вы не должны пытаться выдавать себя за браузер с помощью пользовательского агента, такого как Mozilla/5.0. Вместо этого вы должны использовать информативный пользовательский агент с некоторой контактной информацией.

svick 05.08.2012 12:08

Общее решение, которое я использую для любого сайта, - это получить доступ к странице с помощью Firefox и, используя расширение, такое как Firebug, записать все детали HTTP-запроса, включая любые файлы cookie.

В своей программе (в данном случае в Python) вы должны попытаться отправить HTTP-запрос, настолько похожий, насколько это необходимо, на тот, который работал в Firefox. Это часто включает настройку полей User-Agent, Referer и Cookie, но могут быть и другие.

Вместо того, чтобы пытаться обмануть Википедию, вам следует подумать об использовании их API высокого уровня.

Что, в свою очередь, по-прежнему будет блокировать запросы от urllib с использованием заголовка пользовательского агента по умолчанию. Таким образом, OP по-прежнему будет иметь ту же проблему, хотя API может быть более простым способом взаимодействия с содержимым вики, в зависимости от того, каковы цели OP.

njsg 16.02.2012 14:26

У меня они работают нормально. Разве они не работают на вас? Пример: en.wikipedia.org/w/… или en.wikipedia.org/w/…

sligocki 23.02.2012 00:35

Если вы пытаетесь получить доступ к содержимому Википедии (и не нуждаетесь в какой-либо конкретной информации о самой странице), вместо использования api вы должны просто вызвать index.php с помощью 'action = raw', чтобы получить викитекст, например в:

'http://en.wikipedia.org/w/index.php?действие = сырье&title=Main_Page'

Или, если вам нужен HTML-код, используйте 'action = render', как в:

"http://en.wikipedia.org/w/index.php?действие = визуализация&title=Main_Page"

Вы также можете определить раздел, чтобы получить только часть контента, с чем-то вроде 'section = 3'.

Затем вы можете получить к нему доступ с помощью модуля urllib2 (как указано в выбранном ответе). Однако, если вам нужна информация о самой странице (например, версии), вам лучше использовать mwclient, как предложено выше.

Обратитесь к Часто задаваемые вопросы MediaWiki, если вам нужна дополнительная информация.

привет, если я не знаю номер раздела как 3, но я знаю, что заголовок раздела - «Существительное», как получить этот конкретный раздел?

Lenin Raj Rajasekaran 23.02.2011 17:06

import urllib
s = urllib.urlopen('http://en.wikipedia.org/w/index.php?action=raw&title=Albert_Einstein').read()

Кажется, это работает для меня без изменения пользовательского агента. Без "action = raw" у меня не работает.

requests - это круто!

Вот как вы можете получить HTML-контент с помощью requests:

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

Сделанный!

Запрос страницы с помощью ?printable=yes дает вам полностью относительно чистый HTML-документ. ?action=render дает вам только основной HTML. Запрос на синтаксический анализ страницы через API действий MediaWiki с помощью action=parse также дает вам только основной HTML-код, но было бы хорошо, если вы хотите более точный контроль, см. справку по parse API.

Если вам просто нужен HTML-код страницы, чтобы вы могли его отобразить, быстрее и лучше будет использовать новый RESTBase API, который возвращает кешированное HTML-представление страницы. В этом случае https://en.wikipedia.org/api/rest_v1/page/html/Albert_Einstein.

По состоянию на ноябрь 2015 года вам не нужно устанавливать свой пользовательский агент, а только это настоятельно рекомендуется. Кроме того, почти все вики Викимедиа - это требуется HTTPS, поэтому избегайте перенаправления 301 и выполняйте запросы https.

Другие вопросы по теме