python3-urllib_Handler_1
    :Python 3.7
    :http://httpbin.org
  전술한
보통 링크 를 요청 하 는 python 코드 작성 방법 은:
import requests
url = "http://httpbin.org/get"
res = requests.get(url)
print(res.content)
  실행 후 다음 과 같은 결 과 를 얻 을 수 있 습 니 다.
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0"
  },
  "origin": "x.x.x.x, x.x.x.x",
  "url": "https://httpbin.org/get"
}
  그러나 우 리 는 제3자 요청 라 이브 러 리
requests 을 사용 할 생각 이 없 기 때문에 urllib 라 이브 러 리 의 실현 버 전 은 다음 과 같 습 니 다. 얻 은 결 과 는 기본 적 인 User-Agent 필드 가 urllib 으로 바 뀌 었 습 니 다.import urllib.request as urlreq
url = "http://httpbin.org/get"
res = urlreq.urlopen(url)
print(res.read().decode('utf-8'))
  현재 모든 OK. 만약 에 우리 가 대리 IP 를 사용 하여 요 구 를 하려 고 한다 면
urllib 의 기본 적 인 요구 방식 은 만족 할 수 없 기 때문에 opener 과 Handler 의 용법 을 도입 했다.import urllib.request as urlreq
url = "http://httpbin.org/get"
proxy = {'http':'112.87.68.202:9999'}#              IP
proxyhandler = urlreq.ProxyHandler(proxies=proxy)
opener = urlreq.build_opener(proxyhandler)
res = opener.open(url)
print(res.read().decode('utf-8'))
  orgin 필드 가 우리 가 사용 하 는 프 록 시 IP 의 주소 가 되 었 음 을 발견 할 수 있 습 니 다.
  "origin": "112.87.68.202, 112.87.68.202",
  urllib 라 이브 러 리 자체 가 Handler 를 실현 했다. 예 를 들 어 위 에서 사용 한 ProxyHandler 이다. 그러나 기능 적 인 수 요 는 사람 에 따라 다르다. 예 를 들 어 나 는 특정한 링크 를 요청 할 때 이 과정 에서 세 번 만 방향 을 바 꾸 고 이 세 번 의 방향 을 바 꾸 는 것 은 매번 user - agent 가 다르다.그러면 모듈 이 제공 한 handler 는 이러한 기능 을 만족 시 킬 수 없습니다. 사용자 정의 Handler 가 필요 합 니 다.본문
part-1
앞의 요청 예 에서 user - agent 필드 는 모듈 의 기본 필드 로 브 라 우 저 에 있 는 user - agent 처럼 보이 지 않 습 니 다. 간단 한 python 코드 는:
import requests
url = '...'
headers = {"User-Agent":"......"}
res = requests.get(url,headers=headers)
  혹은
import urllib.request as urlreq
url = '...'
headers = {"User-Agent":'.....'}
req = urlreq.Request(url,headers=headers)
res = urlreq.urlopen(req)
  사용자 정의 Handler 버 전이 라면:
from fake_useragent import UserAgent
import urllib.request as request
ua = UserAgent()
url = 'http://httpbin.org/get'
class HeaderHandler(request.BaseHandler):
    def __init__(self,headers=None):
        if headers is None:
            headers = ua.random
        self.headers = headers
        
    def http_request(self,req):
        req.headers['User-Agent'] = self.headers
        return req
    https_request = http_request
#   handler  *****************
proxyhandler = request.ProxyHandler(proxies={'http':'163.204.242.73:9999'})
headerhandler = HeaderHandler()
handlers = [proxyhandler,headerhandler]
opener = request.build_opener(*handlers)
req_2  = request.Request(url)
res_2 = opener.open(req_2)
print(res_2.read().decode('utf-8'))
  이 예 는 분명히 앞의 두 가지 실현 방식 보다 복잡 하고 큰 인재 가 적 게 사용 되 지만 더욱 복잡 한 기능 수요 라면 그의 맞 춤 형 화 는 그 강 함 을 보 여 준다.
fake_useragent 을 도 입 했 는데 이 모듈 은 주로 user-agent 필드 를 제공 하 는 데 사용 되 고 독 자 는 user-agent 필드 를 직접 복사 할 수 있다. proxyhandler 과 headerhandler 을 중첩 하여 사용 하 였 으 며, 하 나 는 IP 프 록 시 기능 을 완성 하 였 으 며, 하 나 는 요청 헤드 필드 의 수정 을 완성 하 였 다. HTTPRedirectHandler) 를 바탕 으로 이 루어 지 려 면 BaseHandler
BaseHandler 가 제공 하 는 몇 가지 함수 의 기능 은 Scrapy 파충류 프레임 의 중간 부품 이 이 를 바탕 으로 이 루어 졌 는 지 를 연상 할 수 밖 에 없다.하위 클래스 화 를 고려 하기 전에 Opener, 즉 Opener Director 대상 이 url 또는 Request 대상 을 처리 할 때 겪 는 세 가지 시 기 를 알 아야 합 니 다.
     에 두 개 있 습 니 다) 에 따라 그들의 protocol 을 순서대로 호출 합 니 다.request () 방법, 여기 protocol 은 http 또는 https 를 말 합 니 다. 예 를 들 어 재 작성 함 수 는 http 입 니 다.request()。이 방법 은 Request 대상 을 받 아들 이 고 Request 대상 을 되 돌려 줍 니 다. 이 대상 은 다음 Handler 의 protocol 에 게 계속 전 달 됩 니 다.request 방법 가공 또는 기타 조작.다음 코드 예 는 리 셋 횟수 를 제한 하 는 기능 을 실 현 했 고 테스트 사 이 트 는 requests 라 이브 러 리 작성 자의 또 다른 오픈 소스 항목 을 사용 합 니 다.http://httpbin.org사이트 에서 테스트 방향 을 바 꾸 는 기능 을 제공 합 니 다. 여기 서 의 용법 은?
http://httpbin.org/absolute-redirect/{n}
  n,                  ,     3 , 
http://httpbin.org/absolute-redirect/3
  
 여기 서 저 는 첫 번 째 예 처럼 기본 클래스 인 BaseHandler 를 계승 하지 않 고 하위 클래스 인 HTTP Redirect Handler 를 계승 하여 그 중의 소스 코드 를 직접 복사 하여 수정 합 니 다.그럼 왜 이렇게 고 쳐 야 되 는 지 알 았 죠?import urllib.request as urlreq
from urllib.error import HTTPError
from urllib.parse import urlencode
class RedirectTimesOutError(Exception):
    def __init__(self,expression,message):
        self.expression = expression
        self.message = message
class RedirectError(Exception):
    def __init__(self,expression,message):
        self.expression = expression
        self.message = message
class MyHTTPRedirectHandler(urlreq.HTTPRedirectHandler):
    def __init__(self,timeslimit=3):
        self.limit = timeslimit
        self.flag = 1
    def redirect_request(self,req,fp,code,msg,headers,newurl):
        m = req.get_method()
        if (code != 302) and (m != 'GET'):
            raise RedirectError('','Must 302 redirect from GET Method')
            # raise HTTPError(req.full_url,code,msg,headers,fp)
        
        print('newurl:',newurl)
        print('-'*8)
        newurl = newurl.replace(' ','%20')
        CONTENT_HEADERS = ("content-length","content-type")
        newheaders = {k:v for k,v in req.headers.items()
                        if k.lower() not in CONTENT_HEADERS}
 
        if self.flag > self.limit:
        	self.flag = 1
            raise RedirectTimesOutError(expression='32',message='Redirect times out!')
        else:
            self.flag +=1
        return urlreq.Request(newurl,
                       headers=newheaders,
                       origin_req_host=req.origin_req_host,
                       unverifiable=True)
    # def http_error_302(self,req,fp,code,msg,hdrs):
    #     print('call here')
    #     pass
url = 'http://httpbin.org/absolute-redirect/4' #GET  
data = None
myhandler = MyHTTPRedirectHandler(4)
opener = urlreq.build_opener(myhandler)
try:
    res_2 = opener.open(url,data=data)
except RedirectTimesOutError as e:
    print(e.message)
else:
    print(res_2.getcode())
    # print(res_2.read().decode('utf-8'))
  코드 는 원본 url lib 모듈 의 request. py 파일 의 HTTP Redirect Handler 류 의 redirect 를 복사 합 니 다.request 함수, 그리고 부분 수정:
self.limit 값 을 설정 함으로써 한 링크 의 방문 중간 에 몇 번 의 리 셋 이 허용 되 는 지 제한 하고 self.flag 기록 을 이용 하여 몇 번 째 리 셋 을 처리 하 며 마지막 으로 이상 을 던 지기 전에 self.flag 값 을 리 셋 해 야 한다. 그렇지 않 으 면 이 Handler 가 새로운 요청 의 리 셋 을 계속 처리 할 때 이전 요청 에 방 해 를 받는다.공식 API 에서 이 Handler 에 대한 설명 이 있 습 니 다.
HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl)
Return a Request or None in response to a redirect.
This is called by the default implementations of the http_error_30*() methods when a redirection is received from the server.  If a redirection should take place, return a new Request to allow http_error_30*() to perform the redirect to newurl. Otherwise, raise HTTPError if no other handler should try to handle this URL, or return None if you can’t but another handler might. 이 말 에는 주로 이런 두 가지 정보 가 있다.
redirect_request 함 수 는 재 설정 을 처리 하 는 데 사 용 됩 니 다. 이 Handler 가 이 재 설정 을 처리 할 수 있다 면 Request 대상 으로 돌아 갑 니 다.만약 이 Handler 가 할 수 없다 면, None 로 돌아 가 처리 권 을 다음 Handler 로 넘 깁 니 다. http_error_30* 함 수 를 먼저 촉발 합 니 다. 이 함 수 는 redirect_request 함 수 를 촉발 하여 처리 합 니 다. http_error_30* 을 실 현 했 기 때문에 우리 위의 예 는 이 방법 을 실현 하지 못 했 지만 왜 촉발 되 었 고 시스템 의 기본 처리 방안 보다 우선 시 되 었 습 니까?http_error_30* 을 달성 했다 면 집행 순 서 는 어떻게 될 까?이 문제 들 은 다음 Handler 의 주제 에서 해석 되 는데, 여기에 소스 코드 를 결합 하여 그 행 위 를 해석 해 야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.