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

爬虫系列:读取文档

原创
作者头像
太后
发布2021-12-21 15:43:38
1.1K0
发布2021-12-21 15:43:38
举报
文章被收录于专栏:短信接收服务

上一篇文章我们介绍了如何通过 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 和纯文本格式(例如 https://datatracker.ietf.org/doc/html/rfc4437.txt)。大多数浏览器都可以很好的显示纯文本文件,采集这些纯文本文件的网站不会遇到什么问题。

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

代码语言:txt
复制
from requests import Session
代码语言:txt
复制
class ReadDocument(object):
代码语言:txt
复制
    def __init__(self):
代码语言:txt
复制
        self._text_url = 'https://image.pdflibr.com/crawler/blog/tencent_cloud_ip_range.txt'
代码语言:txt
复制
    def read_text_document(self):
代码语言:txt
复制
        init_session = Session()
代码语言:txt
复制
        response = init_session.get(url=self._text_url)
代码语言:txt
复制
        response.encoding = 'utf-8'
代码语言:txt
复制
        print(response.text)
代码语言:txt
复制
if __name__ == '__main__':
代码语言:txt
复制
    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 两种编码方式中都是有效的:

代码语言:txt
复制
01000001 - A
代码语言:txt
复制
01000010 - B
代码语言:txt
复制
01000011 - C

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

Python 编码示例

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

代码语言:txt
复制
from requests import Session
代码语言:txt
复制
class ReadDocument(object):
代码语言:txt
复制
    def __init__(self):
代码语言:txt
复制
        self._text_url = 'https://image.pdflibr.com/crawler/blog/tencent_cloud_ip_range.txt'
代码语言:txt
复制
    def read_text_document(self):
代码语言:txt
复制
        init_session = Session()
代码语言:txt
复制
        response = init_session.get(url=self._text_url)
代码语言:txt
复制
        # 显示原来文本的编码方式
代码语言:txt
复制
        print(response.encoding)
代码语言:txt
复制
        # 将文本设置成 utf-8 的编码方式
代码语言:txt
复制
        response.encoding = 'utf-8'
代码语言:txt
复制
        print(response.text)
代码语言:txt
复制
        # 显示改变编码后的编码方式
代码语言:txt
复制
        print(response.encoding)
代码语言:txt
复制
if __name__ == '__main__':
代码语言:txt
复制
    ReadDocument().read_text_document()

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

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

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

代码语言:txt
复制
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文档编码
  • 纯文本
  • 文本编码和全球互联网
    • 编码类型简介
      • Python 编码示例
      相关产品与服务
      云数据库 MySQL
      腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档