Lỗi HTTP 403 trong Python 3 Web Scraping


100

Tôi đang cố gắng loại bỏ một trang web để thực hành, nhưng tôi vẫn nhận được Lỗi HTTP 403 (nó có nghĩ rằng tôi là một bot) không?

Đây là mã của tôi:

#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 = []

Lỗi tôi nhận được là:

 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

Câu trả lời:


205

Điều này có thể là do mod_securityhoặc một số tính năng bảo mật máy chủ tương tự chặn các tác nhân người dùng spider / bot đã biết ( urllibsử dụng một cái gì đó như python urllib/3.3.0, nó dễ dàng bị phát hiện). Thử đặt tác nhân người dùng trình duyệt đã biết với:

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

Điều này làm việc cho tôi.

Nhân tiện, trong mã của bạn, bạn thiếu phần ()sau .readurlopendòng, nhưng tôi nghĩ rằng đó là lỗi đánh máy.

MẸO: vì đây là bài tập, hãy chọn một trang khác, không hạn chế. Có thể họ đang chặn urllibvì lý do nào đó ...


Tôi cho rằng nó an toàn để sử dụng lại reqcho nhiều urlopencuộc gọi.
Acumenus

Nó có thể là hơi muộn, nhưng tôi đã có User-Agent trong mã của tôi, nó vẫn mang lại cho tôiError 404: Access denied
Reema Parakh

Điều này hoạt động nhưng tôi cảm thấy như họ phải có lý do chính đáng để chặn bot và tôi đang vi phạm điều khoản dịch vụ của họ
xjcl 11/10 '19

39

Chắc chắn nó bị chặn do việc bạn sử dụng urllib dựa trên tác nhân người dùng. Điều tương tự cũng đang xảy ra với tôi với OfferUp. Bạn có thể tạo một lớp mới có tên là AppURLopener, lớp này sẽ ghi đè tác nhân người dùng với Mozilla.

import urllib.request

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

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

Nguồn


2
Câu trả lời hàng đầu không phù hợp với tôi, trong khi câu trả lời của bạn thì có. Cảm ơn rất nhiều!
Tarun Uday,

Điều này hoạt động tốt nhưng tôi cần phải đính kèm cấu hình ssl cho điều này. Làm thế nào để tôi làm điều này? Trước khi tôi chỉ thêm nó làm tham số thứ hai (urlopen (yêu cầu, ngữ cảnh = ctx))
Hauke

2
trông giống như nó đã mở nhưng nó nói 'ValueError: đọc file kín'
Martian2049

@zeta Bạn đã quản lý như thế nào để loại bỏ OfferUp và cung cấp tọa độ địa lý cần thiết để thực hiện tìm kiếm từ tập lệnh?
CJ Travis

@CJTravis, tôi không bỏ qua OfferUp. Tôi chỉ truy xuất giá trị mặt hàng dựa trên URL chính xác của mặt hàng. Mà không yêu cầu bất kỳ tọa độ địa lý cho tôi
zeta

13

"Điều này có thể là do mod_security hoặc một số tính năng bảo mật máy chủ tương tự chặn

nhện / bot

tác nhân người dùng (urllib sử dụng thứ gì đó như python urllib / 3.3.0, nó dễ dàng bị phát hiện) "- như đã được đề cập bởi Stefano Sanfilippo

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

Các web_byte là một đối tượng byte trả về bởi máy chủ và loại hiện nội dung trong trang web chủ yếu là utf-8 . Do đó bạn cần giải mã web_byte bằng phương pháp giải mã.

Điều này giải quyết hoàn toàn sự cố trong khi tôi đang cố gắng tìm kiếm từ một trang web bằng PyCharm

PS -> Tôi sử dụng python 3.4


1

Vì trang hoạt động trong trình duyệt chứ không phải khi gọi trong chương trình python, có vẻ như ứng dụng web phân phối url đó nhận ra rằng bạn yêu cầu nội dung không phải bởi trình duyệt.

Trình diễn:

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>

và nội dung trong r.txt có dòng trạng thái:

HTTP/1.1 403 Forbidden

Thử đăng tiêu đề 'Tác nhân người dùng' giả mạo ứng dụng khách web.

LƯU Ý: Trang chứa lệnh gọi Ajax tạo bảng mà bạn có thể muốn phân tích cú pháp. Bạn sẽ cần kiểm tra logic javascript của trang hoặc đơn giản là sử dụng trình gỡ lỗi trình duyệt (như tab Firebug / Net) để xem bạn cần gọi url nào để lấy nội dung của bảng.


1

Bạn có thể thử theo hai cách. Chi tiết có trong liên kết này .

1) Qua pip

cài đặt pip - nâng cấp chứng chỉ

2) Nếu nó không hoạt động, hãy thử chạy một lệnh Cerificates.com đi kèm với Python 3. * dành cho Mac: (Đi tới vị trí cài đặt python của bạn và nhấp đúp vào tệp)

open / Applications / Python \ 3. * / Install \ Certificates.command


1

Dựa trên câu trả lời trước,

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

Điều này đã làm việc cho tôi bằng cách kéo dài thời gian chờ.


0

Nếu bạn cảm thấy tội lỗi khi giả mạo tác nhân người dùng là Mozilla (bình luận trong câu trả lời hàng đầu từ Stefano), nó cũng có thể hoạt động với Tác nhân người dùng không phải urllib. Điều này đã làm việc cho các trang web tôi tham khảo:

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

Ứng dụng của tôi là kiểm tra tính hợp lệ bằng cách cạo các liên kết cụ thể mà tôi tham khảo, trong các bài báo của tôi. Không phải là một máy quét chung chung.


0

Dựa trên các câu trả lời trước, điều này đã hoạt động với tôi với 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.