天天看點

爬蟲之擷取各大網站熱搜并實作語音播報

一、前言

這篇文章是基于對上篇文章​​爬蟲之擷取各大網站熱搜​​的進階優化修改并添加了語音播報的功能,其中的封裝如果有更好的建議,希望更多的讀者能過提提,下面就要開始我的創作了。

二、針對上篇文章,總體做了以下修改

1、配置檔案的優化,調用盡量避免傳入太多無用的參數,是以我這邊隻保留了url、headers、hot_path三個配置:

hot_top_http:
  url: https://tophub.today/
  headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36' }
  hot_xpath:
    # 綜合
    - //div[ @id='node-1' ]/div # 微網誌
    - //div[ @id='node-6' ]/div # 知乎
    - //div[ @id='node-5' ]/div # 微信
    - //div[ @id='node-2' ]/div # 百度
    # 科技
    - //div[ @id='node-11' ]/div # 36氪
    - //div[ @id='node-137' ]/div # 少數派
    - //div[ @id='node-32' ]/div # 虎嗅網
    - //div[ @id='node-119' ]/div # IT之家
    # 娛樂
    - //div[ @id='node-19' ]/div # 哔哩哔哩
    - //div[ @id='node-221' ]/div # 抖音
    - //div[ @id='node-72' ]/div # 煎蛋
    - //div[ @id='node-26' ]/div # 豆瓣小組
    # 社群
    - //div[ @id='node-68' ]/div # 吾愛破解
    - //div[ @id='node-3' ]/div # 百度貼吧
    - //div[ @id='node-46' ]/div # 天涯
    - //div[ @id='node-42' ]/div # 虎撲社群
    # 購物
    - //div[ @id='node-5666' ]/div # 淘寶
    - //div[ @id='node-167' ]/div # 什麼值得買
    - //div[ @id='node-26696' ]/div # 今日熱賣
    - //div[ @id='node-4416' ]/div # 拼多多
    # 财經
    - //div[ @id='node-215' ]/div # 雪球
    - //div[ @id='node-2413' ]/div # 第一财經
    - //div[ @id='node-2497' ]/div # 财新網
    - //div[ @id='node-252' ]/div # 新浪财經新聞
    # 大學
    - //div[ @id='node-36' ]/div # 水木社群
    - //div[ @id='node-27469' ]/div # 北大未名
    - //div[ @id='node-41' ]/div # 武大珞珈山水
    - //div[ @id='node-37' ]/div # 北師蛋蛋
    # 日報
    - //div[ @id='node-125' ]/div # 知乎日報
    - //div[ @id='node-289' ]/div # 開眼視訊
    - //div[ @id='node-257' ]/div # 百度知道日報
    - //div[ @id='node-9402' ]/div # 哔哩哔哩
    # 地方門戶
    - //div[ @id='node-2594' ]/div # 高樓迷
    - //div[ @id='node-2568' ]/div # 蘇州姑蘇網
    - //div[ @id='node-102' ]/div # 寬帶山
    - //div[ @id='node-25' ]/div # 光谷社群
    # 影視
    - //div[ @id='node-85' ]/div # 豆瓣電影
    - //div[ @id='node-73' ]/div # 貓眼
    - //div[ @id='node-4439' ]/div # 知乎-影視
    - //div[ @id='node-5205' ]/div # 豆瓣電影
    # 閱讀
    - //div[ @id='node-5819' ]/div # 微信讀書
    - //div[ @id='node-88' ]/div # 當當
    - //div[ @id='node-5832' ]/div # 起點中文網
    - //div[ @id='node-5846' ]/div # 縱橫中文網
    # 遊戲
    - //div[ @id='node-60' ]/div # TapTap
    - //div[ @id='node-3524' ]/div # 3DM遊戲網
    - //div[ @id='node-295' ]/div # 機核網
    - //div[ @id='node-203' ]/div # 遊研社
    # 體育
    - //div[ @id='node-251' ]/div # 新浪體育新聞
    - //div[ @id='node-4437' ]/div # 知乎-體育
    - //div[ @id='node-316' ]/div # 虎撲社群
    - //div[ @id='node-26571' ]/div # 新浪熱點榜
    # 産品
    - //div[ @id='node-213' ]/div # 人人都是産品經理
    - //div[ @id='node-293' ]/div # 鳥哥筆記
    - //div[ @id='node-300' ]/div # 産品100
    - //div[ @id='node-133' ]/div # Product Hunt
    # 開發
    - //div[ @id='node-54' ]/div # GitHub
    - //div[ @id='node-267' ]/div # CSDN論壇
    - //div[ @id='node-100' ]/div # 掘金
    - //div[ @id='node-132' ]/div # 開發者頭條
    # 應用
    - //div[ @id='node-62' ]/div # App Store
    - //div[ @id='node-2429' ]/div # 愛範兒
    - //div[ @id='node-392' ]/div # 最美應用
    - //div[ @id='node-3510' ]/div # AppSo
    # 汽車
    - //div[ @id='node-2454' ]/div # 汽車之家
    - //div[ @id='node-66' ]/div # 老司機
    - //div[ @id='node-2464' ]/div # 易車網
    - //div[ @id='node-2460' ]/div # 太平洋汽車網
    # 安全
    - //div[ @id='node-89' ]/div # 看雪論壇
    - //div[ @id='node-327' ]/div # 安全客
    - //div[ @id='node-326' ]/div # FreeBuf
    - //div[ @id='node-328' ]/div # 安全脈搏      

2、新增自命名方法:

# -*- coding: utf-8 -*-

"""
@author: lucas
@Function: 檔案命名,分為預設檔案名和自定義檔案名
@file: fileNaming.py
@time: 2021/10/3 5:47 下午
"""
import os

from utils.config import Config


def fileNaming(path1):
    print("請輸入檔案名,如不輸入,預設檔案名export:  ")
    DEFAULT_FILE_NAME = Config().get('general_parameters').get('default_file_name')
    exportname = input()
    if exportname == '':
        exportname = DEFAULT_FILE_NAME
    if os.path.exists('%s\%s.xlsx' % (path1, exportname)):
        os.remove('%s\%s.xlsx' % (path1, exportname))
    print('導出檔案路徑: %s/%s.xlsx' % (path1, exportname))
    return exportname      

3、寫入資料方法優化:

3.1 将檔案格式作為數組闖入

3.2 合并重複路徑代碼

# -*- coding: utf-8 -*-

"""
@author: lucas
@Function: 定義寫入檔案類型
@file: writeHotToFile.py
@time: 2021/9/29 2:28 下午
"""
import os

import openpyxl
import pandas as pd

from utils.config import DATA_PATH, Config
from utils.fileNaming import fileNaming

FORMAT = ['.html', '.csv', '.json', '.xlsx']


def writeHotToFile(data, n):
    file = pd.DataFrame(data, columns=['排名', '今日熱搜', '熱度(機關為萬)'])
    print(file)
    encoding = Config().get('general_parameters').get('charset')
    exportname = fileNaming(DATA_PATH)

    if n >= len(FORMAT):
        print("Error: 數組大小超限")
    else:
        base_path = DATA_PATH + '/' + exportname + FORMAT[n]
        if n == 0:
            return file.to_html(base_path, encoding=encoding[1])
        elif n == 1:
            return file.to_csv(base_path)
        elif n == 2:
            return file.to_json(base_path, force_ascii=False)
        elif n == 3:
            return file.to_excel(base_path)
        else:
            return "抱歉!沒有找到符合的檔案格式,請重新輸入!"      

4、新增播報方法

# -*- coding: utf-8 -*-

"""
@author: lucas
@Function: 語音播報功能
@file: voiceBroadcast.py
@time: 2021/10/2 4:00 下午
"""
import pyttsx3


def voiceBroadcast(speckingRate, content):
    """
    speckingRate: 語速
    content: 需要播報的内容
    """
    engine = pyttsx3.init()
    rate = engine.getProperty('rate')
    engine.setProperty('rate', speckingRate)
    engine.say(content)
    engine.runAndWait()
    engine.stop()      
# -*- coding: utf-8 -*-

"""
@author: lucas
@Function: 擷取熱搜的方法
@file: getHot.py
@time: 2021/9/29 12:16 下午
"""

from lxml import etree

from utils.client import HTTPClient
from utils.voiceBroadcast import voiceBroadcast
from utils.writeHotToFile import writeHotToFile


def getHot(methods, url, headers, xpath, n):
    """
    methods: 請求方法
    url: 請求路徑
    headers: 請求頭
    xpath: 定位的清單路徑
    n: 對應着檔案格式,0-html,1-csv,2-json,3-xlsx......
    range_num: 排名數量
    """
    html = HTTPClient(url, methods, headers).send()
    html = html.content.decode('utf-8')
    html = etree.HTML(html)
    div = html.xpath(xpath)
    for a in div:
        titles = a.xpath(".//span[@class='t']/text()")
        numbers = a.xpath(".//span[@class='e']/text()")

    b = []
    for i in range(len(titles)):
        list = [f"排行榜第:{i + 1} 今日熱搜:{titles[i]},熱度為:{numbers[i][:-1]}"]
        voiceBroadcast(200, '為您播報今天微網誌熱搜:' + list[0])
        b.append([i + 1, titles[i], numbers[i][:-1]])
    writeHotToFile(b, n)      
# -*- coding: utf-8 -*-
from utils.client import METHODS
from utils.getHot import getHot
from utils.config import Config


if __name__ == '__main__':
    http = Config().get('hot_top_http')
    headers = http.get('headers')
    url = http.get('url')
    hot_xpath = http.get('hot_xpath')
    # 微網誌熱搜排行
    getHot(METHODS[0], url, headers, hot_xpath[0], 0)