如何检查网站上的值是否已更改

时间:2012-06-28 20:42:17

标签: python compare

基本上我正在尝试运行一些代码(Python 3.2),如果网站上的值发生变化,否则稍等一会儿再检查一下。

首先,我认为我可以将值保存在变量中,并将其与下次运行脚本时获取的新值进行比较。但是,当脚本再次运行并初始化该变量时,值会被覆盖,这很快就会遇到问题。

然后我尝试将网页的html保存为文件,然后将其与下次运行脚本时调用的html进行比较。那里没有运气,因为即使没有变化,它仍然会出现错误。

接下来是腌制网页,然后尝试将其与html进行比较。有趣的是,这在脚本中都不起作用。但是,如果我在脚本运行后键入file = pickle.load(打开('D:\ Download \ htmlString.p','rb')),然后输入file == 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')

5 个答案:

答案 0 :(得分:8)

编辑:我没有意识到您只是在寻找脚本问题。这就是我认为的问题,然后是我原来的答案,它解决了你试图解决的更大问题的另一种方法。

你的脚本是使用一揽子except语句的危险的一个很好的例子:你抓住了一切。在这种情况下,包括您的sys.exit(0)

我假设您try阻止了D:\Download\htmlString.p尚不存在的情况。该错误称为IOError,您可以使用except IOError:

专门捕获该错误

以下是您的脚本以及之前的一些代码,为except问题修复了问题:

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

作为旁注,您可以考虑使用os.path作为文件路径 - 它可以帮助以后想要在另一个平台上使用您的脚本的任何人,并且它可以为您节省丑陋的双反斜杠。 / p>

编辑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文档。如果是,您可能只是删除该行或其他东西。这可能是一种更优雅的方式,也许用正则表达式删除数字 - 但这至少可以满足你的问题。

原始答案 - 解决问题的另一种方法。

Web服务器的响应标头是什么样的? HTTP指定了一个Last-Modified属性,您可以使用该属性来检查内容是否已更改(假设服务器说明了事实)。 Uku在他的回答中显示,请使用此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().
"""

Stii的check out this blog post也可能提供一些灵感。我不太了解ETags将它们放在我的示例中,但他的代码也会检查它们。

答案 1 :(得分: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 :(得分: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哈希并在检查时动态计算。

答案 3 :(得分:0)

我不清楚您是否想要查看网站是否已更改,或者您是否要对网站的数据进行更多操作。如果它是前者,肯定是哈希,如前所述。这是一个工作(mac上的python 2.6.1)示例,它将完整的旧html与新的html进行比较;它应该很容易修改,因此它可以根据需要使用哈希或网站的特定部分。希望评论和文字信息能够使一切清晰。

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

答案 4 :(得分:0)

此答案是@DeaconDesperado答案的扩展

为简单起见,加快代码执行速度,可以先创建一个本地哈希(而不是存储页面的副本),然后将其与新获取的哈希进行比较

初始创建本地存储的哈希,可以使用此代码

import hashlib
import urllib

    remote_data = urllib.urlopen('http://remoteurl').read()
    remote_hash = hashlib.md5(remote_data).hexdigest()
  
    # Open a file with access mode 'a'
    file_object = open('localhash.txt', 'a')
    # Append  at the end of file
    file_object.write(remote_hash)
    # Close the file
    file_object.close()

并将local_data = open('localfilepath').read()替换为local_data = open('local\file\path\localhash.txt').read()

那是

    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_hash = open('local\file\path\localhash.txt').read()`
   
    if remote_hash == local_hash:
    
    print( 'right now, we match!' )
    
    else:
    
    print('right now, we are different' )

来源:-https://thispointer.com/how-to-append-text-or-lines-to-a-file-in-python/

DeaconDesperado'答案