前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫系列:存储媒体文件

爬虫系列:存储媒体文件

原创
作者头像
太后
修改2021-11-08 09:21:04
4070
修改2021-11-08 09:21:04
举报
文章被收录于专栏:短信接收服务短信接收服务

本期爬虫系列主要讲解爬虫采集完成数据之后,我们应该怎么存储,以及用什么样的方式存储数据。

虽然在命令行里显示结果很有意思,但是随着数据不断增多,并且需要对数据分析时,将数据打印到命令行就不是办法了。为了可以远程使用大部分网络爬虫,你还需要把采集到的数据存储起来。

本篇文章介绍的数据存储方式,绝大多数应用程序都适用。如果你准备创建一个网站的后端服务或者创建自己的 API,那么可能需要把数据写入数据库。如果你需要一个快速简单的方法收集网上的文档,然后保存到你的硬盘里,那么可能需要创建一个文件流(file stream)来实现。

存储媒体文件

存储媒体文件主要有两种方式:只获取文件 URL 链接,或者直接把源文件下载下来。你可以通过媒体文件所在的 URL 链接直接引用它。这样做的优点如下:

  • 爬虫运行得更快,耗费得流量更少,因为只要链接,不需要下载文件;
  • 可以节省很多存储空间,因为只需要存储 URL 链接就可以了;
  • 存储 URL 的代码更容易编写,也不需要文件下载代码;
  • 不下载文件能够降低目标服务器的负载。

保存媒体文件存在的缺点:

  • 这些内嵌在你网站或应用中的外站 URL 链接称为盗链(hotlinking),使用盗链可能让你麻烦不断,每个网站都会实施防盗链措施;
  • 因为你的链接放在别人的服务器上,所以你的应用就跟着别人的节奏运行了;
  • 盗链是很容易改变的。如果你把盗链图片放在博客上,要是被对方服务器发现,就可能被恶搞。如果你把 URL 链接存储起来准备以后再使用,可能用的时候链接已经失效了,或者变成了完全无关的内容;
  • 现实中的浏览器不仅会请求 HTML 页面并切换页面,它们也会下载访问页面上所有的资源。下载文件会让你的爬虫看起来更像人在浏览网站,这样做反而有好处。

如果你还在犹豫究竟是存储文件,还只是存储文件的 URL 链接,可以想想这些文件是要多次使用还是放进数据库之后就只等着“落灰”,再也不会被打开。如果答案是后者,那么最好还是只存储这些文件的 URL 吧。如果答案是前者,那就继续往下看。

代码语言:txt
复制
import requests
代码语言:txt
复制
from utils import connection_util
代码语言:txt
复制
class SaveData(object):
代码语言:txt
复制
    def __init__(self):
代码语言:txt
复制
        self._target_url = 'https://www.pdflibr.com'
代码语言:txt
复制
        self._init_connection = connection_util.ProcessConnection()
代码语言:txt
复制
    def save_image(self):
代码语言:txt
复制
        # 连接目标网站,获取内容
代码语言:txt
复制
        get_content = self._init_connection.init_connection(self._target_url)
代码语言:txt
复制
        if get_content:
代码语言:txt
复制
            imageLocation = get_content.find("img", {"alt": "IP to Location"})["data-src"]
代码语言:txt
复制
            real_path = self._target_url + imageLocation
代码语言:txt
复制
            r = requests.get(real_path)
代码语言:txt
复制
            with open("ip_location.png", 'wb') as f:
代码语言:txt
复制
                f.write(r.content)
代码语言:txt
复制
if __name__ == "__main__":
代码语言:txt
复制
    SaveData().save_image()

这段程序从IP 查询 - 爬虫识别下载一张图片,然后保存在运行程序的文件夹里。

如果你只需要下载一个文件,而且知道如何获取它,以及它的文件类型,这么做就可以了。但是大多数爬虫一天只下载一个文件。下面的程序会把IP 查询 - 爬虫识别上所有 src 属性的文件都下载下来:

代码语言:txt
复制
import os.path
代码语言:txt
复制
from urllib.request import urlretrieve
代码语言:txt
复制
from utils import connection_util
代码语言:txt
复制
class GetAllSrc(object):
代码语言:txt
复制
    def __init__(self):
代码语言:txt
复制
        self._init_download_dir = 'downloaded'
代码语言:txt
复制
        self._baseUrl = 'https://www.pdflibr.com/ip'
代码语言:txt
复制
        self._init_connection = connection_util.ProcessConnection()
代码语言:txt
复制
    def get_absolute_url(self, baseUrl, source):
代码语言:txt
复制
        if source.startswith("https://image."):
代码语言:txt
复制
            url = "https://" + source[14:]
代码语言:txt
复制
        elif source.startswith("https://"):
代码语言:txt
复制
            url = source
代码语言:txt
复制
        elif source.startswith("www."):
代码语言:txt
复制
            url = "https://" + source[4:]
代码语言:txt
复制
        else:
代码语言:txt
复制
            url = source
代码语言:txt
复制
        if baseUrl not in url:
代码语言:txt
复制
            return None
代码语言:txt
复制
        return url
代码语言:txt
复制
    def get_download_path(self, baseUrl, absoluteUrl, download_dir):
代码语言:txt
复制
        path = absoluteUrl.replace("www.", "")
代码语言:txt
复制
        path = path.replace(baseUrl, "")
代码语言:txt
复制
        path = download_dir + path
代码语言:txt
复制
        directory = os.path.dirname(path)
代码语言:txt
复制
        if not os.path.exists(directory):
代码语言:txt
复制
            os.makedirs(directory)
代码语言:txt
复制
        return path
代码语言:txt
复制
    def download_main(self):
代码语言:txt
复制
        get_content = self._init_connection.init_connection(self._baseUrl)
代码语言:txt
复制
        if get_content:
代码语言:txt
复制
            download_list = get_content.findAll(src=True)
代码语言:txt
复制
            for download in download_list:
代码语言:txt
复制
                file_url = self.get_absolute_url(self._baseUrl, download["src"])
代码语言:txt
复制
                if file_url is not None:
代码语言:txt
复制
                    print(file_url)
代码语言:txt
复制
                    urlretrieve(file_url, self.get_download_path(self._baseUrl, file_url, self._init_download_dir))
代码语言:txt
复制
if __name__ == '__main__':
代码语言:txt
复制
    GetAllSrc().download_main()

运行以上代码需要注意:

这个程序会把页面上所有的文件都下载到你硬盘里,可能会包含一些 bash 脚本,.exe 文件,设置可能是恶意软件(malmare)。

这个程序首先选择页面上所有带 src 属性的标签,然后对 URL 链接进行清理和标准化,获得了文件的绝对路径(而且去掉了外链),最后每个文件都会下载到程序所在的 downloaded 文件里。

这里使用 Python 的 os 模块用来获取每个下载文件的目标文件夹,建立完整的路径。os 模块是 Python 与操作系统交互的接口,它可以操作文件路径,创建目录,获取运行进程和环境变量的信息,以及其他系统相关操作。

文章源代码托管于 Github:爬虫系列:存储媒体文件

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 存储媒体文件
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档