2014-12-11 2 views
0

많은 사이트를 거쳐 구문 분석해야하는 Python 프로젝트가 있습니다.파이썬 요청 라이브러리가 때때로 브라우저가 열 수있는 사이트를 열지 못합니다.

여러 사례를 통해 requests은 Chrome 및 FF에서 사이트가 제대로 열리지 만 사이트 콘텐츠를 제대로 가져 오지 못하는 것으로 나타났습니다. 예를 들어, 내 코드 : 이후

def get_site_content(site): 
    try : 
     content = requests.get(site, allow_redirects = True) 
     content = content.text 
    except Exception as e: 
     if DEBUG : 
      print type(e) 
      print e.args 
      print e 
     global errors 
     errors += 1 
     return '' 

    soup = BeautifulSoup(content) 
    # parse, tokenize and filter the content of the site 
    [...] 
    return tokenized_content 

, 나는 사이트 콘텐츠가 '' 있는지 확인을한다. 그렇다면 오류가 발생했으며 그 사이트를로드하는 데 실패했음을 나타냅니다. 내 로그에서

:

내가 파이썬 쉘에서 동일한 코드를 실행하면

Progress: [=========-] 1.8% Failed to load site : http://www.mocospace.com 
[...] 
Progress: [=========-] 87.8% Failed to load site : http://www.hotchalk.com 
Progress: [=========-] 93.2% Failed to load site : http://Hollywire.com 
Progress: [=========-] 93.8% Failed to load site : http://www.Allplaybook.com 
그러나 :

$ python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import requests 
>>> content = requests.get("http://www.mocospace.com", allow_redirects=True) 
>>> content 
<Response [200]> 
>>> content.text 
u'<?xml version="1.0" encoding="utf-8"?>\r\n<!DOCTYPE html PUBLIC [...] 

내가 403을받을 경우에, 그것은 여전히 ​​예외가 아니다 - 그것이 있어야한다.

# data is a list of all urls together with their category 
for row in data: 
    content = get_site_content(row['URL']) 

    if content : 
     classifier_data.append((content, row['Category'])) 
    else : 
     print "Failed to load site : %s" % row['URL'] 

이 동작은 아마도 무엇을 발생할 수 있습니다 : 예외가 get_site_content()''을 반환 제기 된 경우

>>> content = requests.get("http://www.hotchalk.com", allow_redirects=True) 
>>> content 
<Response [403]> 
>>> content.text 
u'<html>\r\n<head><title>403 Forbidden</title></head>\r\n<body bgcolor="white">\r\n<center><h1>403 Forbidden</h1></center>\r\n<hr><center>nginx</center>\r\n</body>\r\n</html>\r\n' 

가 로딩이 실패 말할 로그의 유일한 방법은? 이 C면, 포인터 및 정의되지 않은 동작이 관련된 뭔가 찾고있을 줄 알았는데 아무것도 비슷한 여기에 발생할 수 찾을 수없는 것.


편집 :

는 robotparser 모듈을 사용하여, 나는 one of the above sites'robots.txt 파일을 검사 시도 User-agent: *가 맨 위에 설정되어 있다고 지적했다. 그렇지 않으면 색인 페이지에 액세스 할 수없는 항목이 표시되지 않으므로 다른 이유로 인해 발생할 수 있습니까? 파이썬 쉘에서

: 서버가 응답을 보낼 때 기본적으로

>>> import robotparser 
>>> rp = robotparser.RobotFileParser() 
>>> rp = robotparser.RobotFileParser() 
>>> rp.set_url("http://www.mocospace.com/robots.txt") 
>>> rp.read() 
>>> rp.can_fetch("*", "http://www.mocospace.com") 
True 
+2

사이트는 요청의 내용에 따라 행동을 자유롭게 변경할 수 있으며, 종종 그렇게합니다. 브라우저가'requests'와 다른 헤더 집합을 보냅니다. 일반적인 범인은'User-Agent' 헤더이지만'Referrer'와'Accept'와 같은 다른 헤더도 꽤 자주 포함됩니다. 이것은'requests' *의 버그가 아닙니다. –

+0

아, 위키 백과 항목에 대한 요청에서 내가 그런 것을 실제로 발견했다고 언급하는 것을 잊었습니다. 이 경우,'(..., headers = 'User-Agent': 'SomeAgent 1.0')'필드를 추가적으로 제공해야합니까, 아니면 헤더에서 예상되는 다른 모든 필드도 포함해야합니까? – user991710

+0

'headers' 매개 변수는 사전입니다. 당신은'headers = { 'User-Agent': 'SomeAgent 1.0'}'을 시도 할 수 있지만 원치 않는 로봇 스파이더를 시도하고 제거하기 위해 사용자 에이전트를 필터링하는 사이트를 고려해야합니다. 'robots.txt' 사이트를 읽고 요청한 정책을 존중하십시오. –

답변

1

, requests는 예외를 발생시키지 않습니다. 당신이 4XX 또는 5XX 응답 코드에 대한 예외를 발생하는 requests을 원하는 경우에, 당신은 명시 적으로 그렇게하도록 지시해야합니다

response = requests.get(site, allow_redirects = True) 
response.raise_for_status() 
content = response.text 

또는이 response.status_code 속성을 검사하고 당신의 행동이 값을 기준으로 변경합니다. 빠른 시작의 Response Status Codes도 참조하십시오.

requests으로 전화 할 때 다르게 작동하는 사이트는 다음과 같습니다. HTTP 서버는 본질적으로 검은 상자임을 기억하십시오. HTTP RFC를 사용하면 원하는대로 응답 할 수 있습니다. 여기에는 헤더에서의 필터링과 요청에 따라 모든 내용이 포함 된 동작 (무작위 응답 포함)이 포함됩니다.

브라우저가 requests과 다른 헤더 세트를 전송합니다. 일반적인 범인은 User-Agent 헤더이지만 ReferrerAccept과 같은 다른 헤더도 꽤 자주 포함됩니다. 이 requests의 버그가 아닙니다.

각 사이트 구성에 따라 달라집니다. User-Agent과 같은 추가 헤더를 설정하여 데스크톱 브라우저를 스푸핑 할 수는 있지만 모든 사이트에서 이러한 동작을 환영하지는 않는다는 점을 고려해야합니다. 사이트를 스파이더 링하는 경우 /robots.txt 정책을 준수하고 은 요청하지 않는 스파이더 사이트가 아닌입니다. 이 프로세스를 자동화하려면 Python과 함께 제공되는 robotparser module을 사용할 수 있습니다.

headers = {'User-Agent': 'FooBar-Spider 1.0'} 
response = requests.get(site, headers=headers) 

을하지만 사이트가 명확하게 거미하지를 묻는 경우 다시 스푸핑 브라우저의 사용자 에이전트 문자열을하지 마십시오

당신은 requests.get()headers 인수를 추가 헤더를 설정할 수 있습니다.

+0

예, 알고 있습니다. 저의 말은 약간 나빴습니다. 예외를 발생시키지 않고 대신 상태 코드를 돌려 줄 것을 기대했습니다. 나는 당신의 첫 번째 코멘트에 위와 같이 답했다. 나는 그것이 내 문제의 핵심이라고 생각한다. 나는 당신이 볼 수 있으면 크게 감사 할 것입니다! – user991710

+0

@ user991710 : 헤더가 예상하는 모든 것을 포함해야한다는 점을 모르겠다 *. 헤더는 ASCII 또는 Latin-1 인코딩 된 문자열이어야하며 RFC 표준에 지정된 특정 헤더에 특정 의미가 할당되어 있어야합니다. 'User-Agent' 헤더는 많은 의미가 할당되어 있지 않습니다; 데스크톱 브라우저를 스푸핑하려면 정확하게 보낸 내용을 복사해야합니다. 나는 당신이 원격 서버의 희망을 존중할 필요가 있다고 충분히 강조 할 수 없다. 당신이하지 않으면 당신을 완전히 막을 수 있습니다. –

+0

나는 본다. 이 경우 사이트의'/ robots.txt'를 확인하고 요청한 콘텐츠가'User-agent : * '가 아닌 경우에는 건너 뛰기 만하면 되는가? – user991710

관련 문제