精华内容
下载资源
问答
  • 手机、电脑随着不断的使用,系统本身、系统工具、第三方应用都会不断产生一些临时文件垃圾文件。手机产生的垃圾文件更是显得杂乱无章,虽然可以使用系统自带或第三方应用来清理垃圾,但在本地存储还是有大量的...

    手机、电脑随着不断的使用,系统本身、系统工具、第三方应用都会不断产生一些临时文件和垃圾文件。手机产生的垃圾文件更是显得杂乱无章,虽然可以使用系统自带或第三方应用来清理垃圾,但在本地存储还是有大量的文件夹或文件是可以手动删除的。当然,有些数据是自己想保留的,这时就要考虑是哪些应用产生的数据,对这些数据在手机内文件夹的保存路径有一个大概的了解,避免误删除。

    1 手机操作系统文件

    在没有获得ROOT权限的情i况下,没法读写手机系统相关的文件以及相关的文件夹。如果手机已经获取ROOT权限,要重点关注Android文件夹。

    2 数据部分

    2.1 保存在Android文件夹内的第三方应用的数据

    如喜马拉雅上下载的文件便保存在以下路径:

    内部存储Androiddatacom.ximalaya.ting.androidfilesdownload

    2.2 系统自带工具产生的数据,如DCIM文件夹,就是你用相机拍照留下来的文件,可能部分是想保留的。

    2.3 第三方应用数据,如tencent文件夹,里面有QQ、微信的聊天记录:

    内部存储encentMicroMsg

    3 系统工具或第三应用的登录信息、使用习惯

    这部分的数据一般保存在一个配置文件中,如果删除了,哪这些信息也丢失了。

    1 系统文件

    在没有获得ROOT权限的情i况下,没法读写手机系统相关的文件以及相关的文件夹。因此,在这种情况下删除内部储存文件不会对系统造成影响。

    如果手机已经获取ROOT权限,那么使用手机文件管理对内部储存文件进行删除的时候应该注意以下文件夹。

    重点关注以下几个文件夹:

    Android文件夹:存放重要的程序数据,误删可能导致手机内应用出现异常。

    .android_secure:存储相关应用的使用认证验证,删除后可能会导致SD卡中的软件将无法使用。

    backups:包含重要的备份文件,比如联系人导出到SD卡会导入到此文件夹。

    bugtogo:系统出现问题的时候会形成一些报告文件,存放在此文件夹。

    data:缓存数据文件夹,与Android类似。

    Download(download):大写字母的是网络联接下载文件目录,小写字母的是手机自身(蓝牙,近场等)存放下载传输文件,不要误删。

    2 系统自带工具相关文件夹

    DCIM:相机随机缓存文件夹,记录功能设置的参数,需要及时清理。一些第三方相机软件拍出的相片也会保存在这里。

    HWiReader、Music、Pictures等文件夹也要小心操作,看有没有自己需要保存的数据。

    3 第三方应用类产生的可能需要保留的数据

    Tencent:腾讯软件的缓存目录,比如QQ。(与上面的.QQ文件夹并不相同)

    UCDownloads:uc浏览器下载文件缓存的保存目录。

    baidunetdisk:百度网盘下载的数据。

    kugou:酷狗音乐缓存或下载的数据。

    第三方应用产生的数据除了可以使用清理工具进行清理外,还可以在“应用管理”中进行清理:

    设置→应用管理,可以看到某个应用的存储使用敢多少M或G(包括应用本身及产生的数据所占用的空间)→点击某个应用→存储→删除数据。同样的问题是一定要想清楚,是不是部分数据自己想保存的,需要考虑做备份,以及登录信息和使用习惯的数据。

    c598475e0e5d3db84eb6632980f34677.png

    所有都弄完了,一切都清爽了,特别是对于有强迫症的人来说,当然,存在的风险就是可能一不小心(或当时忘记了哪些数据是需要备份的)把需要的数据给删了。

    -End-

    展开全文
  • Android应用文件存储目录的结构,及进入应用详情页时,清除数据清除缓存的介绍。

    内推

    【长期有效】欢迎加入字节跳动我的团队:内推链接

    一.应用内置存储。(/data/data/[packagename]目录下)

    此目录读写权限为rwxrwx--x,是应用私有存储目录,其他应用不可读写,除非指定相同的uid。关于Android uid、pid及与linux的关系,可参考:[http://blog.csdn.net/vshuang/article/details/43639211]
    
    1. /data/data/[packagename]/files 文件存储目录,一般存小的文件,如果是图片、音乐、视频等富媒体,不建议放这里,一般放到外置卡。File file = getFilesDir(); 获取目录。

    2. /data/data/[packagename]/cache目录,存放一些缓存文件。 File cache = getCacheDir();获取此目录

    3. /data/data/[packagename]/databases,存放应用的数据库

    4. /data/data/[packagename]/lib,存放应用的so文件

    5. /data/data/[packagename]/shared_prefs ,存放应用的SharedPreferences保存


    二.应用外置存储。(/sdcard/Android/data/[packagename]目录下)

    此目录读写权限为rwxrwxrwx,所有应用可读可写可执行,故不建议将比较重要或者私密的文件放在外置存储。
    
    1. sdcard/Android/data/[packagename]/files,一般放一些长时间保存的文件,通过Context.getExternalFilesDir()方法可以获取到 。

    2. sdcard/Android/data/[packagename]/cache,一般存放临时缓存数据(视频、音频、图片等),通过Context.getExternalCacheDir()方法可以获取到 。

      另:Environment.getExternalStorageDirectory().getPath();可获得应用内置sdcard根目录。


    三.当进入“设置”->“应用管理”->“应用详情页”时:
    这里写图片描述

    1. 应用详情页显示的缓存选项:即为/data/data/[packagename]/cache 和 /mnt/sdcard/Android/data/[packagename]/cache的总大小。
      点击清除缓存时,是清除掉这两个位置下的文件。

    2. 应用详情页显示的数据项:其大小为应用内置存储和外置存储总大小 - /data/data/[packagename]/lib目录大小。
      点击清除数据时,清除应用内置存储(/data/data/[packagename]目录)下除了lib目录下的全部文件及应用外置存储(/sdcard/Android/data/[packagename]目录)下的全部文件。

    3. 应用详情页显示的SD卡选项:其大小即为应用外置存储(/sdcard/Android/data/[packagename]目录)的大小。

    展开全文
  • 1为链接爬虫添加缓存支持 2磁盘缓存 1用磁盘缓存的实现 2缓存测试 3节省磁盘空间 4清理过期数据 5用磁盘缓存的缺点 3数据库缓存 1NoSQL是什么 2安装MongoDB 3MongoDB概述 4MongoDB缓存实现 5压缩存储 6...

    下载缓存

    上篇文章,我们学习了如何提取网页中的数据,以及将提取结果存到表格中。如果我们还想提取另一字段,则需要重新再下载整个网页,这对我们这个小型的示例网站问题不大,但对于数百万个网页的网站而言来说就要消耗几个星期的时间。所以,我们可以先对网页进行缓存,就使得每个网页只下载一次。

    1为链接爬虫添加缓存支持

    • 我们将downloader重构一类,这样参数只需在构造方法中设置一次,就能在后续多次复用,在URL下载之前进行缓存检查,并把限速功能移到函数内部。
    • 在Downloader类的__call__特殊方法实现了下载前先检查缓存,如果已经定义该URL缓存则再检查下载中是否遇到了服务端错误,如果都没问题表明缓存结果可用,否则都需要正常下载该URL存到缓存中。
    • downloader方法返回添加了HTTP状态码,以便缓存中存储错误机校验。如果不需要限速或缓存的话,你可以直接调用该方法,这样就不会通过__call__方法调用了。
    
    class Downloader:
        def __init__(self, delay=5, user_agent='Wu_Being', proxies=None, num_retries=1, cache=None):
            self.throttle = Throttle(delay)
            self.user_agent = user_agent
            self.proxies = proxies
            self.num_retries = num_retries
            self.cache = cache
    
        def __call__(self, url):
            result = None
            if self.cache:
                try:
                    result = self.cache[url]
                except KeyError:
                    # url is not available in cache 
                    pass
                else:
                    if self.num_retries > 0 and 500 <= result['code'] < 600:
                        # server error so ignore result from cache and re-download
                        result = None
            if result is None:
                # result was not loaded from cache so still need to download
                self.throttle.wait(url)
                proxy = random.choice(self.proxies) if self.proxies else None
                headers = {'User-agent': self.user_agent}
                result = self.download(url, headers, proxy=proxy, num_retries=self.num_retries)
                if self.cache:
                    # save result to cache
                    self.cache[url] = result
            return result['html']
    
        def download(self, url, headers, proxy, num_retries, data=None):
            print 'Downloading:', url
    	...
            return {'html': html, 'code': code}
    
    class Throttle:
        def __init__(self, delay):
    	...
        def wait(self, url):
    	...
    

    为了支持缓存功能,链接爬虫代码也需用一些微调,包括添加cache参数、移除限速以及将download函数替换为新的类。

    from downloader import Downloader
    
    def link_crawler(... cache=None):
        crawl_queue = [seed_url]
        seen = {seed_url: 0}
        # track how many URL's have been downloaded
        num_urls = 0
        rp = get_robots(seed_url)
        #cache.clear()			###############################
        D = Downloader(delay=delay, user_agent=user_agent, proxies=proxies, num_retries=num_retries, cache=cache)
    
        while crawl_queue:
            url = crawl_queue.pop()
            depth = seen[url]
            # check url passes robots.txt restrictions
            if rp.can_fetch(user_agent, url):
                html = D(url)				###def __call__(self, url):
                links = []
    	...
    
    def normalize(seed_url, link):
    	...
    def same_domain(url1, url2):
    	...
    def get_robots(url):
    	...
    def get_links(html):
    	...
    """
    if __name__ == '__main__':
        link_crawler('http://example.webscraping.com', '/(index|view)', delay=0, num_retries=1, user_agent='BadCrawler')
        link_crawler('http://example.webscraping.com', '/(index|view)', delay=0, num_retries=1, max_depth=1, user_agent='GoodCrawler')
    """
    

    现在,这个支持缓存的网络爬虫的基本架构已经准备好了,下面就要开始构建实际的缓存功能了。

    2磁盘缓存

    操作系统文件系统非法文件名字符文件名最大长度
    LinuxExt3/Ext4/\0255个字节
    OS XHFS Plus:\0255个UTF-16编码单元
    WindowsNTFS\/?:*"><|255个字节

    为了保证在不同文件系统中,我们的文件路径都是安全的,就需要把除数字、字母和基本符号的其他字符替换为下划线。

    >>> import re
    >>> url="http://example.webscraping.com/default/view/australia-1"
    >>> re.sub('[^/0-9a-zA-Z\-,.;_ ]','_',url)
    'http_//example.webscraping.com/default/view/australia-1'
    

    此外,文件名及其目录长度需要限制在255个字符以内。

    >>> filename=re.sub('[^/0-9a-zA-Z\-,.;_ ]','_',url)
    >>> filename='/'.join(segment[:255] for segment in filename.split('/'))
    >>> print filename
    http_//example.webscraping.com/default/view/australia-1
    >>> print '#'.join(segment[:5] for segment in filename.split('/'))
    http_##examp#defau#view#austr
    >>> 
    

    还有一种边界情况,就是URL以斜杠结尾。这样分割URL后就会造成一个非法的文件名。例如:

    对于第一个URL可以在后面添加index.html作为文件名,所以可以把index作为目录名,1为子目录名,index.html为文件名。

    >>> import urlparse
    >>> components=urlparse.urlsplit('http://exmaple.scraping.com/index/')
    >>> print components
    SplitResult(scheme='http', netloc='exmaple.scraping.com', path='/index/', query='', fragment='')
    >>> print components.path
    /index/
    >>> path=components.path
    >>> if not path:
    ...     path='/index.html'
    ... elif path.endswith('/'):
    ...     path+='index.html'
    ... 
    >>> filename=components.netloc+path+components.query
    >>> filename
    'exmaple.scraping.com/index/index.html'
    >>> 
    

    2.1用磁盘缓存的实现

    现在可以把URL到目录和文件名完整映射逻辑结合起来,就形成了磁盘缓存的主要部分。该构造方法传入了用于设定缓存位置的参数,然后在url_to_path方法中应用了前面讨论的文件名限制。

    from link_crawler import link_crawler
    
    class DiskCache:
    
        def __init__(self, cache_dir='cache', ...):
            """
            cache_dir: the root level folder for the cache
            """
            self.cache_dir = cache_dir
    	...
    
        def url_to_path(self, url):
            """Create file system path for this URL
            """
            components = urlparse.urlsplit(url)
            # when empty path set to /index.html
            path = components.path
            if not path:
                path = '/index.html'
            elif path.endswith('/'):
                path += 'index.html'
            filename = components.netloc + path + components.query
            # replace invalid characters
            filename = re.sub('[^/0-9a-zA-Z\-.,;_ ]', '_', filename)
            # restrict maximum number of characters
            filename = '/'.join(segment[:255] for segment in filename.split('/'))
            return os.path.join(self.cache_dir, filename) #拼接当前目录和文件名为完整目录
        
        def __getitem__(self, url):
            ...
        def __setitem__(self, url, result):
            ...
        def __delitem__(self, url):
            ...
        def has_expired(self, timestamp):
            ...
        def clear(self):
    	...
    
    if __name__ == '__main__':
        link_crawler('http://example.webscraping.com/', '/(index|view)', cache=DiskCache())
    

    现在我们还缺少根据文件名存取数据的方法,就是Downloader类result=cache[url]cache[url]=result的接口方法:__getitem__()__setitem__()两个特殊方法。

    import pickle
    
    class DiskCache:
    
        def __init__(self, cache_dir='cache', expires=timedelta(days=30), compress=True):
    	...    
        def url_to_path(self, url):
    	...
        def __getitem__(self, url):
    	...
        def __setitem__(self, url, result):
            """Save data to disk for this url
            """
            path = self.url_to_path(url)
            folder = os.path.dirname(path)
            if not os.path.exists(folder):
                os.makedirs(folder)
            with open(path, 'wb') as fp:
                fp.write(pickle.dumps(result))
    

    __setitem__()中,我们使用url_to_path()方法将URL映射为安全文件名,在必要情况下还需要创建目录。这里使用的pickle模块会把输入转化为字符串(序列化),然后保存到磁盘中。

    import pickle
    
    class DiskCache:
    
        def __init__(self, cache_dir='cache', expires=timedelta(days=30), compress=True):
    	...    
        def url_to_path(self, url):
    	...
        def __getitem__(self, url):
            """Load data from disk for this URL
            """
            path = self.url_to_path(url)
            if os.path.exists(path):
                with open(path, 'rb') as fp:
                    return pickle.loads(fp.read())
            else:
                # URL has not yet been cached
                raise KeyError(url + ' does not exist')
    
        def __setitem__(self, url, result):
    	...
    

    __getitem__()中,还是先用url_to_path()方法将URL映射为安全文件名。然后检查文件是否存在,如果存在则加载内容,并执行反序列化,恢复其原始数据类型;如果不存在,则说明缓存中还没有该URL的数据,此时会抛出KeyError异常。

    2.2缓存测试

    可以在python命令前加time计时。我们可以发现,如果是在本地服务器的网站,当缓存为空时爬虫实际耗时0m58.710s,第二次运行全部从缓存读取花了0m0.221s,快了265多倍。如果是爬取远程服务器的网站的数据时,将会耗更多时间。

    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ time python 2disk_cache_Nozip127.py 
    Downloading: http://127.0.0.1:8000/places/
    Downloading: http://127.0.0.1:8000/places/default/index/1
    ...
    Downloading: http://127.0.0.1:8000/places/default/view/Afghanistan-1
    real	0m58.710s
    user	0m0.684s
    sys	0m0.120s
    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ time python 2disk_cache_Nozip127.py 
    
    real	0m0.221s
    user	0m0.204s
    sys	0m0.012s
    

    2.3节省磁盘空间

    为节省缓存占用空间,我们可以对下载的HTML文件进行压缩处理,使用zlib压缩序列化字符串即可。

    fp.write(zlib.compress(pickle.dumps(result)))
    

    从磁盘加载后解压的代码如下:

    return pickle.loads(zlib.decompress(fp.read()))
    

    压缩所有网页之后,缓存占用大小2.8 MB下降到821.2 KB,耗时略有增加。

    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ time python 2disk_cache.py 
    Downloading: http://127.0.0.1:8000/places/
    Downloading: http://127.0.0.1:8000/places/default/index/1
    ...
    Downloading: http://127.0.0.1:8000/places/default/view/Afghanistan-1
    
    real	1m0.011s
    user	0m0.800s
    sys	0m0.104s
    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ 
    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ time python 2disk_cache.py 
    
    real	0m0.252s
    user	0m0.228s
    sys	0m0.020s
    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ 
    

    2.4清理过期数据

    本节中,我们将为缓存数据添加过期时间,以便爬虫知道何时需要重新下载网页。在构造方法中,我们使用timedelta对象将默认过期时间设置为30天,在__set__方法中把当前时间戳保存在序列化数据中,在__get__方法中对比当前时间和缓存时间,检查是否过期。

    from datetime import datetime, timedelta
    
    class DiskCache:
    
        def __init__(self, cache_dir='cache', expires=timedelta(days=30), compress=True):
            """
            cache_dir: the root level folder for the cache
            expires: timedelta of amount of time before a cache entry is considered expired
            compress: whether to compress data in the cache
            """
            self.cache_dir = cache_dir
            self.expires = expires
            self.compress = compress
    
        def __getitem__(self, url):
            """Load data from disk for this URL
            """
            path = self.url_to_path(url)
            if os.path.exists(path):
                with open(path, 'rb') as fp:
                    data = fp.read()
                    if self.compress:
                        data = zlib.decompress(data)
                    result, timestamp = pickle.loads(data)
                    if self.has_expired(timestamp):
                        raise KeyError(url + ' has expired')
                    return result
            else:
                # URL has not yet been cached
                raise KeyError(url + ' does not exist')
    
        def __setitem__(self, url, result):
            """Save data to disk for this url
            """
            path = self.url_to_path(url)
            folder = os.path.dirname(path)
            if not os.path.exists(folder):
                os.makedirs(folder)
    
            data = pickle.dumps((result, datetime.utcnow()))
            if self.compress:
                data = zlib.compress(data)
            with open(path, 'wb') as fp:
                fp.write(data)
    
    	...
        def has_expired(self, timestamp):
            """Return whether this timestamp has expired
            """
            return datetime.utcnow() > timestamp + self.expires
    

    为了测试时间功能,我们可以将其缩短为5秒,如下操作:

        """
        Dictionary interface that stores cached 
        values in the file system rather than in memory.
        The file path is formed from an md5 hash of the key.
        """
    >>> from disk_cache import DiskCache
    >>> cache=DiskCache()
    >>> url='http://www.baidu.com'
    >>> result={'html':'<html>...','code':200}
    >>> cache[url]=result
    >>> cache[url]
    {'code': 200, 'html': '<html>...'}
    >>> cache[url]['html']==result['html']
    True
    >>> 
    >>> from datetime import timedelta
    >>> cache2=DiskCache(expires=timedelta(seconds=5))
    >>> url2='https://www.baidu.sss'
    >>> result2={'html':'<html>..ss.','code':500}
    >>> cache2[url2]=result2
    >>> cache2[url2]
    {'code': 200, 'html': '<html>...'}
    >>> cache2[url2]
    {'code': 200, 'html': '<html>...'}
    >>> cache2[url2]
    {'code': 200, 'html': '<html>...'}
    >>> cache2[url2]
    {'code': 200, 'html': '<html>...'}
    >>> cache2[url2]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "disk_cache.py", line 57, in __getitem__
        raise KeyError(url + ' has expired')
    KeyError: 'http://www.baidu.com has expired'
    >>> cache2.clear()
    
    

    2.5用磁盘缓存的缺点

    由于受制于文件系统的限制,之前我们将URL映射为安全文件名,然而这样又会引发一些问题:

    • 有些URL会被映射为相同的文件名。比如URL:.../count.asp?a+b,.../count.asp?a*b
    • URL截断255个字符的文件名也可能相同。因为URL可以超过2000下字符。

    使用URL哈希值为文件名可以带来一定的改善。这样也有一些问题:

    • 每个卷和每个目录下的文件数量是有限制的。FAT32文件系统每个目录的最大文件数65535,但可以分割到不同目录下。
    • 文件系统可存储的文件总数也是有限的。ext4分区目前支持略多于1500万个文件,而一个大型网站往往拥有超过1亿个网页。

    要想避免这些问题,我们需要把多个缓存网页合并到一个文件中,并使用类似B+树的算法进行索引。但我们不会自己实现这种算法,而是在下一节中介绍已实现这类算法的数据库。

    3数据库缓存

    爬取时,我们可能需要缓存大量数据,但又无须任何复杂的连接操作,因此我们将选用NoSQL数据库,这种数据库比传统的关系型数据库更容易扩展。在本节中,我们将选用目前非常流行的MongoDB作为缓存数据库。

    3.1NoSQL是什么

    NoSQL全称为Not Only SQL,是一种相对较新的数据库设计方式。传统的关系模型使用是固定模式,并将数据分割到各个表中。然而,对于大数据集的情况,数据量太大使其难以存放在单一服务器中,此时就需要扩展到多台服务器。不过,关系模型对于这种扩展的支持并不够好,因为在查询多个表时,数据可能在不同的服务器中。相反,NoSQL数据库通常是无模式的,从设计之初就考虑了跨服务器无缝分片的问题。在NoSQL中,有多种方式可以实现该目标,分别是:
    
    • 列数据存储(如HBase);
    • 键值对存储(如Redis);
    • 图形数据库(如Neo4j);
    • 面向文档的数据库(如MongoDB)。

    3.2安装MongoDB

    MongoDB可以从https://www.mongodb.org/downloads 下载。然后安装其Python封装库:

    pip install pymongo
    

    检测安装是否成功,在本地启动MongoDB服务器:

    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ mongod -dbpath MongoD
    2017-01-17T21:20:46.224+0800 [initandlisten] MongoDB starting : pid=1978 port=27017 dbpath=MongoD 64-bit host=ubuntukylin64
    2017-01-17T21:20:46.224+0800 [initandlisten] db version v2.6.10
    2017-01-17T21:20:46.224+0800 [initandlisten] git version: nogitversion
    2017-01-17T21:20:46.225+0800 [initandlisten] OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016
    2017-01-17T21:20:46.225+0800 [initandlisten] build info: Linux lgw01-12 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64 BOOST_LIB_VERSION=1_58
    2017-01-17T21:20:46.225+0800 [initandlisten] allocator: tcmalloc
    2017-01-17T21:20:46.225+0800 [initandlisten] options: { storage: { dbPath: "MongoD" } }
    2017-01-17T21:20:46.269+0800 [initandlisten] journal dir=MongoD/journal
    2017-01-17T21:20:46.270+0800 [initandlisten] recover : no journal files present, no recovery needed
    2017-01-17T21:20:49.126+0800 [initandlisten] preallocateIsFaster=true 33.72
    2017-01-17T21:20:51.932+0800 [initandlisten] preallocateIsFaster=true 32.7
    2017-01-17T21:20:55.729+0800 [initandlisten] preallocateIsFaster=true 32.36
    2017-01-17T21:20:55.730+0800 [initandlisten] preallocateIsFaster check took 9.459 secs
    2017-01-17T21:20:55.730+0800 [initandlisten] preallocating a journal file MongoD/journal/prealloc.0
    2017-01-17T21:20:58.042+0800 [initandlisten] 		File Preallocator Progress: 608174080/1073741824	56%
    2017-01-17T21:21:03.290+0800 [initandlisten] 		File Preallocator Progress: 744488960/1073741824	69%
    2017-01-17T21:21:08.043+0800 [initandlisten] 		File Preallocator Progress: 954204160/1073741824	88%
    2017-01-17T21:21:18.347+0800 [initandlisten] preallocating a journal file MongoD/journal/prealloc.1
    2017-01-17T21:21:21.166+0800 [initandlisten] 		File Preallocator Progress: 639631360/1073741824	59%
    2017-01-17T21:21:26.328+0800 [initandlisten] 		File Preallocator Progress: 754974720/1073741824	70%
    ...
    

    然后,在Python中,使用MongoDB的默认端口尝试连接MongoDB:

    >>> from pymongo import MongoClient
    >>> client=MongoClient('localhost',27017)
    

    3.3MongoDB概述

    下面是MongoDB示例代码:

    >>> from pymongo import MongoClient
    >>> client=MongoClient('localhost',27017)
    >>> url='http://www.baidu.com/view/China-47'
    >>> html='...<html>...'
    >>> db=client.cache
    >>> db.webpage.insert({'url':url,'html':html})
    ObjectId('587e2cb26b00c10b956e0be9')
    >>> db.webpage.find_one({'url':url})
    {u'url': u'http://www.baidu.com/view/China-47', u'_id': ObjectId('587e2cb26b00c10b956e0be9'), u'html': u'...<html>...'}
    >>> db.webpage.find({'url':url})
    <pymongo.cursor.Cursor object at 0x7fcde0ca60d0>
    >>> db.webpage.find({'url':url}).count()
    1
    

    当插入同一条记录时,MongoDB会欣然接受并执行这次操作,但通过查找发现记录没更新。

    >>> db.webpage.insert({'url':url,'html':html})
    ObjectId('587e2d546b00c10b956e0bea')
    >>> db.webpage.find({'url':url}).count()
    2
    >>> db.webpage.find_one({'url':url})
    {u'url': u'http://www.baidu.com/view/China-47', u'_id': ObjectId('587e2cb26b00c10b956e0be9'), u'html': u'...<html>...'}
    

    为了存储最新的记录,并避免重复记录,我们将ID设置为URL,并执行upsert操作。该操作表示当记录存在时则更新记录,否则插入新记录。

    >>> 
    >>> new_html='<...>...'
    >>> db.webpage.update({'_id':url},{'$set':{'html':new_html}},upsert=True)
    {'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}
    >>> db.webpage.find_one({'_id':url})
    {u'_id': u'http://www.baidu.com/view/China-47', u'html': u'<...>...'}
    >>> db.webpage.find({'_id':url}).count()
    1
    >>> db.webpage.update({'_id':url},{'$set':{'html':new_html}},upsert=True)
    {'updatedExisting': True, u'nModified': 0, u'ok': 1, u'n': 1}
    >>> db.webpage.find({'_id':url}).count()
    1
    >>> 
    

    MongoDB官方文档:http://docs.mongodb.org/manual/

    3.4MongoDB缓存实现

    现在我们已经准备好创建基于MongoDB的缓存了,这里使用了和之前的DiskCache类相同的接口。我们在下面构造方法中创建了timestamp索引,在达到给定的时间戳之后,MongoDB的这一便捷功能可以自动过期删除记录。

    import pickle
    from datetime import datetime, timedelta
    from pymongo import MongoClient
    
    class MongoCache:
        def __init__(self, client=None, expires=timedelta(days=30)):
            """
            client: mongo database client
            expires: timedelta of amount of time before a cache entry is considered expired
            """
            # if a client object is not passed 
            # then try connecting to mongodb at the default localhost port 
            self.client = MongoClient('localhost', 27017) if client is None else client
            #create collection to store cached webpages,
            # which is the equivalent of a table in a relational database
            self.db = self.client.cache
            self.db.webpage.create_index('timestamp', expireAfterSeconds=expires.total_seconds())
    
        def __getitem__(self, url):
            """Load value at this URL
            """
            record = self.db.webpage.find_one({'_id': url})
            if record:
                return record['result']
            else:
                raise KeyError(url + ' does not exist')
    
        def __setitem__(self, url, result):
            """Save value for this URL
            """
            record = {'result': result, 'timestamp': datetime.utcnow()}
            self.db.webpage.update({'_id': url}, {'$set': record}, upsert=True)
    

    下面我们来测试一下这个MongoCache类,我们用默认0时间间隔timedelta()对象进行测试,此时记录创建后应该会马上会被删除,但实际却没有。这是因为MongoDB运行机制造成的,MongoDB后台运行了一个每分钟检查一次过期记录的任务。所以我们可以再等一分钟,就会发现缓存过期机制已经运行成功了。

    >>> from mongo_cache import MongoCache
    >>> from datetime import timedelta
    >>> cache=MongoCache(expires=timedelta())
    >>> result={'html':'.....'}
    >>> cache[url]=result
    >>> cache[url]
    {'html': '.....'}
    >>> cache[url]
    {'html': '.....'}
    >>> import time
    >>> import time;time.sleep(60)
    >>> cache[url]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "mongo_cache.py", line 62, in __getitem__
        raise KeyError(url + ' does not exist')
    KeyError: 'http://www.baidu.com/view/China-47 does not exist'
    >>> 
    

    3.5压缩存储

    import pickle
    import zlib
    from bson.binary import Binary
    
    class MongoCache:
        def __getitem__(self, url):
            """Load value at this URL
            """
            record = self.db.webpage.find_one({'_id': url})
            if record:
                #return record['result']
                return pickle.loads(zlib.decompress(record['result']))
            else:
                raise KeyError(url + ' does not exist')
    
        def __setitem__(self, url, result):
            """Save value for this URL
            """
            #record = {'result': result, 'timestamp': datetime.utcnow()}
            record = {'result': Binary(zlib.compress(pickle.dumps(result))), 'timestamp': datetime.utcnow()}
            self.db.webpage.update({'_id': url}, {'$set': record}, upsert=True)
    

    3.6缓存测试

    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ time python 3mongo_cache.py 
    Downloading: http://127.0.0.1:8000/places/
    Downloading: http://127.0.0.1:8000/places/default/index/1
    Downloading: http://127.0.0.1:8000/places/default/index/2
    ...
    Downloading: http://127.0.0.1:8000/places/default/view/Algeria-4
    Downloading: http://127.0.0.1:8000/places/default/view/Albania-3
    Downloading: http://127.0.0.1:8000/places/default/view/Aland-Islands-2
    Downloading: http://127.0.0.1:8000/places/default/view/Afghanistan-1
    
    real	0m59.239s
    user	0m1.164s
    sys	0m0.108s
    
    
    wu_being@ubuntukylin64:~/GitHub/WebScrapingWithPython/3.下载缓存$ time python 3mongo_cache.py 
    
    real	0m0.695s
    user	0m0.408s
    sys	0m0.044s
    
    

    可以看出,用数据库缓存的读取时间是磁盘缓存的两倍,但成功地避免了磁盘缓存的缺点。

    3.7MongoDB缓存完整代码

    try:
        import cPickle as pickle
    except ImportError:
        import pickle
    import zlib
    from datetime import datetime, timedelta
    from pymongo import MongoClient
    from bson.binary import Binary
    
    from link_crawler import link_crawler
    
    
    class MongoCache:
        """
        Wrapper around MongoDB to cache downloads
    
        >>> cache = MongoCache()
        >>> cache.clear()
        >>> url = 'http://example.webscraping.com'
        >>> result = {'html': '...'}
        >>> cache[url] = result
        >>> cache[url]['html'] == result['html']
        True
        >>> cache = MongoCache(expires=timedelta())
        >>> cache[url] = result
        >>> # every 60 seconds is purged http://docs.mongodb.org/manual/core/index-ttl/
        >>> import time; time.sleep(60)
        >>> cache[url] 
        Traceback (most recent call last):
         ...
        KeyError: 'http://example.webscraping.com does not exist'
        """
        def __init__(self, client=None, expires=timedelta(days=30)):
            """
            client: mongo database client
            expires: timedelta of amount of time before a cache entry is considered expired
            """
            # if a client object is not passed 
            # then try connecting to mongodb at the default localhost port 
            self.client = MongoClient('localhost', 27017) if client is None else client
            #create collection to store cached webpages,
            # which is the equivalent of a table in a relational database
            self.db = self.client.cache
            self.db.webpage.create_index('timestamp100s', expireAfterSeconds=expires.total_seconds())		#timestamp
    
        def __contains__(self, url):
            try:
                self[url]
            except KeyError:
                return False
            else:
                return True
        
        def __getitem__(self, url):
            """Load value at this URL
            """
            record = self.db.webpage.find_one({'_id': url})
            if record:
                #return record['result']
                return pickle.loads(zlib.decompress(record['result']))
            else:
                raise KeyError(url + ' does not exist')
    
    
        def __setitem__(self, url, result):
            """Save value for this URL
            """
            #record = {'result': result, 'timestamp': datetime.utcnow()}
            record = {'result': Binary(zlib.compress(pickle.dumps(result))), 'timestamp100s': datetime.utcnow()}	#timestamp
            self.db.webpage.update({'_id': url}, {'$set': record}, upsert=True)
    
    
        def clear(self):
            self.db.webpage.drop()
            print 'drop() successful'
    
    
    
    if __name__ == '__main__':	
        #link_crawler('http://example.webscraping.com/', '/(index|view)', cache=MongoCache())
        #link_crawler('http://127.0.0.1:8000/places/', '/places/default/(index|view)/', cache=MongoCache())
        link_crawler('http://127.0.0.1:8000/places/', '/places/default/(index|view)/', cache=MongoCache(expires=timedelta(seconds=100)))
    
    

    Wu_Being 博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
    《【Python爬虫3】在下载的本地缓存做爬虫》http://blog.csdn.net/u014134180/article/details/55506984

    展开全文
  • 前言:最近写了一个文件下载的接口,我测试下能下载文件后就提交了到了生产,然后然后使用下载功能的小伙伴找到我说下载有bug,我明明修改了文件内容重新下载后还是以前的数据,吓得我赶紧去看代码,终于让我发现了...

    前言:最近写了一个文件下载的接口,我测试下能下载文件后就提交了到了生产,然后然后使用下载功能的小伙伴找到我说下载有bug,我明明修改了文件内容重新下载后还是以前的数据,吓得我赶紧去看代码,终于让我发现了问题。

    一、基础框架

    后端:python3.8 + flask + flask-restful

    前端:vue

    二、场景:有一个功能界面需要上传下载文件,且支持更改新的上传文件

    文件上传:通过request.files 获取到文件流,os.makedirs创建文件存储目录, file.save(filepath)保存,另外保存一条文件上传记录,涵盖文件名,文件保存路径等等,貌似一切都ok

    文件下载: 通过前端界面获取到当前记录的文件名,通过文件名查找文件信息,找到文件目录filepath

    response = make_response(send_from_directory(filepath, fullflname, as_attachment=True))
    获取到response对象,返回文件流

    三、当修改新的上传文件为B时,点击下载 还是获取的之前文件A,清理浏览器缓存后,点击下载,文件为B,这才是正确的
    在这里插入图片描述

    四、经过一系列资料查询,得知,谷歌会对文件下载进行缓存的

    解决方法: 在下载获取到response对象后,增加headers 设置 cache-controll = “no-store“
    在这里插入图片描述
    重新下载文件查看接口请求头发现问题已经解决了
    在这里插入图片描述

    五、Cache-Control详解

    服务器标记资源有效期使用的头字段是“Cache-Control”,里面的值“max-age=43200”就是资源的有效时间,相当于告诉浏览器,“这个页面只能缓存 43200秒,之后就算是过期,不能用。
    no-cache — 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据 的应用(不惜牺牲使用缓存的所有好处)。
    Pragma 当”no-cache”出现在请求消息中时,应用程序应当向原始服务器推送此请求,即使它已经在上次请求时已经缓存了一份拷贝。这样将保证客户端能接收到最权威的回应。它也用来在客户端发现其缓存中拷贝不可用或过期时,对拷贝进行强制刷新。
    max-age>0:直接从游览器缓存中 提取。
    max-age<=0:向server 发送http 请求确认 ,该资源是否有修改,有的话 返回200 ,无的话 返回304。

    展开全文
  • Android中缓存的必要性: 1、没有缓存的弊端: ...流量开销:对于客户端——服务器端应用,从远程获取图片算是经常要用的一个...异步下载+本地缓存 2、缓存带来的好处: 1. 服务器的压力大大减小
  • python爬虫-->下载缓存

    千次阅读 2017-07-03 13:25:07
    上一篇博文中,我们讲解了如何从下载的网页中抓取自己感兴趣的数据,以及如何把获取的数据保存到表格中。但是如果我们突然又想抓取另外...前面我们在download网页时,每次下载都会throttle一下,如果我们已经有缓存,从
  • 一、 OSCache 下载地址: ...从http://www.opensymphony.com/oscache/download.html下载合适的OSCache版本, 解压缩下载的文件到指定目录 。  2、新建立一个web应用  3、将OSCache集成
  • HTTPWeb缓存

    万次阅读 2017-03-03 23:06:12
    你必须指派一名忍者来传达建交文书,为确保文书的完好,你指派的忍者必须非常可靠,无论遇到多么危险的情况,都准确完好地将文书传达到风影手里。这名忍者叫卡卡西,啊,叫HTTP(数据传输协议)。 现在知道了吧...
  • java 缓存

    千次阅读 2016-02-29 16:24:50
    Java缓存所谓缓存,就是将程序或...1、常用内存缓存实现简单,通常使用static关键字实现一个静态的Map,将从数据库中查询出的值放入缓存对象内,当再次需要从数据库中取出相同的值时直接从此Map中取出数据即可,避免了
  • Glide默认是用InternalCacheDiskCacheFactory类来创建硬盘缓存的,这个类会在应用的内部缓存目录下面创建一个最大容量250MB的缓存文件夹,使用这个缓存目录而不用sd卡,意味着除了本应用之外,其他应用是不能访问...
  • npm install中的缓存和资源拉取机制

    千次阅读 2020-04-25 14:04:53
    npm config list //查看基本配置 npm config list -l //查看所有配置 npm@5之前的版本在缓存存储使用...npm install或npm update命令,从 远程仓库下载压缩包之后,都存放在本地的缓存目录。 在 Linux 或 Mac 默...
  • web缓存原理分析

    千次阅读 2018-03-22 14:29:18
    为什么2月份会停更一个月的博客呢? … 过年是一个原因, ... 上班真的很辛苦, 每天感觉挺累的, 书也好久没有看了, 今天恰逢没有新需求, 项目在提测之际来写下一遍转载的文章, 主要记录一下在各处搜索到的关于web缓存...
  • Android 文件外/内部存储的获取各种存储目录路径

    万次阅读 多人点赞 2018-06-12 14:51:50
    前言 对于任何一个应用来说,无论是PC端应用还是Android应用,存储肯定是必可少的。对于很多做Android开发的同学来说,可能认为文件存储很简单,调用一些诸如getFilesDir,getExternalStorageDirectory方法行了,...
  • 安卓中的缓存包括两种情况即内存缓存与磁盘缓存,其中内存缓存主要是使用LruCache这个类,其中内存缓存我在【安卓中的缓存策略系列】安卓缓存策略之内存缓存LruCache中已经进行过详细讲解,如看官还没看过此博客,...
  • Java缓存机制

    万次阅读 多人点赞 2018-08-21 02:53:25
    Java中实现缓存的方式有很多,比如用static hashMap基于内存缓存的jvm内置缓存,简单实用,保对象的有效性周期无法控制,容易造成内存急剧上升。常用的有Oscache(主要针对jsp页面),Ehcache(主要针对数据库...
  • Bitmap的高效加载LruCache缓存

    千次阅读 2017-04-18 00:07:56
    DiskLruCache并不能通过构造方法来创建,它提供open方法创建自身 public static DiskLruCache open(File directory,int appVersion, int valueCount, long maxSize) //directory表示磁盘缓存在文件系统中的存储...
  • 缓存-redis 三种模式搭建运行原理

    千次阅读 2018-10-15 10:11:10
    redis 缓存 主从 哨兵 集群
  • Web缓存

    千次阅读 2015-11-17 15:01:43
    由于测试的同事比较细心专业,发现了项目实现中一些效率低下的环节,比如在线预览图片没有经过压缩、重开打开同一张图片没有有效利用Web缓存等问题。而这些细节问题往往在做项目架构时,容易因为时间紧张等等因素...
  • 导语在web项目开发中,...有些web开发经验的同学应该马上会想到,可能是资源发布出了岔子导致没有实际发布成功,更大的可能是老的资源被缓存了。说到web缓存,首先我们要弄清它是什么。Web缓存可以理解为Web资源在...
  • 然而,有时候虽然应用缓存刷新了,但是还是不能看到最新的:那么有可能是使用了本地存储。 常用的本地存储有DOM StoragewebSQLindexDB三种 ,细节可以参考这篇文章 ...
  • 第三方缓存软件:Redis Memcached

    千次阅读 2016-04-06 16:03:15
    memcachedredis相同点:都是以键值对的形式来存储数据,通俗讲就是一个大的hashtable 缓存数据都是存在内存中 key-value 不同点: Memcached: 1、一个key所对应的值必须要通过客户端序列化成二进制流存储 (即:...
  • 缓存Cache详解

    万次阅读 2018-02-11 13:05:21
    全面介绍有关 缓存 cache以及利用PHP写...接着,如果有另外一个使用相同URL发送请求,他能够使用之前已经保存下来的反馈文件,而不是再次向服务器发出请求。有两个主要的理由让人们使用缓存:1.减少延迟 — 因为...
  • 关于CDN与缓存(浏览器CDN)

    千次阅读 2018-11-12 02:32:20
    本文目录:一、引入  二、CDN定义  三、关于缓存  四、浏览器缓存 一、引入 客户端直接从源站点获取数据,当服务器访问量大时会影响访问速度,进而影响用户体验,且无法保证客户端与源站点间的距离足够短,...
  • mybatis是一个持久层框架,是Apache下的开源项目,前身是ibatis,是一个完全的ORM框架,mybatis提供输入输出的映射,需要程序员自己手动写SQL语句,mybatis重点对SQL语句进行灵活操作。适用场合:需求变化频繁,...
  • Redis缓存技术

    万次阅读 多人点赞 2019-01-17 21:02:12
    文章目录NoSQL 产品(key-value)1、Redis功能介绍2、企业缓存产品介绍3、Redis使用场景介绍4、Redis安装部署5、Redis基本管理操作5.1 基础配置文件介绍:5.2 redis安全配置5.3在线查看修改配置5.4 redis持久化(内存...
  • 代理缓存服务-squid

    千次阅读 2017-01-19 17:04:12
     代理缓存服务器:接收到用户请求后,自动下载指定资源并存储到本地服务器,以后用户请求相同资源时,直接把存储在本地服务器的资源直接传给用户。  Squid服务程序支持HTTP、FTP、SSL等多种协议的数据缓存,支持...
  • 如果你更关心细节实现则完全不必耐心看完本文,后面参考文档更多深入阅读部分可能是你更需要的内容。 什么是Web缓存,为什么要使用它?Web缓存的类型: 浏览器缓存;代理服务器缓存; Web缓存无害吗?为什么要...
  • 高速缓存

    千次阅读 2008-09-27 14:12:00
    上一页 目录 索引 下一页 Sun
  • CDN 缓存与浏览器缓存

    千次阅读 2020-02-29 23:28:34
    目前又拍云 CDN 可以提供基于文件后缀、目录等多个维度来指定 CDN 缓存和浏览器时间,为开发者提供更精细化的缓存管理服务。针对开发者不同的业务需求,又拍云提供了多项预制模板,方便快捷的来帮助开发者进行数据...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 80,275
精华内容 32,110
关键字:

下载目录和缓存目录不能相同