模拟知乎点赞小助手

模拟知乎点赞小助手

CoderJia 29 2024-02-07

背景

之前公司一直会安排各种学习任务,视频章节很多的视频,有些是技术的有些是政策相关的,如果没有按时完成学习任务会被通报。但是,这些学习内容不一定有帮助,所以大家就养成了刷课的习惯,也就是点开视频,让它在那挂着。但是有个问题,视频播放过程会检测用户有没有操作,如果检测长时间不操作会弹框提示,只有点击弹框上的继续按钮才能继续播放,这就导致我们在刷课的时候要经常关注页面有没有暂停,刷课的效率有点低。为此就做了一个桌面图标检测的小工具,它测到桌面出现特定的图标之后,再模拟鼠标点击,完成继续播放的功能。

这就用到了一个 python 库—— PyAutoGUI。下面就是这个库的使用的方式,并且利用这个库做一个刷赞的助手来供参考,但是建议不要拿来真正的去刷赞。

PyAutoGUI库基础

pyautogui是一个Python库,用于编程方式控制鼠标和键盘操作,可以用于自动化测试、任务和其他需求。以下是一个 pyautogui基础使用教程。

安装 pyautogui

首先,需要安装 pyautogui

pip install pyautogui

基本使用

移动鼠标

pyautogui可以控制鼠标移动到屏幕上的特定位置。这可以通过 moveTo函数实现,它需要 x 和 y 坐标作为参数。

import pyautogui

# 移动鼠标到屏幕的(100, 100)位置
pyautogui.moveTo(100, 100, duration=1)

duration参数是可选的,表示移动到指定位置所需的时间,单位为秒。

点击鼠标

使用 click函数可以模拟鼠标点击,也可以指定点击的位置。

# 在当前位置点击鼠标左键
pyautogui.click()

# 在屏幕的(200, 200)位置点击鼠标右键
pyautogui.click(200, 200, button='right')

滚动鼠标

scroll 函数可以滚动鼠标。正数表示向上滚动,负数表示向下滚动。这个单位并不直接对应于屏幕上的像素数量,而是依赖于操作系统和应用程序的滚动设置。例如,在一些文本编辑器或网页浏览器中,一行可能被定义为一个文本行的高度,而在其他上下文中,则可能依赖于系统的滚动速度设置。

# 向上滚动
pyautogui.scroll(200)

# 向下滚动
pyautogui.scroll(-200)

键盘操作

pyautogui还可以模拟键盘操作,如按键、输入文字等。

# 按下并释放空格键
pyautogui.press('space')

# 输入字符串
pyautogui.write('Hello, pyautogui!', interval=0.25)

interval参数表示每个字符之间的延迟时间,单位为秒。

截图功能

pyautogui可以捕获屏幕的截图,这对于自动化测试和监控非常有用。

# 捕获全屏截图
screenshot = pyautogui.screenshot()
screenshot.save('screenshot.png')

识别图像

pyautogui可以在屏幕上找到图像的位置。如果找到会返回一个四元组 (left, top, width, height),表示找到的图像在屏幕上的位置和大小。如果没有找到匹配的图像,函数返回 None。可以通过 confidence参数增加搜索的容错能力。confidence参数用于指定匹配的精度,范围从0到1。注意,使用 confidence参数需要安装 opencv-python库。

location = pyautogui.locateOnScreen('button.png', confidence=0.9)

注意事项

  • 使用 pyautogui时,特别是在自动控制鼠标和键盘时,要确保有足够的安全措施,比如设置延迟或使用 pyautogui.FAILSAFE = True启用故障安全特性。当启用故障安全特性时,将鼠标移动到屏幕左上角将抛出 pyautogui.FailSafeException,从而中断脚本。
  • 在运行自动化脚本之前,确保了解代码将执行的操作,以防止鼠标键盘的意外操作或其他问题。

实现原理

该工具的核心是使用Python库 pyautoguipynputopencv-python来实现自动化的互动行为。工作流程如下:

  1. 打开知乎关注页面:首先,手动打开知乎的关注页面,准备开始自动化操作。
  2. 屏幕检测赞同图标:工具将不断扫描屏幕,寻找特定的赞同图标。
  3. 模拟用户阅读:一旦发现赞同图标,工具会先模拟点击图标上方一行以打开全文,然后模拟鼠标上下滚动来模拟阅读过程。
  4. 自动点赞:阅读完毕后,工具模拟点击赞同图标,完成点赞操作。
  5. 退出阅读,继续检测:识别到收起图标后,退出阅读状态,并模拟鼠标下滑,准备检测下一个赞同图标。

通过这一系列操作,工具能够自动在知乎上为文章点赞,模拟用户的正常浏览行为。

image-nmri.png

image-zozg.png

image-awat.png

Show me the code

代码获取

项目代码已托管于GitHub,可通过以下链接下载代码和图标:GitHub - 知乎点赞机器人

import random
import time
import pyautogui

from pynput import keyboard
import threading

# 监听ESC键标识(监听到ESC键时,停止运行)
listener_esc = False

# 图像样本的路径
agree_path = 'image/agree.png'
read_more_path = 'image/read_more.png'
close_path = 'image/close.png'

# 休息时长(单位s,最好调长一点)
sleep_time = 1

# 置信度(建议调高,不然容易误触)
confidence = 0.8

# 鼠标滚动速度
scroll_speed = 10


def on_press(key):
    # 按键按下时的操作
    try:
        if key == keyboard.Key.esc:
            # 当检测到ESC键被按下时,输出信息并停止监听
            print('ESC键被按下,停止监听。')

            # ESC已按下
            global listener_esc
            listener_esc = True
            # 返回False来停止监听器
            return False
    except AttributeError:
        pass


def get_a_number(a, b):
    """
    生成一个随机数[a, b]
    :return:
    """
    return random.Random().randint(a, b)


def on_release(key):
    # 按键释放时的操作
    pass


def start_listener():
    """
    监听ESC键
    :return:
    """
    with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()


def reading():
    """
    模拟阅读
    1、随机滚动鼠标次数
    2、随机滚动像素行数
    :return:
    """
    # 随机上下滚动鼠标次数()
    scroll_times = get_a_number(1, 3)

    while scroll_times > 0 and not listener_esc:
        # 随机滚动像素行数
        lines = get_a_number(50, 100)

        # 向下滑动
        for _ in range(int(lines / scroll_speed)):
            pyautogui.scroll(-scroll_speed)
        time.sleep(sleep_time)

        # 向上滑动,为了能回到刚刚的位置
        for _ in range(int(lines / scroll_speed)):
            pyautogui.scroll(scroll_speed)
        time.sleep(sleep_time)

        scroll_times -= 1


def close():
    """
    模拟关闭阅读,循环是为了防止坐标不准确导致没关掉
    :return:
    """

    try:
        close_location = pyautogui.locateOnScreen(close_path, confidence=confidence)
        while close_location:
            # 计算图像中心点
            center = pyautogui.center(close_location)
            pyautogui.click(center)
            print(f"close-Clicked on {center}")
            time.sleep(sleep_time)

            close_location = pyautogui.locateOnScreen(close_path, confidence=confidence)

    except pyautogui.FailSafeException:
        print("close not found")
        return


def do_read(x, y):
    """
    模拟点击“阅读更多”
    :param x:
    :param y: 赞同上方约50像素位置点击即可查看全文
    :return:
    """
    # 在屏幕上查找阅读全文图像
    if not listener_esc:
        # 点击查看全文
        pyautogui.click(x, y)
        print(f"Read more-Clicked on {x}, {y}")

        # 加载内容
        time.sleep(sleep_time)

        # 阅读
        reading()


def do_click():
    """
    模拟点赞
    :return:
    """

    # 检查是否按下了ESC键,如果是,则退出循环
    while not listener_esc:
        # 给自己一些时间准备切换到目标应用窗口
        time.sleep(sleep_time)

        try:
            # 在屏幕上查找赞同图像,可以调整confidence参数以适应图像匹配的准确性要求
            agree_location = pyautogui.locateOnScreen(agree_path, confidence=confidence)

            if agree_location:
                # 计算图像中心点
                center = pyautogui.center(agree_location)
                x, y = center

                # 模拟阅读
                do_read(x, y - 50)

                # 点赞
                if not listener_esc:
                    # pyautogui.click(x, y)  # 防止坐标因移动而造成的偏差,重新获取赞同坐标
                    agree_location = pyautogui.locateOnScreen(agree_path, confidence=confidence)
                    center = pyautogui.center(agree_location)
                    pyautogui.click(center)
                    print(f"Agree - Clicked on {center}")

                    # 点击关闭按钮
                    close()

        except pyautogui.ImageNotFoundException:
            print("agree not found. Trying again...")

            # 短暂暂停,以便循环不会过于频繁地执行
            time.sleep(sleep_time)

        # 向下滚动,大概向下滚动200像素行
        for _ in range(int(200 / scroll_speed)):
            pyautogui.scroll(-scroll_speed)

    print("Exited.")


# 创建并启动线程监听ESC键
listener_thread1 = threading.Thread(target=start_listener)
listener_thread1.start()

# 这里的代码可以在不被阻塞的情况下执行
print("Like mode begin...")
do_click()
print("Like mode end...")

依赖安装

为了运行本工具,需要安装以下Python库:

pip install pyautogui pynput opencv-python
  • pyautogui:用于模拟鼠标点击和滚动操作。
  • pynput:用于模拟键盘输入,捕获退出信号。
  • opencv-python:用于图像识别,检测屏幕上的特定图标。

注意事项

  • 坐标精确性:确保使用的像素坐标是左上角的,而不是中心坐标,以提高识别精度。
  • 图标清晰度:点赞和关闭按钮的截图需要清晰,且截图时的网页缩放比例应与程序运行时一致。
  • 防检测措施:为避免被平台检测,建议设置较长的随机休息时间。
  • 合理使用:本项目仅供学习和研究使用,请勿用于任何违规行为。

视频演示

视频演示中的休息时间间隔调的较短,并做了倍速处理。