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

爬虫系列:数据标准化

原创
作者头像
太后
发布2022-01-12 10:38:00
4280
发布2022-01-12 10:38:00
举报
文章被收录于专栏:短信接收服务

上一期我们介绍了使用 Python 数据清洗的相关方法,本篇文章我们介绍数据标准化的相关方法。

每个人都会遇到一些样式设计不够人性化的网页,比如“请输入你的电话号码,号码格式为 xxx-xxxx-xxxx”。

作为一名优秀的程序员,你可能会问:”为什么不自动对输入的数据进行清洗,去掉非数字内容,然后自动把数据加上分隔符呢?“数据标准化过程要确保清洗后的数据在语言学上是等价的,比如电话号码虽然显示成”134-1234-5678“和”134-12345678“两种形式,但是实际号码是一样的。

还是用上一期的 n-gram 示例,让我们在上面增加一些数据标准化的特征。

上期文章内容的明显问题,就是输出结果中包含太多重复的 2-gram 序列。程序把每个 2-gram 都加入了列表,没有统计过序列的频率。掌握 2-gram 序列的频率,而不只是知道某个序列是否存在,这有助于对比不同的数据清洗和数据标准化算法的效果。如果数据标准化成功了,那么唯一的 n-gram 序列数量就会减少,而 n-gram 序列的总数(任何一个 n-gram 序列和与之重复的序列都被看成一个 n-gram 序列)不变,也就是说,同样数量的 n-gram 序列,经过去重之后“容量(bucket)”会减少。

不过 Python 的字典是无序的,不能像数组一样直接对 n-gram 序列频率进行排序。字典内部元素的位置是不固定的,排序之后再次使用时还是发生变化,除非你把排序过的字典里的值复制到其他类型中进行排序。在 Python 中 collections 库里面有一个 OrderedDict 可以解决这个问题:

代码语言:txt
复制
import re
代码语言:txt
复制
import string
代码语言:txt
复制
from collections import OrderedDict
代码语言:txt
复制
from utils import connection_util
代码语言:txt
复制
class DataCleaning(object):
代码语言:txt
复制
    def __init__(self):
代码语言:txt
复制
        self._target_url = 'https://en.wikipedia.org/wiki/python_(programming_language)'
代码语言:txt
复制
        self._init_connection = connection_util.ProcessConnection()
代码语言:txt
复制
    def getNgrams(self, input, n):
代码语言:txt
复制
        input = self.clean_input(input)
代码语言:txt
复制
        output = dict()
代码语言:txt
复制
        for i in range(len(input) - n + 1):
代码语言:txt
复制
            newNGram = " ".join(input[i:i + n])
代码语言:txt
复制
            if newNGram in output:
代码语言:txt
复制
                output[newNGram] += 1
代码语言:txt
复制
            else:
代码语言:txt
复制
                output[newNGram] = 1
代码语言:txt
复制
        return output
代码语言:txt
复制
    @staticmethod
代码语言:txt
复制
    def clean_input(input):
代码语言:txt
复制
        input = re.sub('\n+', " ", input)
代码语言:txt
复制
        input = re.sub('\[[0-9]*\]', "", input)
代码语言:txt
复制
        input = re.sub(' +', " ", input)
代码语言:txt
复制
        input = bytes(input, "UTF-8")
代码语言:txt
复制
        input = input.decode("ascii", "ignore")
代码语言:txt
复制
        input = input.split(' ')
代码语言:txt
复制
        clean_input = []
代码语言:txt
复制
        for item in input:
代码语言:txt
复制
            # string.punctuation 获取所有的标点符号
代码语言:txt
复制
            item = item.strip(string.punctuation)
代码语言:txt
复制
            if len(item) > 1 or (item.lower() == 'a' or item.lower() == 'i'):
代码语言:txt
复制
                clean_input.append(item)
代码语言:txt
复制
        return clean_input
代码语言:txt
复制
    def get_result(self):
代码语言:txt
复制
        # 连接目标网站,获取内容
代码语言:txt
复制
        get_content = self._init_connection.init_connection(self._target_url)
代码语言:txt
复制
        if get_content:
代码语言:txt
复制
            content = get_content.find("div", {"id": "mw-content-text"}).get_text()
代码语言:txt
复制
            ngrams = self.getNgrams(content, 2)
代码语言:txt
复制
            ngrams = OrderedDict(sorted(ngrams.items(), key=lambda t: t[1], reverse=True))
代码语言:txt
复制
            print(ngrams)
代码语言:txt
复制
            print("2-grams count is: " + str(len(ngrams)))
代码语言:txt
复制
if __name__ == '__main__':
代码语言:txt
复制
    DataCleaning().get_result()

这我们使用了 Python 的排序函数(https://docs.python.org/zh-cn/3/howto/sorting.html)把序列频率转换成 OrderedDict 对象,并按照频率值排序。结果如下:

代码语言:txt
复制
('Python Software', 37), ('2021 Retrieved', 36), ('Foundation Archived', 35), ('on June', 34), ('of Python', 28), ('in the', 25), ('such as', 23)

去掉语气词,以及连接词之后频率最高的是“Software Foundation”和“Python Software”。但是仔细观察结果会发现会有大小写字母的影响,“Python Software”有三次是“Python software”的形式,同样,“Van Rossum”和“van Rossum”也是作为两个序列来统计的。

因此,我们增加一行代码:

代码语言:txt
复制
    input = input.upper()

clean_input()函数里,这样就解决了上面的问题,同时减少了重复的 2-gram 序列。

除了这些,还需要在考虑一下,自己计划为数据标准化的进一步深入再投入多少计算力。很多单词在不同的环境里会使用不同的拼写形式,其实都是等价的,但是为了解决这种等价关系,你需要对每个单词进行检查,判断是否和其他单词有等价关系。

比如,“Python 1st”和“Python first”都出现在 2-gram 序列里面。但是,如果增加一条规则:“让所有‘first’、‘secode’、‘third’……与 1st、2nd、3rd……等价”,那么每个单词就需要额外增加十几次检查。

同理,连字符使用不一致(像“co-ordinated”和“coordinated”)、单词拼写错误以及其他语病(incongruities),都可能对 n-gram 序列的分组结果造成影响,如果语病很严重的话,很可能彻底打乱输出结果。

对连字符单词的一个处理方法是,首先把连字符去掉,然后把单词当作一个字符串,这可能需要在程序中增加一步操作。但是,这样做也可能把带连字符的短语(这种很常见,比如:“just-in-time”、“object-oriented”等)处理成一个字符串。要是换一种做法,把连字符换成空格可能会更好一些。但是就得准备见到“co ordinated”和“ordinated attack”之类的 2-gram 序列了!

总结

这篇文章主要讲解了在英文中关于数据标准化的相关内容,首先是对单词出现的频率进行排序,之后对一些大小写进行转换,缩小 2-gram 序列的重复内容,之后对一些连字符以及一些语法上的习惯进行处理。

处理完成后的内容我们可以制作一个词云,如下:

词云
词云

以上就是这篇文章的全部内容。

源代码已经托管于 Github 当中,地址:https://github.com/sycct/Scrape_1_1.git

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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档