Python自动化-头条、抖音、微博热搜采集分析

前言
这是一个自媒体常用案例,今天我们通过分析这个案例来获得有关 python 的学习和使用

效果
通过运行 py 脚本输出本地得到 xlsx 数据表格文件

自动化分类;整体匹配率:84%~96% 区间左右。

词频统计;三者共存的热搜,说明为持久公共热度,信息密度较高。

文本情感平均值、每条标题的情感数值;主:人为置顶热搜的文本情绪强烈程度。

词性分析;标记可能存有引导与被植入意识成分用词,只要定语、状语叠得多,总能是宣传正态形势。

Python 自动化-头条、抖音、微博热搜采集分析

 

代码

import os
from datetime import datetime
import requests
from bs4 import BeautifulSoup
from openpyxl import Workbook
from snownlp import SnowNLP
import jieba
from collections import Counter
import jieba.posseg as pseg
import json
import urllib.request

# 确定保存文本格式用的。
def get_formatted_time():
    """
    获取格式化后的当前时间
    :return: 格式化后的当前时间字符串
    """
    now = datetime.now()
    return now.strftime('%Y-%m-%d')

# 解析新闻函数
def get_news_from_url(url: str):
    """
    从指定的 URL 抓取热搜新闻
    :param url: 网页 URL
    :return: 热搜新闻列表
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                      '(KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
    r = requests.get(url, headers=headers)
    r.encoding = 'utf-8'
    soup = BeautifulSoup(r.text, 'html.parser')
    toutiao_resoubang = soup.find_all('div', class_='single-entry tindent')

    resoubang_list = []
    for item in toutiao_resoubang:
        spans = item.find_all('span')
        for span in spans:
            resoubang_list.append(span.string)
    return resoubang_list

# 删除空行
def delete_empty_rows(sheet_name: str, wb: Workbook):
    """
    删除指定工作表中的空行
    :param sheet_name: 工作表名称
    :param wb: Excel 工作簿对象
    :param None 关键字
    https://notes-by-yangjinjie.readthedocs.io/zh_CN/latest/python/05-modules/openpyxl.html?highlight=openpyxl
    """
    ws = wb[sheet_name]
    # 迭代行所用的内置函数 ws.iter_rows()
    for row in ws.iter_rows():
        if all(cell.value is None for cell in row):
            ws.delete_rows(row[0].row)

# 计数平均指数、情感得分
def calculate_average_index_and_sentiment_score(sheet_name: str, wb: Workbook):
    """
    计算指定工作表中热搜新闻的平均指数和情感得分
    :param sheet_name: 工作表名称
    :param wb: Excel 工作簿对象
    :return: 平均指数、情感得分元组
    """
    ws = wb[sheet_name]
    total_index = 0
    count = 0
    sentiment_score_list = []
    for row in ws.iter_rows(min_row=2, min_col=1, max_col=3):
        news_str = ''
        for cell in row:
            if cell.value is not None:
                news_str += str(cell.value)
        # 功能挺多,见:https://github.com/isnowfy/snownlp
        s = SnowNLP(news_str)
        sentiment_score = s.sentiments
        sentiment_score_list.append(sentiment_score)
        # row[2] 是指每一行中的第三个单元格,也就是第三列。
        total_index += row[2].value
        count += 1
        ws.cell(row=row[0].row, column=4, value=sentiment_score)
    # 每张表的平均指数与情感得分
    return (total_index / count, sum(sentiment_score_list) / len(sentiment_score_list))

# 统计词频
def calculate_word_count(sheet_names: list, wb: Workbook):
    """
    计算工作表中出现最多的 20 个单词,将结果写入新的工作表中
    :param sheet_names: 工作表名称
    :param wb: Excel 工作簿对象
    :param stopwords_file: 停用词文件路径
    停用词是指在自然语言中使用频率很高,
    但通常不具有实际含义或对文本分析任务没有太大帮助的单词,如“的”,“了”等。
    """
    
    # 停用词文件
    stopwords_file = 'https://ghproxy.com/https://raw.githubusercontent.com/goto456/stopwords/master/cn_stopwords.txt'
    # 请求停用词库
    response = requests.get(stopwords_file)
    stopwords = response.content.decode('utf-8').split('\n')

    # 加载停用词库
    for word in stopwords:
        jieba.del_word(word.strip())

    # 遍历所有工作表,统计词频,由于语料库词汇功能欠佳,只能粗略统计
    word_count = Counter()
    for sheet_name in sheet_names:
        ws = wb[sheet_name]
        for row in ws.iter_rows(min_row=2, min_col=1, max_col=3):
            news_str = ''
            for cell in row:
                if cell.value is not None:
                    news_str += str(cell.value)
            words = jieba.lcut(news_str)

            # 只要是数值类型的忽略。
            # words = [word for word in words if not(word.isdigit() or (word.replace('w', '').replace('.', '').isdigit()))]
            new_words = []
            for word in words:
                 # 忽略长度为 0 或 1 的字符串
                if len(word) <= 1:
                    continue
                # 去除数值噪声
                if not(word.isdigit() or (word.replace('w', '').replace('.', '').isdigit())):
                    new_words.append(word)
            words = new_words
            # 更新词库集
            word_count.update(words)

    # 去掉停用词
    for word in list(word_count):
        if word in stopwords:
            del word_count[word]

    # 取出出现最多的 30 个词
    top_words = word_count.most_common(30)
    # 创建一个新的工作表
    ws = wb.create_sheet(title='词频统计')
    # 添加行
    ws.append(['排名', '词语', '词频'])
    # 从 1 开始计数,而非 0 开始排名
    for i, (word, freq) in enumerate(top_words,1):
        ws.append([i, word, freq])


# 2023.5.9 新增分类功能
def write_category_to_sheet(sheet_name: str, wb: Workbook):
    """
    将新闻事件的关键词分类信息写入到 Excel 工作表中的第五列中
    :param sheet_name: 工作表名称
    :param wb: Excel 工作簿对象
    :jieba 分词:https://github.com/fxsjy/jieba
    """

    # 调用在线分类字典 json
    # 从 URL 获取 JSON 数据
    response = urllib.request.urlopen('https://ghproxy.com/https://raw.githubusercontent.com/hoochanlon/scripts/main/AQUICK/category_news.json')
    json_data = response.read().decode('utf-8')

    # 解析 JSON 数据
    category_keywords = json.loads(json_data)

    # 从当前 sheet 开始
    ws = wb[sheet_name]
    for row in ws.iter_rows(min_row=2, min_col=1, max_col=4):
        title_str = ''
        for cell in row:
            if cell.value is not None:
                title_str += str(cell.value)

        # 将标题字符串分词并转换为列表数组
        words = pseg.cut(title_str)
        category = ''
        for word, flag in words:
            # 内置的字符串方法,用于检查前缀指定开头
            # if flag.startswith('n'):
            # key keywords 关键字,.items() 检索键值对
                for key, keywords in category_keywords.items():
                    if word in keywords:
                        category = key
                        break
                if category:
                    break
        if not category:
           # category = '其他'
            category = '综合'
        ws.cell(row=row[0].row, column=5, value=category)


# 将已解析网页排版的数据,按规则写入到 xlsx,行列对称,条理分明。
def write_news_to_sheet(news_list: list, sheet_name: str, wb: Workbook):
    """
    将新闻列表写入到 Excel 工作表中
    :param news_list: 新闻列表
    :param sheet_name: 工作表名称
    :param wb: Excel 工作簿对象
    :cell.value.isnumeric() 表示当前字符串是否能表示为一个数字
    :isinstance(cell.value, str) 表示当前值是否字符串
    """
    ws = wb.create_sheet(title=sheet_name)

    row = []
    for i, item in enumerate(news_list, start=1):
        if i >= 156: # 抽取 50 组数据(如果索引大于 156 是关于微博的其他介绍文章)
            continue  
        if i % 3 == 1: #  # 索引从 0 开始,即 2%3,往后是新组数据。
            item = item.replace("、", "")
        row.append(item)
        if i % 3 == 0: # 取模被整除,3 列一组,被整除说明已到 3 列,换行。
            ws.append(row)
            row = []
    
    # 从第二行开始迭代每一行数据
    for row in ws.iter_rows(min_row=2, min_col=1):
        for cell in row:
            if cell.column == 1 or cell.column == 3:
                # 实例判断,如果是返回 True,否则返回 False。
                if isinstance(cell.value, str) and not cell.value.isnumeric():
                    # 去除字符串中的 '[置顶]' 字符,185 为 2、3、4 排名的平均值(实时)
                    cell.value = cell.value.replace('[置顶]', '185w') 
                if isinstance(cell.value, str) and cell.value.isnumeric():
                    cell.value = int(cell.value)
                elif isinstance(cell.value, str):
                    cell.value = float(cell.value.replace('w', ''))

    ws.cell(row=1, column=3, value='指数(万)')
    ws.cell(row=1, column=4, value='情感得分')
    ws.cell(row=1, column=5, value='分类')
    

def main():

    urls = ['http://resou.today/art/11.html', 'http://resou.today/art/22.html','http://resou.today/art/6.html']
    sheet_names = ['今日头条热榜', '抖音时事热榜', '微博热搜']

    wb = Workbook()

    wb.remove(wb['Sheet'])
    for url, sheet_name in zip(urls, sheet_names):
        news_list = get_news_from_url(url)
        # 写入网页解析的数据到 xlsx
        write_news_to_sheet(news_list, sheet_name, wb)
        # 删除操作留下的空行
        delete_empty_rows(sheet_name, wb)
        # 分类
        write_category_to_sheet(sheet_name, wb)

        # 统计平均指数、各表平均情感值
        average_index, sentiment_score = calculate_average_index_and_sentiment_score(sheet_name, wb)
        print(f'{sheet_name} 平均指数:{average_index:.2f} 情感得分: {sentiment_score:.2f}')
    
    # 词频统计
    calculate_word_count(sheet_names, wb)

    # 进行跨平台处理保存路径
    save_path_xlsx_file = os.path.join(os.path.join(os.path.expanduser("~"), "Desktop"), 
                                       "resoubang_{}.xlsx".format(get_formatted_time()))
    # 删除空表,并保存为指定文件
    # wb.remove(wb['Sheet']);wb.save(save_path_xlsx_file)
    wb.save(save_path_xlsx_file)

# 如果当前模块是被其他模块导入的,则该条件语句下面的代码将不会被执行。
if __name__ == '__main__':
    main()

 

分析
透过代码我们首先看到代码第一部分导入了一些常用的 Python 库和模块

import os:这是 Python 的标准库之一,用于与操作系统进行交互,例如创建文件夹、删除文件等操作。

from datetime import datetime:从 datetime 模块中导入 datetime 方法,用于处理日期和时间的功能。

import requests:这是一个非常常用的库,用于发送 HTTP 请求,例如获取网页内容。

from bs4 import BeautifulSoup:从 BeautifulSoup 模块中导入 BeautifulSoup 类,用于解析和提取 HTML 或 XML 文档中的数据。

from openpyxl import Workbook:从 openpyxl 模块中导入 Workbook 类,用于操作 Excel 文件。

from snownlp import SnowNLP:从 snownlp 模块中导入 SnowNLP 类,用于中文文本情感分析。

import jieba:这是一个非常常用的中文分词库,用于将中文文本分割成一个个单词。

from collections import Counter:从 collections 模块中导入 Counter 类,用于对一个可迭代对象进行计数。

import jieba.posseg:导入 jieba 库中的 posseg 模块,用于中文词性标注。

import json:这是 Python 的标准库之一,用于处理 JSON 数据。

import urllib.request:这是 Python 的标准库之一,用于发送 HTTP 请求和处理 URL。

整体部分解释
它使用了上面多个第三方库来实现不同的功能。

接下来,代码定义了一个函数 get_formatted_time(),用于获取格式化后的当前时间。

然后,代码定义了一个函数 get_news_from_url(url: str),用于从指定的 URL 抓取热搜新闻。

接着,代码定义了一个函数 delete_empty_rows(sheet_name: str, wb: Workbook),用于删除指定工作表中的空行。

然后,代码定义了一个函数 calculate_average_index_and_sentiment_score(sheet_name: str, wb: Workbook),用于计算指定工作表中热搜新闻的平均指数和情感得分。

接下来,代码定义了一个函数 calculate_word_count(sheet_names: list, wb: Workbook),用于统计工作表中出现最多的 20 个单词。

然后,代码定义了一个函数 write_category_to_sheet(sheet_name: str, wb: Workbook),用于将新闻事件的关键词分类信息写入到 Excel 工作表中。

接着,代码定义了一个函数 write_news_to_sheet(news_list: list, sheet_name: str, wb: Workbook),用于将新闻列表写入到 Excel 工作表中。

最后,代码定义了一个函数 main(),用于执行主要的程序逻辑。它首先定义了要抓取的 URL 和工作表名称的列表,然后创建了一个 Excel 工作簿对象。接着,它使用 get_news_from_url()函数抓取热搜新闻,并使用 write_news_to_sheet()函数将新闻列表写入到 Excel 工作表中。然后,它使用 delete_empty_rows()函数删除空行,并使用 write_category_to_sheet()函数将关键词分类信息写入到 Excel 工作表中。接着,它使用 calculate_average_index_and_sentiment_score()函数计算平均指数和情感得分,并打印结果。最后,它使用 calculate_word_count()函数统计词频,并将工作簿保存为 xlsx 文件。

最后,代码使用 if __name__ == ‘__main__’:条件语句判断当前模块是否被直接执行,如果是,则调用 main()函数执行主程序逻辑。

使用
安装 python
下载 Python:首先,您需要下载并安装 Python 解释器。您可以在 Python 官方网站(https://www.python.org)上找到不同版本的 Python。选择适合您操作系统的版本并下载安装程序。

安装 Python:运行下载的安装程序,并按照安装向导的指示进行安装。确保选择将 Python 添加到系统路径中的选项。

如果要运行 Python 文件:打开命令提示符(Windows)或终端(Mac/Linux),导航到存储了 Python 脚本的目录。使用 cd 命令来切换目录,例如:cd C:\Users\YourUsername\Documents 然后,可以运行以下命令来执行 Python 脚本:python example.py 这样,您就可以安装和运行 Python 文件了。如果一切顺利,您应该能够在命令提示符或终端中看到输出结果。

注:python3.x 版本运行 python3 example.py 才会执行文件

设置 python 的全局环境变量
打开终端应用程序。您可以在“应用程序”文件夹中找到它,或者使用 Spotlight 搜索并输入“终端”。

在终端中,输入以下命令来编辑您的 bash 配置文件(如果您使用的是 Zsh,请将命令中的.bash_profile 替换为.zshrc):

nano ~/.bash_profile
终端将打开一个文本编辑器,显示您的 bash 配置文件的内容(如果您没有创建过配置文件,则会是空白的)。

在文件的末尾添加以下行来设置 Python 的全局环境变量:

export PATH=”/usr/local/bin:$PATH”
这将将/usr/local/bin 目录添加到您的 PATH 环境变量中,该目录通常是 Python 安装的位置。

按下 Control + X 来退出文本编辑器,然后按下 Y 来保存更改,最后按下 Enter 键确认保存的文件名。

在终端中,输入以下命令来使更改生效:

source ~/.bash_profile
这将重新加载您的 bash 配置文件,使更改立即生效。

现在,您已经成功设置了 Python 的全局环境变量。您可以在终端中运行 python 命令来验证是否正确设置。

正确验证服务器证书
如果在使用 python 时 urllib 库发送 HTTPS 请求出现了证书验证失败的问题

为了解决这个问题,您可以尝试以下步骤:

打开终端应用程序。

输入以下命令并按 Enter 键:

/applications/python\ {your_python_version}/install\ Certificates.command
请将{your_python_version}替换为您当前使用的 Python 版本号。例如,如果您使用的是 Python 3.10,则命令应为:

/applications/python\ 3.10/install\ Certificates.command
执行上述命令后,将会自动下载并安装缺失的根证书。

这个命令会运行 Python 安装目录中的 Install Certificates.command 脚本,用于安装缺失的根证书。执行此命令后,您的 Python 环境应该能够正确验证服务器证书,而不会再出现证书验证失败的错误。

PIP 安装文件依赖库
输入以下命令来检查是否已经安装了 pip:

pip –version
如果已经安装了 pip,您将看到 pip 的版本信息。如果未安装,您将看到一条错误消息。

如果未安装 pip,您可以使用以下方法之一来安装它:

在命令行中运行以下命令来安装 pip:

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
sudo python get-pip.py
在浏览器中打开 https://bootstrap.pypa.io/get-pip.py。

将页面上的内容保存为名为 get-pip.py 的 Python 脚本文件。

在命令行中导航到保存了 get-pip.py 文件的目录。

运行以下命令来安装 pip:

python get-pip.py
对于 Windows 用户:

对于 Mac 和 Linux 用户:

安装完成后,您可以再次运行以下命令来验证 pip 是否已成功安装:

如果显示了 pip 的版本信息,那么 pip 已经成功安装了。

pip –version
现在可以在终端使用以下命令安装所需的依赖库:pip install requests beautifulsoup4 openpyxl snownlp jieba 要使用 import os 和 from datetime import datetime 这两个库,它们是 Python 的内置库,无需安装。至于 import jieba.posseg as pseg 和 import urllib.request,它们是 Python 标准库的一部分,也不需要单独安装。如果使用 pip 安装时出现权限问题,可以添加–user 参数来将库安装在用户目录下:pip install –user requests beautifulsoup4 openpyxl snownlp jieba

最后,在满足 python 必要环境、文件所需依赖库的情况下使用终端命令或 python 解释器直接运行文件即可。

© 版权声明

☆ END ☆
喜欢就点个赞吧
点赞0 分享
图片正在生成中,请稍后...