一、前言

这篇文章是基于对上篇文章​​爬虫之获取各大网站热搜​​的进阶优化修改并添加了语音播报的功能,其中的封装如果有更好的建议,希望更多的读者能过提提,下面就要开始我的创作了。

二、针对上篇文章,总体做了以下修改

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()

5、getHot方法做了对应的传参精简

# -*- 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)

三、编写main.py

# -*- 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)

执行后便可逐条念出今日热搜了