乐趣区

关于python:爬虫系列数据清洗

上一期咱们解说了应用 Python 读取 CSV、PDF、Word 文档相干内容。

后面咱们曾经介绍了网络数据采集的一些基础知识,当初咱们将进入 高级数据采集 局部。到目前为止,咱们创立的网络爬虫都不是特地给力,如果网络服务器不能立刻提供款式标准的信息,爬虫就不能采集正确的数据。如果爬虫只能采集那些不言而喻的信息,不通过解决就存储起来,那么迟早要被登录表单、网页交互以及 Javascript 困住手脚。总之,目前爬虫还没有足够的实力去采集各种数据,只能解决那些违心被采集的信息。

高级数据采集 局部就是要帮你剖析原始数据,获取暗藏在数据背地的故事——网站的实在故事其实都暗藏在 Javascript、登录表单和网站反爬措施背地。

数据荡涤

到目前为止,咱们都没有解决过那些款式不标准的数据,要么应用的是款式标准的数据源,要么就是放弃款式不合乎咱们预期的数据。但在网络数据采集中,你通常无奈对采集的数据款式太挑剔。

因为谬误的标点符号、大小写字母不统一、断行和拼写错误等问题,凌乱的数据(dirty data)是网络中的大问题。上面咱们就通过工具和技术,通过扭转代码的编写形式,帮你从源头控制数据凌乱的问题,并且对曾经入库的数据经行荡涤。

编写代码荡涤数据

和编写异样解决代码一样,你应该学会编写预防型代码来解决意外状况。

在语言学中有一个模型叫 n-gram,示意文本或语言中的 n 个间断的单词组成的序列。再进行自然语言剖析时,用 n-gram 或者寻找罕用词组,就能够很容易的把一句话分成若干个文字片段。

在接下来的内容咱们将重点介绍如何获取格局正当的 n-gram。

上面的代码返回维基百科词条“Python programming language”的 2-gram 列表:

from utils import connection_util


class DataCleaning(object):
    def __init__(self):
        self._target_url = 'https://en.wikipedia.org/wiki/python_(programming_language)'
        self._init_connection = connection_util.ProcessConnection()

    @staticmethod
    def ngrams(input_text, n):
        split_result = input_text.split(' ')
        output = []
        for i in range(len(split_result) - n + 1):
            output.append(split_result[i:i + n])
        return output

    def get_result(self):
        # 连贯指标网站,获取内容
        get_content = self._init_connection.init_connection(self._target_url)
        if get_content:
            content = get_content.find("div", {"id": "mw-content-text"}).get_text()
            ngrams = self.ngrams(content, 2)
            print(ngrams)
            print("2-grams count is:" + str(len(ngrams)))


if __name__ == '__main__':
    DataCleaning().get_result()

ngrams 函数把一个待处理的字符串分成单词序列(假如所有单词依照空格离开),而后减少到 n-gram 模型造成以每个单词开始的二元数组。

运行程序之后,会有一些凌乱的数据,例如:

['web', 'frameworks\nBottle\nCherryPy\nCubicWeb\nDjango\nFastAPI\nFlask\nGrok\nNagare\nNevow\nPylons\nPyramid\nQuixote\nTACTIC\nTornado\nTurboGears\nTwistedWeb\nWebware\nweb2py\nZope']

另外,应为每个单词(除了最初一个单词)都要创立一个 2-gram 序列,所以这个词条里共有 11680 个 2-gram 序列。这并不是一个十分便于管理的数据集!

咱们首先应用一些正则表达式来移除转义字符(\n), 再把 Unicode 字符过滤掉。咱们能够通过上面的函数对之前输入的内容经行清理:

import re

from utils import connection_util


class DataCleaning(object):
    def __init__(self):
        self._target_url = 'https://en.wikipedia.org/wiki/python_(programming_language)'
        self._init_connection = connection_util.ProcessConnection()

    @staticmethod
    def ngrams(input, n):
        input = re.sub('\n+', " ", input)
        input = re.sub('+', " ", input)
        input = bytes(input, "UTF-8")
        input = input.decode("ascii", "ignore")
        print(input)
        input = input.split(' ')
        output = []
        for i in range(len(input) - n + 1):
            output.append(input[i:i + n])
        return output

    def get_result(self):
        # 连贯指标网站,获取内容
        get_content = self._init_connection.init_connection(self._target_url)
        if get_content:
            content = get_content.find("div", {"id": "mw-content-text"}).get_text()
            ngrams = self.ngrams(content, 2)
            print(ngrams)
            print("2-grams count is:" + str(len(ngrams)))


if __name__ == '__main__':
    DataCleaning().get_result()

下面的代码首先将内容中的换行符(或者多个换行符)替换成空格,而后把间断的多个空格替换成一个空格,确保所有单词之间只有一个空格。最初,把内容转换成 UTF-8 格局以打消转义字符。

通过下面的几步,咱们曾经能够大大改善输入后果了,然而还是有一些问题:

ALGOL 68,[13] APL,[14] C,[15] C++,[16] CLU,[17] Dylan,[18] Haskell,[19] Icon,[20] Java,[21] Lisp,[22] Modula-3,[16] Perl, Standard ML[14]InfluencedApache Groovy

因而,须要减少一些规定来解决数据。咱们能够定制一些规定让数据变得更标准:

  • 剔除单字符的“单词”,除非这个单词是“a”或“i”;
  • 剔除维基百科的援用标记(方括号包裹的数字,入[1])
  • 剔除标点符号

当初“荡涤工作”列表变得越来越长,让咱们把规定都移出来,新建一个函数:

import re
import string

def ngrams(self, input, n):
    input = self.clean_input(input)
    output = []
    for i in range(len(input) - n + 1):
        output.append(input[i:i + n])
    return output

@staticmethod
def clean_input(input):
    input = re.sub('\n+', " ", input)
    input = re.sub('\[[0-9]*\]', "", input)
    input = re.sub('+', " ", input)
    input = bytes(input, "UTF-8")
    input = input.decode("ascii", "ignore")
    input = input.split(' ')
    clean_input = []
    for item in input:
        # string.punctuation 获取所有的标点符号
        item = item.strip(string.punctuation)
        if len(item) > 1 or (item.lower() == 'a' or item.lower() == 'i'):
            clean_input.append(item)
    return clean_input

这里用 import string 和 string.punctuation 来获取 Python 所有的标点符号。咱们能够在 Python 命令行外面查看标点符号有哪些:

import string
print(string.punctuation)
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

在循环体中用 item.strip(string.punctuation) 对内容中的所有单词进行荡涤,单词两端的任何标点符号都会被去掉,但带连字符的单词(连字符在单词外部)任然会保留。

本期对于数据荡涤就是如上内容,在接下来的内容中我会解说数据标准化,以及存储的数据如何荡涤。

以上的演示源代码托管于 Gihub,地址:https://github.com/sycct/Scra…

如果有任何问题,欢送大家 issue。

退出移动版