2012-06-28 2 views
5

기본적으로 웹 사이트의 값이 변경되면 일부 코드 (Python 3.2)를 실행하려고합니다. 그렇지 않으면 잠시 기다렸다가 나중에 확인하십시오.웹 사이트의 값이 변경되었는지 확인하는 방법

처음에는 변수에 값을 저장하고 다음 번에 스크립트를 실행할 때 가져온 새 값과 비교할 수 있다고 생각했습니다. 그러나 스크립트가 다시 실행되고 해당 변수를 초기화 할 때 값을 덮어 쓰면 문제가 발생했습니다.

그럼 웹 페이지의 HTML을 파일로 저장 한 다음 스크립트가 실행 된 다음 번에 호출 될 html과 비교해 보았습니다. 아무런 변화가 없을 때라도 거짓을 계속 유지하면서 운이 없음.

다음은 웹 페이지를 산발로 처리 한 다음 html과 비교하려고합니다. 흥미롭게도 스크립트 내에서 작동하지 않았습니다. 하지만, file = pickle.load (open ('D : \ Download \ htmlString.p', 'rb'))를 입력하면 파일이 == html이 된 후 True가 표시됩니다. 모든 변경 사항.

나는 스크립트가 실행될 때 왜 작동하지 않겠는가에 대해 조금 혼란 스럽다. 그러나 위의 경우 정답을 보여준다.

편집 : 답변 주셔서 감사합니다. 내가 가지고있는 질문은 실제로 이것에 대해 갈 다른 방법에 관한 것이 아닙니다. (작업을 수행하는 더 많은 방법을 배우는 것이 좋습니다.) 오히려 아래 코드가 스크립트로 실행될 때 작동하지 않는 이유는 스크립트가 실행 된 후 프롬프트에서 pickle 객체를 다시로드 한 다음 html에 대해 테스트하면 변경 사항이없는 경우 True를 반환합니다.

try: 
    file = pickle.load(open('D:\\Download\\htmlString.p', 'rb')) 
    if pickle.load(open('D:\\Download\\htmlString.p', 'rb')) == htmlString: 
     print("Values haven't changed!") 
     sys.exit(0) 
    else: 
     pickle.dump(htmlString, open('D:\\Download\\htmlString.p', "wb")) 
     print('Saving') 
except: 
    pickle.dump(htmlString, open('D:\\Download\\htmlString.p', "wb")) 
    print('ERROR') 
+1

원격 및 로컬 콘텐츠의 내용/MIME 형식은 무엇입니까? – DeaconDesperado

+1

전체 페이지를 저장하고 비교하는 것은 매우 비효율적입니다. md5와 같은 해시를 계산하고 저장할 수 있습니다. 해시가 나중에 일치하면 페이지가 변경되지 않았습니다. – TJD

+0

수정 사항을 해결하기 위해 답변을 업데이트했습니다. 그게 니가 찾고 있던거야? – Phil

답변

7

편집는 : 나는 당신이 당신의 스크립트의 문제를 찾고 있었다 실현하지 않았다. 여기 내가 문제라고 생각하는 것, 해결하려고하는 더 큰 문제에 대한 또 다른 접근법을 다루는 본래의 대답이 뒤 따릅니다.

귀하의 스크립트는 담요 except 문을 사용하는 위험의 좋은 예입니다. 모든 것을 잡습니다. 이 경우에는 sys.exit(0)을 포함합니다.

나는 D:\Download\htmlString.p이 아직 존재하지 않는 경우를 잡기 위해 블록이 try이라고 가정합니다. 보조 노트로

import sys 
import pickle 
import urllib2 

request = urllib2.Request('http://www.iana.org/domains/example/') 
response = urllib2.urlopen(request) # Make the request 
htmlString = response.read() 

try: 
    file = pickle.load(open('D:\\Download\\htmlString.p', 'rb')) 
    if file == htmlString: 
     print("Values haven't changed!") 
     sys.exit(0) 
    else: 
     pickle.dump(htmlString, open('D:\\Download\\htmlString.p', "wb")) 
     print('Saving') 
except IOError: 
    pickle.dump(htmlString, open('D:\\Download\\htmlString.p', "wb")) 
    print('Created new file.') 

: 그 오류가 IOError라고, 당신은 여기에 except IOError:

스크립트 플러스가 갈 수 있도록하기 전에 코드의 비트가 구체적으로 그것을 잡을 수있는, 당신의 except 문제에 대한 해결 파일 경로에 os.path을 사용하는 것을 고려해 볼 수 있습니다. 나중에 다른 플랫폼에서 스크립트를 사용하려는 사람을 돕고 추한 이중 백 슬래시를 저장합니다.

편집 2 : 특정 URL에 맞게 수정되었습니다.

페이지로드시마다 변경되는 해당 페이지의 광고에 동적으로 생성 된 번호가 있습니다. 모든 콘텐츠가 끝나면 끝 부분 근처에 있으므로 HTML 문자열을 해당 지점에서 분할하고 전반을 가져 와서 동적 번호가있는 부분을 삭제할 수 있습니다.

import sys 
import pickle 
import urllib2 

request = urllib2.Request('http://ecal.forexpros.com/e_cal.php?duration=weekly') 
response = urllib2.urlopen(request) # Make the request 
# Grab everything before the dynabic double-click link 
htmlString = response.read().split('<iframe src="http://fls.doubleclick')[0] 

try: 
    file = pickle.load(open('D:\\Download\\htmlString.p', 'r')) 
    if pickle.load(open('D:\\Download\\htmlString.p', 'r')) == htmlString: 
     print("Values haven't changed!") 
     sys.exit(0) 
    else: 
     pickle.dump(htmlString, open('D:\\Download\\htmlString.p', "w")) 
     print('Saving') 
except IOError: 
    pickle.dump(htmlString, open('D:\\Download\\htmlString.p', "w")) 
    print('Created new file.') 

귀하의 문자열이되지이 중요하다고 더 이상 경우 유효한 HTML 문서 입니다. 만약 그렇다면, 당신은 그 라인이나 뭔가를 제거 할 수 있습니다. 아마도 이것을하는 더 우아한 방법이있을 것입니다 - 아마도 정규 표현식으로 숫자를 지우는 것입니다 -하지만 이것은 적어도 당신의 질문을 만족시킵니다.

Original Answer - 문제에 대한 대체 접근 방식.

웹 서버의 응답 헤더는 어떻게됩니까? HTTP는 내용이 변경되었는지 확인하는 데 사용할 수있는 Last-Modified 속성을 지정합니다 (서버가 사실을 알리는 경우). Uku가 대답 한 것처럼 HEAD 요청을 사용하십시오. 대역폭을 절약하고 폴링하려는 서버에 좋을 수 있습니다.

그리고 If-Modified-Since 헤더가있을 수 있습니다.

우리가 그들을 결합 할 경우,이 같은 것을 가지고 올 수 있습니다 STII에 의해

import sys 
import os.path 
import urllib2 

url = 'http://www.iana.org/domains/example/' 
saved_time_file = 'last time check.txt' 

request = urllib2.Request(url) 
if os.path.exists(saved_time_file): 
    """ If we've previously stored a time, get it and add it to the request""" 
    last_time = open(saved_time_file, 'r').read() 
    request.add_header("If-Modified-Since", last_time) 

try: 
    response = urllib2.urlopen(request) # Make the request 
except urllib2.HTTPError, err: 
    if err.code == 304: 
     print "Nothing new." 
     sys.exit(0) 
    raise # some other http error (like 404 not found etc); re-raise it. 

last_modified = response.info().get('Last-Modified', False) 
if last_modified: 
    open(saved_time_file, 'w').write(last_modified) 
else: 
    print("Server did not provide a last-modified property. Continuing...") 
    """ 
    Alternately, you could save the current time in HTTP-date format here: 
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 
    This might work for some servers that don't provide Last-Modified, but do 
    respect If-Modified-Since. 
    """ 

""" 
You should get here if the server won't confirm the content is old. 
Hopefully, that means it's new. 
HTML should be in response.read(). 
""" 
또한

check out this blog post하는 영감을 제공 할 수있다. 내 예제에 넣기에는 ETags에 대해 충분히 알지 못하지만 코드는이를 확인합니다.

+0

곧 작곡 할 때 편집을 놓쳤습니다 ... 답변 # 2 곧. – Phil

+0

Hey Phil, sys.exit에 대한 재미있는 말을 해줘서 고맙다. 스크립트를 종료 할 때 오류가 발생한다는 사실을 알지 못했기 때문이다. 내 원래 문제에 대해서는, 그것을 해결하지 않습니다. 필자가 피클 오브젝트를 다시로드하고 평등성을 테스트하지 않는 한 알 수없는 이유로 True를 인쇄하지 못합니다. 그래도 고마워! –

+0

흠, 그건 이상합니다. 그것은 나를 위해 잘 작동하는 것 : 그것을 처음으로 실행하면 그것은'새 파일을 만든', 그리고 나서'가치가 변경되지 않았습니다!'또는'저장'제대로. 나는 내가 제어하는 ​​서버에서 그것을 테스트했다. 함께 작업하는 URL은 무엇입니까? 그것은 당신이나 다른 사람의 것입니까? 아마도 플랫폼에 따라 다릅니다. 나는 리눅스를 여기에서 운영하고있다. – Phil

3

HEAD 요청을 수행하고 문서의 Content-Length를 확인하는 것이 더 효율적입니다. 컨텐츠 길이가 정확하게 일치하지만, 동시에 가장 효율적인 방법입니다 것을 수 있지만이 가능성이 있음을

import urllib2 
""" 
read old length from file into variable 
""" 
request = urllib2.Request('http://www.yahoo.com') 
request.get_method = lambda : 'HEAD' 

response = urllib2.urlopen(request) 
new_length = response.info()["Content-Length"] 
if old_length != new_length: 
    print "something has changed" 

참고. 이 방법은 예상되는 변경의 종류에 따라 적합하거나 부적절 할 수 있습니다.

+2

Nifty. 질문 제목이 페이지의 특정 값을 검사하고 있음을 암시하는 것처럼 보일지라도, 정수 또는 무언가라면 내용 길이가 변경되지 않았을 확률이 높습니다. – Phil

1

항상 로컬 저장 파일과 리모컨의 내용을 해시하여 데이터 내의 모든 변경 사항을 알 수 있습니다. 이것은 일반적으로 다운로드 된 데이터의 정확성을 확인하는 데 사용됩니다. 계속 확인하려면 while 루프가 필요합니다.

import hashlib 
import urllib 

num_checks = 20 
last_check = 1 
while last_check != num_checks: 
    remote_data = urllib.urlopen('http://remoteurl').read() 
    remote_hash = hashlib.md5(remote_data).hexdigest() 

    local_data = open('localfilepath').read() 
    local_hash = hashlib.md5(local_data).hexdigest() 
    if remote_hash == local_hash: 
    print 'right now, we match!' 
    else: 
    print 'right now, we are different' 

실제 데이터를 절대로 로컬에 저장할 필요가없는 경우 검사 할 때 md5 해시를 저장하고 즉시 계산합니다.

0

웹 사이트가 변경되었는지 또는 웹 사이트의 데이터를 더 많이 활용할 것인지 여부를 완전히 알기는 어렵습니다. 앞에서 언급했듯이 이전의 해시 인 경우 해시입니다. 다음은 완전한 old html과 새로운 html을 비교하는 working (파이썬 2.6.1 on mac) 예제입니다. 필요에 따라 해시를 사용하거나 웹 사이트의 특정 부분 만 사용하도록 수정해야합니다. 다행히 주석과 docstrings은 모든 것을 명확하게 해줍니다.

import urllib2 

def getFilename(url): 
    ''' 
    Input: url 
    Return: a (string) filename to be used later for storing the urls contents 
    ''' 
    return str(url).lstrip('http://').replace("/",":")+'.OLD' 


def getOld(url): 
    ''' 
    Input: url- a string containing a url 
    Return: a string containing the old html, or None if there is no old file 
    (checks if there already is a url.OLD file, and make an empty one if there isn't to handle the case that this is the first run) 
    Note: the file created with the old html is the format url(with : for /).OLD 
    ''' 
    oldFilename = getFilename(url) 
    oldHTML = "" 
    try: 
     oldHTMLfile = open(oldFilename,'r') 
    except: 
     # file doesn't exit! so make it 
     with open(oldFilename,'w') as oldHTMLfile: 
      oldHTMLfile.write("") 
     return None 
    else: 
     oldHTML = oldHTMLfile.read() 
     oldHTMLfile.close() 

    return oldHTML 

class ConnectionError(Exception): 
    def __init__(self, value): 
     if type(value) != type(''): 
      self.value = str(value) 
     else: 
      self.value = value 
    def __str__(self): 
     return 'ConnectionError: ' + self.value  


def htmlHasChanged(url): 
    ''' 
    Input: url- a string containing a url 
    Return: a boolean stating whether the website at url has changed 
    ''' 

    try: 
     fileRecvd = urllib2.urlopen(url).read() 
    except: 
     print 'Could not connect to %s, sorry!' % url 
     #handle bad connection error... 
     raise ConnectionError("urlopen() failed to open " + str(url)) 
    else: 
     oldHTML = getOld(url) 
     if oldHTML == fileRecvd: 
      hasChanged = False 
     else: 
      hasChanged = True 

     # rewrite file 
     with open(getFilename(url),'w') as f: 
      f.write(fileRecvd) 

     return hasChanged 

if __name__ == '__main__': 
    # test it out with whatismyip.com 
    try: 
     print htmlHasChanged("http://automation.whatismyip.com/n09230945.asp") 
    except ConnectionError,e: 
     print e 
+0

죄송합니다. 게시하기 전에 원래 질문에 대한 편집을 보지 못했습니다 ... –

관련 문제