2012-06-28 9 views
5

असल में मैं कुछ कोड (पायथन 3.2) चलाने की कोशिश कर रहा हूं यदि वेबसाइट पर कोई मूल्य बदलता है, अन्यथा थोड़ी देर प्रतीक्षा करें और बाद में जांचें।यह जांचने के लिए कि वेबसाइट पर मूल्य बदल गया है

सबसे पहले मैंने सोचा कि मैं केवल एक चर में मूल्य को बचा सकता हूं और इसे उस नए मान से तुलना कर सकता हूं जो अगली बार स्क्रिप्ट चलाएगा। लेकिन वह जल्दी से समस्याओं में भाग गया क्योंकि स्क्रिप्ट फिर से चलने पर और उस चर को प्रारंभ करने पर मान ओवरराइट किया गया था।

तो फिर मैं सिर्फ एक फ़ाइल के रूप में वेब पेज के HTML सहेजने और फिर एचटीएमएल कि अगली बार स्क्रिप्ट चलाने पर कहा जा सकता है के साथ उसकी तुलना करने की कोशिश की। कोई भाग्य या तो इसे गलत आ रहा रखा के रूप में भले ही कोई परिवर्तन किया गया है।

आगे वेबपेज नमकीन बनाना था और तब एचटीएमएल के साथ तुलना करने की कोशिश कर। दिलचस्प बात यह है कि स्क्रिप्ट के भीतर या तो काम नहीं किया। लेकिन, अगर मैं फ़ाइल = pickle.load टाइप करें (खुला ('डी: \ डाउनलोड \ htmlString.p', 'rb')) के बाद स्क्रिप्ट चलाने है और फिर == HTML फ़ाइल है, यह सच है पता चलता है जब वहाँ नहीं किया गया है कोई बदलाव।

मैं थोड़ा उलझन में हूं कि स्क्रिप्ट चलाने पर यह क्यों काम नहीं करेगा, लेकिन यदि मैं उपर्युक्त करता हूं तो यह सही उत्तर दिखाता है।

संपादित करें: प्रतिक्रियाएं अब तक लोगों के लिए धन्यवाद। सवाल मैं वास्तव में अन्य तरीकों से इस बारे में जाने के लिए (यह हमेशा अच्छा है, हालांकि अधिक तरीकों एक कार्य को पूरा करने के लिए! जानने के लिए), लेकिन जब यह एक स्क्रिप्ट के रूप में चलाए जाने के दौरान नहीं बल्कि क्यों नीचे कोड काम नहीं करता है के बारे में नहीं था, लेकिन अगर मैं प्रॉम्प्ट पर अचार वस्तु को फिर से लोड करने के बाद स्क्रिप्ट चलाने है और फिर एचटीएमएल के खिलाफ परीक्षण करते हैं, यह सच है वापस आ जाएगी अगर कोई परिवर्तन नहीं किया गया है।

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

रिमोट और स्थानीय सामग्री की सामग्री/mimetype क्या हैं? – DeaconDesperado

+1

पूरे पृष्ठों को सहेजना और तुलना करना बहुत अक्षम है। आप सिर्फ md5 की तरह हैश की गणना कर सकते हैं और उसे सहेज सकते हैं। यदि भविष्य में हैश मैच है, तो पृष्ठ नहीं बदला है। – TJD

+0

मैंने आपके संपादन को संबोधित करने के लिए अपना उत्तर अपडेट कर दिया है। क्या आप इसी की तलाश में हैं? – Phil

उत्तर

7

संपादित: मुझे एहसास हुआ कि नहीं था तुम सिर्फ अपनी स्क्रिप्ट के साथ समस्या यह देख रहे थे। यहां मुझे लगता है कि समस्या क्या है, इसके बाद मेरे मूल उत्तर के बाद जो आप हल करने की कोशिश कर रहे बड़ी समस्या के लिए एक और दृष्टिकोण को संबोधित करते हैं।

आपकी स्क्रिप्ट एक कंबल except कथन का उपयोग करने के खतरों का एक बड़ा उदाहरण है: आप सब कुछ पकड़ते हैं। इस मामले में, आपके sys.exit(0) सहित।

मुझे लगता है कि आप try ब्लॉक हैं जहां D:\Download\htmlString.p अभी तक मौजूद नहीं है।

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: अपने विशिष्ट यूआरएल के लिए अनुकूलित।

उस पृष्ठ के विज्ञापनों के लिए गतिशील रूप से जेनरेट की गई संख्या है जो प्रत्येक पृष्ठ लोड के साथ बदलती है। यह सभी सामग्री के बाद अंत में सही है, इसलिए हम उस बिंदु पर केवल 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 दस्तावेज है कि अब और अगर महत्वपूर्ण था है। अगर ऐसा होता है, तो आप उस रेखा या कुछ को हटा सकते हैं। ऐसा करने का शायद एक और शानदार तरीका है, - शायद एक रेगेक्स के साथ संख्या को हटा रहा है - लेकिन यह कम से कम आपके प्रश्न को संतुष्ट करता है।

मूल उत्तर - आपकी समस्या के लिए एक वैकल्पिक दृष्टिकोण।

वेब सर्वर से प्रतिक्रिया शीर्षलेख कैसा दिखते हैं? HTTP Last-Modified प्रॉपर्टी निर्दिष्ट करता है जिसका उपयोग आप यह जांचने के लिए कर सकते हैं कि सामग्री बदल गई है या नहीं (मान लीजिए कि सर्वर सत्य बताता है)। यूके ने अपने उत्तर में दिखाए गए अनुरोध के रूप में HEAD अनुरोध के साथ इसका उपयोग करें। यदि आप बैंडविड्थ को संरक्षित करना चाहते हैं और सर्वर पर अच्छा होना चाहते हैं तो आप मतदान कर रहे हैं।

और If-Modified-Since हेडर भी है जो आपको लगता है कि आप क्या देख रहे हैं।

तो हम उन्हें गठबंधन है, तो आप कुछ इस तरह के साथ आने सकता है:

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 Stii द्वारा जो कुछ प्रेरणा प्रदान कर सकता है। मुझे अपने उदाहरण में रखने के लिए ETags के बारे में पर्याप्त जानकारी नहीं है, लेकिन उसका कोड उनके लिए भी जांच करता है।

+0

मैंने इसे लिखते समय संपादन को भी याद किया ... उत्तर # 2 जल्द ही आ रहा है। – Phil

+0

हे फिल, sys.exit के बारे में tidbit को इंगित करने के लिए धन्यवाद क्योंकि मुझे पता नहीं था कि यह स्क्रिप्ट से बाहर निकलने के लिए एक त्रुटि उठाई है। मेरी मूल समस्या के बारे में, हालांकि यह हल नहीं करता है। किसी अज्ञात कारण के लिए यह तब भी सही नहीं होता जब तक कि इसे तब तक सही नहीं किया जाता जब तक कि मैं अचार वस्तु को फिर से लोड नहीं करता और फिर समानता के लिए परीक्षण करता हूं। हालांकि धन्यवाद! –

+0

हम्म, यह अजीब है। ऐसा लगता है कि मेरे लिए ठीक काम करता है: पहली बार यह चलाता है कि 'नई फाइल बनाई गई' कहती है, और उसके बाद या तो 'मान बदल नहीं गए हैं!' या 'सेविंग' सही ढंग से। मैंने इसे नियंत्रित सर्वर पर परीक्षण किया। यूआरएल क्या है जिसके साथ आप काम कर रहे हैं? क्या यह तुम्हारा है या कोई और है? शायद यह किसी भी तरह से मंच-विशिष्ट है। मैं यहाँ लिनक्स चला रहा हूँ। – Phil

3

यह एक HEAD अनुरोध करते हैं और जाँच दस्तावेज़ के सामग्री-लंबाई करने के लिए और अधिक कुशल हो जाएगा।

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

निफ्टी। यद्यपि प्रश्न शीर्षक का अर्थ यह है कि वह पृष्ठ पर एक विशिष्ट मूल्य की जांच कर रहा है, इसलिए यदि यह केवल एक पूर्णांक या कुछ है, तो सामग्री की लंबाई में बदलाव नहीं होने का मौका अधिक है। – Phil

1

आप स्थानीय संग्रहीत फ़ाइल और रिमोट दोनों के बीच डेटा के भीतर किसी भी बदलाव के बारे में हमेशा बता सकते हैं कि दोनों की सामग्री हैशिंग करें। यह आमतौर पर डाउनलोड किए गए डेटा की सत्यता को सत्यापित करने के लिए नियोजित किया जाता है। निरंतर जांच के लिए, आपको थोड़ी देर की आवश्यकता होगी।

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

मैं पूरी तरह से स्पष्ट नहीं था कि आप देखना चाहते हैं कि वेबसाइट बदल गई है या नहीं, या यदि आप वेबसाइट के डेटा के साथ और अधिक करने जा रहे हैं। यदि यह पूर्व है, निश्चित रूप से हैश, जैसा कि पहले उल्लेख किया गया है। यहां एक काम कर रहा है (एक मैक पर पायथन 2.6.1) उदाहरण है कि नए एचटीएमएल के साथ पूर्ण पुराने एचटीएमएल की तुलना करता है; इसे संशोधित करना आसान होना चाहिए ताकि आपको वेबसाइट की हेश या वेबसाइट का एक विशिष्ट हिस्सा उपयोग किया जा सके। उम्मीद है कि टिप्पणियां और दस्तावेज सब कुछ स्पष्ट कर देते हैं।

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

ओह, पोस्ट करने से पहले मूल प्रश्न में संपादन को नहीं देखा ... –