Помилка HTTP 403 у Python 3 Web Scraping


100

Я намагався скасувати веб-сайт для практики, але продовжував отримувати помилку HTTP 403 (чи вважає мене, що я бот)?

Ось мій код:

#import requests
import urllib.request
from bs4 import BeautifulSoup
#from urllib import urlopen
import re

webpage = urllib.request.urlopen('http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1').read
findrows = re.compile('<tr class="- banding(?:On|Off)>(.*?)</tr>')
findlink = re.compile('<a href =">(.*)</a>')

row_array = re.findall(findrows, webpage)
links = re.finall(findlink, webpate)

print(len(row_array))

iterator = []

Я отримую помилку:

 File "C:\Python33\lib\urllib\request.py", line 160, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python33\lib\urllib\request.py", line 479, in open
    response = meth(req, response)
  File "C:\Python33\lib\urllib\request.py", line 591, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python33\lib\urllib\request.py", line 517, in error
    return self._call_chain(*args)
  File "C:\Python33\lib\urllib\request.py", line 451, in _call_chain
    result = func(*args)
  File "C:\Python33\lib\urllib\request.py", line 599, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

Відповіді:


209

Можливо, це пов’язано з mod_securityякоюсь подібною функцією безпеки сервера, яка блокує відомі користувацькі агенти павуків / ботів ( urllibвикористовує щось на зразок python urllib/3.3.0, це легко виявити). Спробуйте встановити відомий користувацький агент браузера за допомогою:

from urllib.request import Request, urlopen

req = Request('http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1', headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()

Це працює для мене.

До речі, у вашому коді вам не вистачає ()після .readв urlopenрядку, але я думаю, що це друкарська помилка.

ПОРАДА: оскільки це вправа, виберіть інший, не обмежуючий сайт. Можливо, вони urllibчомусь блокують ...


Я припускаю, що безпечно повторно використовувати reqдля кількох urlopenдзвінків.
Прозріння

Це може бути трохи пізно, але я вже маю User-Agent у своєму коді, все ще це дає меніError 404: Access denied
Reema Parakh

Це працює, але я відчуваю, що вони повинні мати
поважну

39

Безумовно, це блокується через використання urllib на основі агента користувача. Те саме відбувається зі мною з OfferUp. Ви можете створити новий клас під назвою AppURLopener, який замінює агент користувача за допомогою Mozilla.

import urllib.request

class AppURLopener(urllib.request.FancyURLopener):
    version = "Mozilla/5.0"

opener = AppURLopener()
response = opener.open('http://httpbin.org/user-agent')

Джерело


2
Найважливіша відповідь для мене не спрацювала, тоді як ваша. Дуже дякую!
Тарун Удай

Це працює чудово, але мені потрібно приєднати до цього конфігурацію ssl. Як це зробити? До того, як я просто додав його як другий параметр (urlopen (запит, контекст = ctx))
Хоке

2
схоже, що він відкрився, але там написано "ValueError: читання закритого файлу"
Martian2049,

@zeta Як вам вдалося зішкребти OfferUp та надати необхідні геокоординати для здійснення пошуку за сценарієм?
CJ Travis

@CJTravis, я не шарував OfferUp. Я просто отримував значення елементів на основі точної URL-адреси товару. Для цього мені не потрібні географічні координати
зета

13

"Це, мабуть, через mod_security або якусь подібну функцію захисту сервера, яка блокує відомі

павук / бот

користувацькі агенти (urllib використовує щось на зразок python urllib / 3.3.0, це легко виявити) "- як уже згадував Стефано Санфіліппо

from urllib.request import Request, urlopen
url="https://stackoverflow.com/search?q=html+error+403"
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})

web_byte = urlopen(req).read()

webpage = web_byte.decode('utf-8')

Web_byte є об'єктом байт , що повертається сервером і типу контенту в даний час веб - сторінці в основному UTF-8 . Тому вам потрібно декодувати web_byte методом декодування.

Це вирішує повну проблему, коли я намагався видалити з веб-сайту за допомогою PyCharm

PS -> Я використовую python 3.4


2

На основі попередньої відповіді,

from urllib.request import Request, urlopen       
#specify url
url = 'https://xyz/xyz'
req = Request(url, headers={'User-Agent': 'XYZ/3.0'})
response = urlopen(req, timeout=20).read()

Це спрацювало для мене, продовживши час очікування.


1

Оскільки сторінка працює у браузері, а не під час викликів у програмі python, здається, що веб-програма, яка обслуговує цю URL-адресу, розпізнає, що ви вимагаєте вміст не браузером.

Демонстрація:

curl --dump-header r.txt http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1

...
<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
You don't have permission to access ...
</HTML>

а вміст у r.txt має рядок стану:

HTTP/1.1 403 Forbidden

Спробуйте опублікувати заголовок "User-Agent", який підробляє веб-клієнта.

ПРИМІТКА . Сторінка містить виклик Ajax, який створює таблицю, яку ви, ймовірно, хочете проаналізувати. Вам потрібно буде перевірити логіку сторінки на сторінці javascript або просто за допомогою налагоджувача браузера (наприклад, на вкладці Firebug / Net) побачити, яку URL-адресу потрібно викликати, щоб отримати вміст таблиці.


1

Спробувати можна двома способами. Деталі - за цим посиланням .

1) Через піп

pip install --upgrade certifi

2) Якщо це не працює, спробуйте запустити команду Cerificates.com, яка постачається в комплекті з Python 3. * для Mac: (Перейдіть до місця встановлення python і двічі клацніть файл)

відкрийте / Applications / Python \ 3.. * / Install \ Certificates.command


0

Якщо ви відчуваєте провину за фальсифікацію агента користувача як Mozilla (коментар у верхній відповіді від Stefano), це може працювати і з не-urllib User-Agent. Це спрацювало для сайтів, на які я посилаюся:

    req = urlrequest.Request(link, headers={'User-Agent': 'XYZ/3.0'})
    urlrequest.urlopen(req, timeout=10).read()

Моя заявка - перевірити валідність, зішкребавши конкретні посилання, на які я посилаюся, у своїх статтях. Не загальний скребок.


0

На підставі попередніх відповідей, це працювало для мене з Python 3.7

from urllib.request import Request, urlopen

req = Request('Url_Link', headers={'User-Agent': 'XYZ/3.0'})
webpage = urlopen(req, timeout=10).read()

print(webpage)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.