爬虫系列:读取文档

上一篇文章我们介绍了如何通过 MySQL 存储 Python 爬虫采集的内容,以及使用Python 与 MySQL 交互,这篇文章我们介绍如何通过 Python 读取文档。

虽然互联网在20世纪60年代末期就已经以不同的形式出现,但是 HTML 直到1992年才问世。在此之前,互联网上基本就是收发邮件传输文件;今天看到的网页概念那时还没有。总之,互联网并不是一个 HTML 页面的集合。他是一个信息集合,而 HTML 文件只是展示信息的一个框架而已。如果我们的爬虫不能读取其他类型的文件,包括纯文本、PDF、图像、视频、邮件等,我们将会失去很大一部分数据。

本篇文章我将详细介绍文档处理的相关内容,包括把文件下载到文件夹里,以及读取文档并提取数据。同时介绍文档不同编码类型,让程序可以读取非英文 HTML 页面。

文档编码

文档编码是一种告诉程序——无论是计算机的操作系统还是 Python 代码——读取文档的规则。文档的编码方式通常可以根据文件的扩展名进行判断,虽然文件扩展名并不是由编码确定的,而是由开发者确定的。例如,如果我把 python_logo.jpg 存储为 python_logo.txt 不会出现任何问题,但当我使用文本编辑器打开的时候就有问题了。这种情况很少见,如果要正确的读取一个文档,必须知道它的扩展名。

从最底层的角度看,所有文档都是由0和1编码而成的。而在高层(贴近用户的层级)编码算法会定义“每个字符多少位”或“每个像素的颜色值用多少位”(图像文件里)之类的事情,在哪里你会遇到一些数据压缩算法或体积缩减算法,比如 PNG 图像编码格式(一种无损压缩的位图图形格式)。

虽然我们第一次处理这些非 HTML 格式的文件会觉得没有任何经验,但是只要安装了合适的库,Python 就可以帮你处理任意类型的文档。纯文本文件、视频文件和图像文件的唯一区别,就是他们的0和1面向用户的转换方式不同。

纯文本

虽然把文件存储为在线的纯文本格式并不常见,但是一些简易的网站,或者有大量纯文本文件的“旧式学术”(old-shcool)网站经常会这么做。例如,互联网工程任务组(Internet Engineering Task Force,IETF)网站就存储了 IETF 发表过的所有文档,包含 HTML、PDF 和纯文本格式(例如 rfc4437)。大多数浏览器都可以很好的显示纯文本文件,采集这些纯文本文件的网站不会遇到什么问题。

下面一个 Python 读取纯文本示例,展示了如何读取 https://image.pdflibr.com/crawler/blog/tencent_cloud_ip_range.txt 地址的纯文本文件。

from requests import Session


class ReadDocument(object):
    def __init__(self):
        self._text_url = 'https://image.pdflibr.com/crawler/blog/tencent_cloud_ip_range.txt'

    def read_text_document(self):
        init_session = Session()
        response = init_session.get(url=self._text_url)
        response.encoding = 'utf-8'
        print(response.text)


if __name__ == '__main__':
    ReadDocument().read_text_document()

这段 Python 代码,我们直接读取文本内容,并对文本从新编码,如果使用原来的编码方式,显示为乱码。一旦纯文本被读取成字符串,你就只能用普通的 Python 字符串方法分析他了。当然这没做有个缺点,就是你不能对字符串使用 HTML 标签,去定位那些你真正需要的文字,避开那些你不需要的文字。如果你现在需要在纯文本里面找到你需要的信息还是有困难的。

文本编码和全球互联网

记得我前面说过,如果你想正确的读取一个文件,知道它的扩展名就可以了。不过非常奇怪的是,这条规则不能应用到最基本的文档格式:.txt 文件。

大多数时候前面的方法读取纯文本文件都没有问题。但是,护粮网上的文本文件会比较复杂。下面介绍一些英文和非英文编码的基础知识,包括 ASCII、Unicode 和 ISO 编码,以及应对的处理方法。

编码类型简介

20世纪90年代,一个叫 Unicode 联盟(The Unicode Consortium)的非盈利组织尝试将地球所有的用于书写的符号经行统一编码。其目标包括拉丁字母、斯拉夫字母、中国象形文字(象形)、数字和逻辑符号,甚至表情和“杂项”(misellaneous)符号,比如生化危机标记(☣)和和平符号(☮)等。

UTF-8(8-bit Unicode Transformation Format) 是一种针对 Unicode 的可变长度字符编码,也是一种前缀码。它可以用一至四个字节对 Unicode 字符集中的所有有效编码点进行编码,属于U nicode 标准的一部分,最初由肯·汤普逊和罗布·派克提出。

一个最常见的错误就是 UTF-8 把所有的字符都存储成8位。其实“8位”显示一个字符所需要的最小位数,而不是最大位数。(如果 UTF-8 的每个字符都是8位,,那一共只能存储2^8个字符,这对于中文和其他字符显然不够。)

真实情况是,UTF-8每个字符开头都有一个标记表示“这个字符只用一个字节”或“那个字符需要两个字节”,一个字符最多可以是四个字节。由于这四个字节里面还包含一部分设置信息,用来决定多少字节用来做字符编码,所以全部的32位(32位=4字节x8位/字节)并不都会用,其实最多使用21位,也就是总共2097152种可能里面可以有1114112个字符。

虽然对很多程序来说,Unicode 都是上帝的礼物(godsend),但是有很多习惯都很难改变, ASCII 依然是许多英文用户的主要选择。

ASCII 是20世纪60年代开始使用的文字编码标准,每个字符7位,一共2^7,即128个字符。这个对于拉丁字母(包括大小写)、标点符号和英文键盘上的所有符号,都是够用的。

在20世纪60年代,存储的文件用7位编码和用8位编码之间的差异是巨大的,因为内存非常昂贵。当时,计算机科学家们为了需要增加一位获得一个漂亮的二进制数(用8位),还是在文件里用更少的位数(7位)费尽心机。最终,7位编码胜利了。但是,在新式计算方式中,每个7位码前面都补充(pad)了一个“0”,留给我们最坏的结果是,文件大了14%(编码由7为变成8位,体积增加了14%),并且由于只有128个字符,缺乏灵活性。

在 UTF-8 设计过程中,设计师决定利用 ASCII 文档里的“填充位”,让所有“0”开头的字节表示这个字符自用1个字节,从而把 ASCII 和 UTF-8 编码完美的结合在一起。因此,下面的字符在 ASCII 和 UTF-8 两种编码方式中都是有效的:

01000001 - A
01000010 - B
01000011 - C

除了 UTF-8,还有其他 UTF 标准,像 UTF-16、UTF-24、UTF-32,不过很少用这些编码标准对文件经行编码,所以在此不做过多介绍。

Python 编码示例

在上面的实例中我们通过 Python 的 requests 库读取了远程的文档内容,但是显示的是乱码,无法阅读,我们对文档内容重新设置编码,使其正常显示,示例如下:

from requests import Session


class ReadDocument(object):
    def __init__(self):
        self._text_url = 'https://image.pdflibr.com/crawler/blog/tencent_cloud_ip_range.txt'

    def read_text_document(self):
        init_session = Session()
        response = init_session.get(url=self._text_url)
        # 显示原来文本的编码方式
        print(response.encoding)
        # 将文本设置成 utf-8 的编码方式
        response.encoding = 'utf-8'
        print(response.text)
        # 显示改变编码后的编码方式
        print(response.encoding)


if __name__ == '__main__':
    ReadDocument().read_text_document()

上面的代码首先打印出了原来文档采用的编码方式,之后将文档重设成 UTF-8 的编码方式,之后再次打印文档内容,再次显示被编码后的文档编码。

你可能打算以后使用网络爬虫全部采用 UTF-8 编码读取内容,毕竟 UTF-8 也可以完美的处理 ASCII 编码。但是,要记住还有9%的网站使用 ISO 编码格式。所以在处理纯文本文档的时候,想用一种编码搞定所有文档是不可能的。有一些库可以检查文档的编码,或是对文档编码经行估计,不过效果并不是很好。

处理 HTML 的时候,网站其实会在 <head> 部分显示页面使用的编码格式。大多数网站,尤其是英文网站,都会带上这样的标签:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

如果你要做很多网络数据采集工作,尤其是面对国际网站时,建议先看看 meta 标签的内容,用网站推荐的方式读取页面内容。

python爬虫与项目实战,网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成。 随着网络的迅速发展,万维网成为大量信息的载体,如何有效地提取并利用这些信息成为一个巨大的挑战。搜索引擎(Search Engine),例如传统的通用搜索引擎AltaVista,Yahoo!Google等,作为一个辅助人们检索信息的工具成为用户访问万维网的入口指南。但是,这些通用性搜索引擎也存在着一定的局限性,如: (1)不同领域、不同背景的用户往往具有不同的检索目的需求,通用搜索引擎所返回的结果包含大量用户不关心的网页。 (2)通用搜索引擎的目标是尽可能大的网络覆盖率,有限的搜索引擎服务器资源与无限的网络数据资源之间的矛盾将进一步加深。 (3)万维网数据形式的丰富网络技术的不断发展,图片、数据库、音频、视频多媒体等不同数据大量出现,通用搜索引擎往往对这些信息含量密集且具有一定结构的数据无能为力,不能很好地发现获取。 (4)通用搜索引擎大多提供基于关键字的检索,难以支持根据语义信息提出的查询。 网络爬虫 为了解决上述问题,定向抓取相关网页资源的聚焦爬虫应运而生。聚焦爬虫是一个自动下载网页的程序,它根据既定的抓取目标,有选择的访问万维网上的网页与相关的链接,获取所需要的信息。与通用爬虫(general purpose web crawler)不同,聚焦爬虫并不追求大的覆盖,而将目标定为抓取与某一特定主题内容相关的网页,为面向主题的用户查询准备数据资源。 传统爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统的一定停止条件。聚焦爬虫的工作流程较为复杂,需要根据一定的网页分析算法过滤与主题无关的链接,保留有用的链接并将其放入等待抓取的URL队列。然后,它将根据一定的搜索策略从队列中选择下一步要抓取的网页URL,并重复上述过程,直到达到系统的某一条件时停止。另外,所有被爬虫抓取的网页将会被系统存贮,进行一定的分析、过滤,并建立索引,以便之后的查询检索;对于聚焦爬虫来说,这一过程所得到的分析结果还可能对以后的抓取过程给出反馈指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值