圆弧派博客 - 专注于网络技术 圆弧派博客,是一个专注于网络技术分享的个人博客,包括但不止记录与分享编程知识、实用工具、开源项目,愿与更多志同道合的朋友共享网络乐趣! 2025-11-27T10:42:00+08:00 Typecho https://www.iarc.top/feed/atom/ <![CDATA[Selenium常用代码速查手册]]> https://www.iarc.top/515.html 2025-11-27T10:42:00+08:00 2025-11-27T10:42:00+08:00 青帝 http://icp.iarc.top migttyar.png

Selenium常用代码速查手册

1. 基础配置

用法:导入必要的模块,初始化浏览器驱动

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep

# 初始化Chrome浏览器(需要先下载chromedriver)
driver = webdriver.Chrome()
driver.maximize_window()  # 最大化窗口
driver.implicitly_wait(10)  # 设置隐式等待10秒

# 打开网页
driver.get("https://www.baidu.com")

2. 元素定位

用法:在网页中找到你要操作的元素(按钮、输入框等)

# CSS选择器(推荐使用,最灵活)
element = driver.find_element(By.CSS_SELECTOR, "#id")  # 通过id找元素
element = driver.find_element(By.CSS_SELECTOR, ".class")  # 通过class找元素
element = driver.find_element(By.CSS_SELECTOR, "input[type='text']")  # 通过属性找元素

# 其他定位方式
element = driver.find_element(By.ID, "element_id")  # 直接通过id找
element = driver.find_element(By.CLASS_NAME, "class_name")  # 通过class名找
element = driver.find_element(By.XPATH, "//div[@class='example']")  # 通过xpath找
element = driver.find_element(By.TAG_NAME, "button")  # 通过标签名找
element = driver.find_element(By.LINK_TEXT, "链接文本")  # 通过链接文字找
element = driver.find_element(By.PARTIAL_LINK_TEXT, "部分链接")  # 通过部分链接文字找

# 查找多个相同元素(返回列表)
elements = driver.find_elements(By.CSS_SELECTOR, ".item")

3. 基本操作

用法:对找到的元素进行各种操作

# 点击元素(按钮、链接等)
element.click()

# 在输入框中输入文本
element.send_keys("要输入的文本")

# 清空输入框内容
element.clear()

# 获取元素显示的文本内容
text = element.text
print(text)  # 打印获取的文本

# 获取元素的属性值(如value、href等)
value = element.get_attribute("value")  # 获取输入框的值
href = element.get_attribute("href")    # 获取链接地址

# 判断元素状态
is_displayed = element.is_displayed()  # 元素是否可见
is_enabled = element.is_enabled()      # 元素是否可用
is_selected = element.is_selected()    # 元素是否被选中(复选框、单选框)

4. 键盘操作

用法:模拟键盘按键,实现快捷键操作

# 组合键操作(常用于复制粘贴等)
element.send_keys(Keys.CONTROL, 'a')  # Ctrl+A 全选文本
element.send_keys(Keys.CONTROL, 'c')  # Ctrl+C 复制
element.send_keys(Keys.CONTROL, 'v')  # Ctrl+V 粘贴

# 特殊按键
element.send_keys(Keys.ENTER)     # 按回车键(提交表单)
element.send_keys(Keys.TAB)       # 按Tab键(切换焦点)
element.send_keys(Keys.ESCAPE)    # 按ESC键(取消操作)
element.send_keys(Keys.DELETE)    # 按Delete键
element.send_keys(Keys.BACKSPACE) # 按退格键
element.send_keys(Keys.ARROW_UP)  # 按方向键上

# 实用示例:清空输入框并输入新内容
input_box = driver.find_element(By.ID, "search")
input_box.send_keys(Keys.CONTROL, 'a')  # 全选
input_box.send_keys(Keys.DELETE)        # 删除
input_box.send_keys("新的搜索内容")      # 输入新内容

5. 鼠标操作

用法:模拟鼠标的各种操作

# 鼠标悬停(显示下拉菜单等)
ActionChains(driver).move_to_element(element).perform()

# 右键点击(显示右键菜单)
ActionChains(driver).context_click(element).perform()

# 双击元素
ActionChains(driver).double_click(element).perform()

# 拖拽元素从source到target位置
ActionChains(driver).drag_and_drop(source, target).perform()

# 拖拽元素到指定距离(x轴100像素,y轴0像素)
ActionChains(driver).click_and_hold(element).move_by_offset(100, 0).release().perform()

# 实用示例:滑动滑块
slider = driver.find_element(By.CSS_SELECTOR, ".slider")
ActionChains(driver).click_and_hold(slider).move_by_offset(50, 0).release().perform()

6. 等待机制

用法:等待页面元素加载完成,避免操作失败

# 固定等待(简单但不推荐,会浪费时间)
sleep(2)  # 等待2秒

# 显式等待(推荐使用,更智能)
wait = WebDriverWait(driver, 10)  # 最多等待10秒

# 等待元素出现在DOM中
element = wait.until(EC.presence_of_element_located((By.ID, "myElement")))

# 等待元素可以被点击
element = wait.until(EC.element_to_be_clickable((By.ID, "myButton")))

# 等待元素可见
element = wait.until(EC.visibility_of_element_located((By.ID, "myDiv")))

# 等待元素消失(如加载动画)
wait.until(EC.invisibility_of_element_located((By.ID, "loading")))

# 实用示例:等待搜索结果加载
search_button = driver.find_element(By.ID, "search-btn")
search_button.click()
# 等待结果列表出现
results = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "results")))

7. 下拉框操作

用法:操作HTML的select下拉框

from selenium.webdriver.support.ui import Select

# 找到下拉框并创建Select对象
dropdown = driver.find_element(By.ID, "country")
select = Select(dropdown)

# 三种选择方式
select.select_by_visible_text("中国")        # 通过显示文本选择
select.select_by_value("china")            # 通过value属性选择
select.select_by_index(1)                  # 通过索引选择(从0开始)

# 获取选项信息
all_options = select.options               # 获取所有选项
selected_option = select.first_selected_option  # 获取当前选中项
print(selected_option.text)               # 打印选中项文本

# 取消选择(多选下拉框)
select.deselect_by_visible_text("中国")
select.deselect_all()                     # 取消所有选择

8. 窗口和标签页

用法:处理多个浏览器窗口或标签页

# 保存当前窗口句柄(用于后续切换回来)
main_window = driver.current_window_handle

# 获取所有窗口句柄
all_windows = driver.window_handles
print(f"共有{len(all_windows)}个窗口")

# 点击链接打开新窗口后,切换到新窗口
link = driver.find_element(By.LINK_TEXT, "打开新窗口")
link.click()
# 切换到最新打开的窗口
driver.switch_to.window(driver.window_handles[-1])

# 用JavaScript打开新标签页
driver.execute_script("window.open('https://www.baidu.com');")

# 关闭当前窗口并切换回主窗口
driver.close()
driver.switch_to.window(main_window)

# 处理iframe框架
driver.switch_to.frame("frame_name")      # 切换到iframe
driver.switch_to.frame(0)                 # 通过索引切换
driver.switch_to.default_content()        # 切回主页面

# 实用示例:处理弹出窗口
original_window = driver.current_window_handle
# 点击按钮打开新窗口
driver.find_element(By.ID, "open-window").click()
# 等待新窗口出现
wait.until(lambda d: len(d.window_handles) > 1)
# 切换到新窗口
for window in driver.window_handles:
    if window != original_window:
        driver.switch_to.window(window)
        break

9. JavaScript执行

用法:执行JavaScript代码解决复杂操作

# 滚动页面到底部(加载更多内容)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

# 滚动到指定元素位置
element = driver.find_element(By.ID, "target")
driver.execute_script("arguments[0].scrollIntoView();", element)

# 强制点击被遮挡的元素
hidden_button = driver.find_element(By.ID, "hidden-btn")
driver.execute_script("arguments[0].click();", hidden_button)

# 直接设置输入框的值(绕过输入限制)
input_box = driver.find_element(By.ID, "readonly-input")
driver.execute_script("arguments[0].value = '强制设置的值';", input_box)

# 修改元素样式(如显示隐藏元素)
driver.execute_script("arguments[0].style.display = 'block';", element)

# 获取页面信息
page_height = driver.execute_script("return document.body.scrollHeight;")
print(f"页面高度:{page_height}像素")

# 实用示例:无限滚动加载
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    sleep(2)  # 等待加载
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break  # 没有新内容了
    last_height = new_height

10. 文件操作

用法:处理文件上传和截图

# 文件上传(找到文件选择器并传入文件路径)
file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
file_path = r"C:\Users\用户名\Desktop\要上传的文件.jpg"
file_input.send_keys(file_path)

# 多文件上传
files = [r"C:\file1.jpg", r"C:\file2.jpg"]
file_input.send_keys("\n".join(files))

# 整个页面截图
driver.save_screenshot("页面截图.png")

# 单个元素截图
element = driver.find_element(By.ID, "target")
element.screenshot("元素截图.png")

# 带时间戳的截图(避免文件名重复)
from datetime import datetime
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
driver.save_screenshot(f"截图_{timestamp}.png")

# 实用示例:自动化测试截图
def take_screenshot_on_error():
    try:
        # 执行测试步骤
        driver.find_element(By.ID, "submit").click()
    except Exception as e:
        # 出错时自动截图
        driver.save_screenshot("错误截图.png")
        print(f"操作失败:{e}")

11. 弹窗处理

用法:处理JavaScript弹出的对话框

# 等待弹窗出现并处理
try:
    # 触发弹窗的操作
    driver.find_element(By.ID, "alert-btn").click()
    
    # 切换到弹窗
    alert = driver.switch_to.alert
    
    # 获取弹窗文本
    alert_text = alert.text
    print(f"弹窗内容:{alert_text}")
    
    # 确认弹窗(点击确定)
    alert.accept()
    
    # 或者取消弹窗(点击取消)
    # alert.dismiss()
    
except:
    print("没有弹窗出现")

# 处理输入型弹窗(prompt)
try:
    driver.find_element(By.ID, "prompt-btn").click()
    alert = driver.switch_to.alert
    alert.send_keys("要输入的文本")  # 在弹窗中输入文本
    alert.accept()  # 确认
except:
    print("没有输入弹窗")

# 实用示例:批量确认删除操作
delete_buttons = driver.find_elements(By.CLASS_NAME, "delete-btn")
for btn in delete_buttons:
    btn.click()
    # 等待确认弹窗
    alert = WebDriverWait(driver, 5).until(lambda d: d.switch_to.alert)
    alert.accept()  # 确认删除

12. Cookie操作

用法:管理浏览器Cookie,实现登录状态保持等

# 添加Cookie(通常用于模拟登录状态)
driver.add_cookie({
    "name": "session_id", 
    "value": "abc123456",
    "domain": "example.com"
})

# 获取指定Cookie
session_cookie = driver.get_cookie("session_id")
if session_cookie:
    print(f"会话ID:{session_cookie['value']}")

# 获取所有Cookie
all_cookies = driver.get_cookies()
for cookie in all_cookies:
    print(f"{cookie['name']}: {cookie['value']}")

# 删除指定Cookie
driver.delete_cookie("session_id")

# 删除所有Cookie(退出登录)
driver.delete_all_cookies()

# 实用示例:保存和恢复登录状态
import json

# 登录后保存Cookie
def save_cookies():
    with open("cookies.json", "w") as f:
        json.dump(driver.get_cookies(), f)

# 下次访问时恢复Cookie
def load_cookies():
    try:
        with open("cookies.json", "r") as f:
            cookies = json.load(f)
            for cookie in cookies:
                driver.add_cookie(cookie)
        driver.refresh()  # 刷新页面使Cookie生效
    except FileNotFoundError:
        print("没有保存的Cookie文件")

13. 浏览器控制

用法:控制浏览器的基本行为

# 页面导航
driver.get("https://www.baidu.com")  # 打开网页
driver.back()       # 后退到上一页
driver.forward()    # 前进到下一页
driver.refresh()    # 刷新当前页面

# 窗口大小控制
driver.maximize_window()              # 最大化窗口
driver.minimize_window()              # 最小化窗口
driver.set_window_size(1920, 1080)   # 设置窗口大小
driver.fullscreen_window()            # 全屏模式

# 获取窗口大小和位置
size = driver.get_window_size()
print(f"窗口大小:{size['width']} x {size['height']}")
position = driver.get_window_position()
print(f"窗口位置:({position['x']}, {position['y']})")

# 获取页面信息
title = driver.title                  # 获取页面标题
url = driver.current_url             # 获取当前URL
page_source = driver.page_source     # 获取页面源码

print(f"页面标题:{title}")
print(f"当前网址:{url}")

# 实用示例:检查页面是否正确加载
def check_page_loaded(expected_title):
    actual_title = driver.title
    if expected_title in actual_title:
        print("页面加载成功")
        return True
    else:
        print(f"页面加载异常,期望标题包含:{expected_title},实际标题:{actual_title}")
        return False

# 设置浏览器位置(多显示器环境)
driver.set_window_position(0, 0)     # 移动到左上角

14. 常用操作模式

用法:封装常用的操作组合,提高代码复用性

# 清空输入框并输入新内容(最常用)
def input_text(element, text):
    element.click()                          # 点击激活输入框
    element.send_keys(Keys.CONTROL, 'a')     # 全选现有内容
    element.send_keys(Keys.DELETE)           # 删除内容
    element.send_keys(text)                  # 输入新内容

# 使用示例
search_box = driver.find_element(By.ID, "search")
input_text(search_box, "Python教程")

# 等待并点击(避免元素未加载完成)
def wait_and_click(driver, selector, timeout=10):
    element = WebDriverWait(driver, timeout).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, selector))
    )
    element.click()
    return element

# 使用示例
wait_and_click(driver, "#submit-btn")

# 滚动到元素并点击(处理页面很长的情况)
def scroll_and_click(driver, element):
    driver.execute_script("arguments[0].scrollIntoView();", element)
    sleep(0.5)  # 等待滚动完成
    element.click()

# 安全点击(多种点击方式的组合)
def safe_click(driver, element):
    try:
        element.click()  # 尝试普通点击
    except ElementClickInterceptedException:
        # 如果被遮挡,用JS点击
        driver.execute_script("arguments[0].click();", element)

# 批量操作示例
def batch_delete_items():
    items = driver.find_elements(By.CLASS_NAME, "item")
    for item in items:
        delete_btn = item.find_element(By.CLASS_NAME, "delete")
        safe_click(driver, delete_btn)
        sleep(1)  # 等待删除完成

15. 异常处理

用法:处理自动化过程中的各种异常情况

from selenium.common.exceptions import *

# 基本异常处理
try:
    element = driver.find_element(By.ID, "submit")
    element.click()
except NoSuchElementException:
    print("找不到提交按钮,可能页面结构发生变化")
except TimeoutException:
    print("页面加载超时,网络可能有问题")
except ElementClickInterceptedException:
    print("按钮被其他元素遮挡,尝试滚动页面")
except StaleElementReferenceException:
    print("元素引用已失效,需要重新查找元素")

# 完整的异常处理示例
def robust_click(driver, selector, max_retries=3):
    """健壮的点击函数,包含重试机制"""
    for attempt in range(max_retries):
        try:
            element = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, selector))
            )
            element.click()
            return True  # 成功点击
        except TimeoutException:
            print(f"第{attempt+1}次尝试:等待元素超时")
        except ElementClickInterceptedException:
            print(f"第{attempt+1}次尝试:元素被遮挡,尝试滚动")
            driver.execute_script("window.scrollBy(0, 200);")
        except Exception as e:
            print(f"第{attempt+1}次尝试:未知错误 {e}")
        
        if attempt < max_retries - 1:
            sleep(2)  # 重试前等待
    
    print("所有尝试都失败了")
    return False

# 使用示例
if robust_click(driver, "#difficult-button"):
    print("成功点击按钮")
else:
    print("点击失败,需要人工检查")

16. 性能优化

用法:提高自动化脚本的运行速度和稳定性

# Chrome浏览器性能优化配置
chrome_options = webdriver.ChromeOptions()

# 禁用图片加载(大幅提升速度)
chrome_options.add_argument('--blink-settings=imagesEnabled=false')

# 无头模式(不显示浏览器界面,速度更快)
chrome_options.add_argument('--headless')

# 禁用GPU加速(避免某些环境下的问题)
chrome_options.add_argument('--disable-gpu')

# 禁用开发者工具
chrome_options.add_argument('--disable-dev-shm-usage')

# 设置页面加载策略(不等待所有资源加载完成)
chrome_options.add_argument('--page-load-strategy=eager')

# 禁用扩展
chrome_options.add_argument('--disable-extensions')

# 禁用通知
chrome_options.add_argument('--disable-notifications')

# 创建优化后的驱动
driver = webdriver.Chrome(options=chrome_options)

# 设置较短的页面加载超时
driver.set_page_load_timeout(30)  # 30秒超时

# 实用示例:批量处理时的优化
def optimized_batch_process():
    # 使用无头模式进行批量处理
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    options.add_argument('--disable-images')
    
    driver = webdriver.Chrome(options=options)
    
    urls = ["http://example1.com", "http://example2.com"]
    results = []
    
    for url in urls:
        driver.get(url)
        # 快速获取需要的信息
        title = driver.title
        results.append(title)
    
    driver.quit()
    return results

17. 调试技巧

用法:帮助定位和解决自动化脚本中的问题

# 高亮显示元素(方便调试时查看)
def highlight_element(driver, element, color="red", width=3):
    """高亮显示元素"""
    original_style = element.get_attribute("style")
    driver.execute_script(
        f"arguments[0].style.border='{width}px solid {color}';", 
        element
    )
    sleep(2)  # 显示2秒
    # 恢复原始样式
    driver.execute_script(f"arguments[0].style='{original_style}';", element)

# 获取元素详细信息
def get_element_info(element):
    """获取元素的详细信息用于调试"""
    info = {
        "tag_name": element.tag_name,
        "text": element.text,
        "location": element.location,
        "size": element.size,
        "is_displayed": element.is_displayed(),
        "is_enabled": element.is_enabled()
    }
    return info

# 使用示例
button = driver.find_element(By.ID, "submit")
print("按钮信息:", get_element_info(button))
highlight_element(driver, button)  # 高亮显示按钮

# 检查元素是否在视口内
def is_element_in_viewport(driver, element):
    """检查元素是否在当前视口内"""
    return driver.execute_script("""
        var rect = arguments[0].getBoundingClientRect();
        return (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= window.innerHeight &&
            rect.right <= window.innerWidth
        );
    """, element)

# 调试模式运行(添加详细日志)
def debug_click(driver, selector):
    """调试版本的点击函数"""
    print(f"正在查找元素:{selector}")
    
    try:
        element = driver.find_element(By.CSS_SELECTOR, selector)
        print(f"找到元素:{element.tag_name}")
        
        if not element.is_displayed():
            print("警告:元素不可见")
        
        if not element.is_enabled():
            print("警告:元素不可用")
        
        if not is_element_in_viewport(driver, element):
            print("元素不在视口内,滚动到元素位置")
            driver.execute_script("arguments[0].scrollIntoView();", element)
        
        highlight_element(driver, element)  # 高亮显示
        element.click()
        print("成功点击元素")
        
    except Exception as e:
        print(f"点击失败:{e}")
        driver.save_screenshot("debug_error.png")  # 出错时截图

18. 移动端测试

用法:模拟移动设备进行测试

# 模拟不同移动设备
mobile_devices = {
    "iPhone X": {"deviceName": "iPhone X"},
    "iPad": {"deviceName": "iPad"},
    "Galaxy S5": {"deviceName": "Galaxy S5"},
    "自定义": {
        "deviceMetrics": {
            "width": 375,
            "height": 667,
            "pixelRatio": 2.0
        },
        "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X)"
    }
}

# 创建移动端浏览器
def create_mobile_driver(device="iPhone X"):
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_experimental_option(
        "mobileEmulation", 
        mobile_devices[device]
    )
    return webdriver.Chrome(options=chrome_options)

# 使用示例
mobile_driver = create_mobile_driver("iPhone X")
mobile_driver.get("https://m.baidu.com")

# 触摸操作(注意:TouchActions在新版本中已弃用)
# 推荐使用ActionChains进行移动端操作
def mobile_swipe(driver, start_x, start_y, end_x, end_y):
    """模拟手机滑动操作"""
    ActionChains(driver)\
        .move_by_offset(start_x, start_y)\
        .click_and_hold()\
        .move_by_offset(end_x - start_x, end_y - start_y)\
        .release()\
        .perform()

# 移动端特有操作示例
def mobile_test_example():
    driver = create_mobile_driver("iPhone X")
    driver.get("https://m.taobao.com")
    
    # 模拟向下滑动加载更多
    for i in range(3):
        driver.execute_script("window.scrollBy(0, 500);")
        sleep(2)
    
    # 检查移动端特有元素
    try:
        menu_btn = driver.find_element(By.CLASS_NAME, "mobile-menu")
        menu_btn.click()
        print("成功打开移动端菜单")
    except:
        print("未找到移动端菜单")
    
    driver.quit()

# 响应式测试(测试不同屏幕尺寸)
def responsive_test():
    driver = webdriver.Chrome()
    
    # 测试不同分辨率
    resolutions = [
        (1920, 1080),  # 桌面
        (1366, 768),   # 笔记本
        (768, 1024),   # 平板
        (375, 667)     # 手机
    ]
    
    for width, height in resolutions:
        driver.set_window_size(width, height)
        driver.get("https://example.com")
        
        # 检查布局是否正常
        title = driver.title
        print(f"分辨率 {width}x{height}: {title}")
        
        # 截图保存
        driver.save_screenshot(f"responsive_{width}x{height}.png")
        sleep(2)
    
    driver.quit()
]]>
<![CDATA[五分钟开发ToDoListAPP后端]]> https://www.iarc.top/499.html 2025-08-14T21:15:00+08:00 2025-08-14T21:15:00+08:00 青帝 http://icp.iarc.top 使用CodeBuddy IDE五分钟内即可完成ToDoList基础后端开发,在这个AI工具发达的时代,我们已不需要将全部的知识装进大脑,只需有一个大的框架,细节交给AI即可快速建立项目。
环境配置:Node.js

将项目需求描述给codebuddy,我这里模型选的是GPT-5-nano,只需稍等几十秒钟,项目将会完全构建
mebdpi7q.png
以下是codebuddy生成的项目(未进行任何修改)
index.js:

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

// In-memory storage
let todos = [];
let nextId = 1;

function findTodo(id) {
  return todos.find(t => t.id === id);
}

app.use(express.json());

// Get all todos, with optional filtering by completion status
app.get('/todos', (req, res) => {
  const completed = req.query.completed;
  if (completed !== undefined) {
    const isDone = completed === 'true';
    return res.json(todos.filter(t => t.completed === isDone));
  }
  res.json(todos);
});

// Get a single todo by id
app.get('/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const t = todos.find(t => t.id === id);
  if (!t) return res.status(404).json({ error: 'Todo not found' });
  res.json(t);
});

// Create a new todo
app.post('/todos', (req, res) => {
  const { title, description } = req.body;
  if (!title) return res.status(400).json({ error: 'title is required' });

  const todo = {
    id: nextId++,
    title,
    description: description || '',
    completed: false,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString()
  };
  todos.push(todo);
  res.status(201).json(todo);
});

// Update an existing todo
app.put('/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const t = todos.find(t => t.id === id);
  if (!t) return res.status(404).json({ error: 'Todo not found' });

  const { title, description, completed } = req.body;
  if (title !== undefined) t.title = title;
  if (description !== undefined) t.description = description;
  if (completed !== undefined) t.completed = completed;

  t.updatedAt = new Date().toISOString();
  res.json(t);
});

// Delete a todo
app.delete('/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const idx = todos.findIndex(t => t.id === id);
  if (idx === -1) return res.status(404).json({ error: 'Todo not found' });
  const removed = todos.splice(idx, 1);
  res.json(removed[0]);
});

// Health check (optional)
app.get('/health', (req, res) => {
  res.json({ status: 'ok', todoCount: todos.length });
});

app.listen(port, () => {
  console.log(`Todo backend listening at http://localhost:${port}`);
});

package.json

{
  "name": "todolist-backend",
  "version": "1.0.0",
  "description": "In-memory Todo List backend using Node.js + Express",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

接下来进行npm安装项目运行所需的库,安装完后直接开始运行看看能不能正常跑起来
mebdyaqa.png

测试阶段:
测试接口:(内存存储,重启丢失数据)

请求方式路径功能
GET/todos获取所有待办,可通过查询参数 completed=true/false 进行筛选
POST/todos创建待办,body 示例 { "title": "示例", "description": "可选" }
GET/todos/:id获取指定待办
PUT/todos/:id更新待办,支持 title、description、completed
DELETE/todos/:id删除待办
GET/health健康检查

获取所有待办:

mebe8wrx.png
目前初始化成功但还没有添加数据

创建待办

由于我没有进行前端的编写,这里直接在浏览器控制台模拟前端js发送请求完成接下来的测试,js代码如下:

fetch("/todos", {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ "title": "待办名字", "description": "待办描述" })
})

mebebqwl.png
已成功创建两个待办事项,重新get请求todos可查看已成功添加
mebed9yl.png

通过id获取指定待办信息

mebeeegt.png
mebeet8z.png

更新已有待办事项内容

mebehhgu.png
成功更新
mebehygl.png

删除待办事项

mebejchw.png
mebejr8h.png

健康检测

mebekpzb.png

注意事项:
该版本的待办事项数据仅保存在内存,重启后将全部丢失,仅适合开发/测试阶段。不过接下来可以让codebuddy优化成使用json文件存储或者使用数据库(SQLite、PostgreSQL、MongoDB 等)存储数据,交给各位去继续探索了。

评论区留言“CodeBuddy”抽5位送永久体验码!
CodeBuddyIDE官网:https://www.codebuddy.ai/
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=6g36nynyzup

]]>
<![CDATA[Github账号只要满180天,即可终身享受免费4核8G服务器搭建Alist网盘]]> https://www.iarc.top/492.html 2025-08-01T22:39:00+08:00 2025-08-01T22:39:00+08:00 青帝 http://icp.iarc.top mdsx6sgy.png

ClawCloud Run,它是阿里云青春版Claw Cloud家的,有点像Vercel那种在线开发平台。不管是啥应用、程序,包括Docker应用,都能快速部署,现在已经支持76款热门开源应用一键搞定了。

mdsx1f16.png

福利这块:如果你的GitHub账号注册满180天,能终身享受每月5美金的免费额度;新用户刚注册,也会直接送5美金体验额度,但用完就没了。

mdsx81mi.png

资源配置呢,免费套餐最高能给到10GB流量、4核vCPU、8GB内存、10GB磁盘空间,还有1个工作区,很适合用来部署轻量级的小应用。举个例子,部署Alist搭个个人网盘管理系统,一天下来也就0.07刀,每月5刀的免费额度完全够用,轻量场景用着特别合适。

注册也简单,直接用GitHub账号登录就行。可选地区有美国东部、德国、美国西部、新加坡和日本。从国内访问速度看,新加坡和日本这两个节点更推荐。

mdsx94m1.png

注册完之后,界面上会显示几个核心功能模块:App Launchpad(应用启动)、Database(数据库)、Devbox(开发沙盒)、Object Storage(对象存储)、App Store(应用商店)和Terminal(终端)。

注册地址在这:https://console.run.claw.cloud/signin?link=BSYQATGONVWT
]]>
<![CDATA[祝各位2025新年快乐,这是一份新年礼物,免费主机二级域名等]]> https://www.iarc.top/482.html 2025-01-29T16:22:00+08:00 2025-01-29T16:22:00+08:00 青帝 http://icp.iarc.top 瑞蛇携福至,好运满征途。新的一年,祝您蛇来运转,巳巳如意,创新无限,前程似锦。新年快乐🎉🎉

2025新启程

赠送100台康乐主机

活动链接:http://idc.arcpi.cn

微信图片_20250129161455.jpg

免费二级域名212025.xyz

公益二级域名:http://212025.xyz
微信图片_20250129161504.jpg

祝福网页在线生成

制作地址:http://web.iarc.top
微信图片_20250129161517.jpg

]]>
<![CDATA[油管无水印下载视频工具]]> https://www.iarc.top/480.html 2025-01-27T13:33:00+08:00 2025-01-27T13:33:00+08:00 青帝 http://icp.iarc.top 工具展示

show

最高可支持8K无水印视频下载

使用需知

该工具为英文,如果有的看不懂需要用翻译软件,然后下载速度取决于你的梯的速度,支持下载视频合集。

下载地址

{cloud title="油管无水印视频下载" type="default" url="https://pan.quark.cn/s/9f01f8c5ee7b" password=""/}

]]>
<![CDATA[魔幻粒子新年快乐祝福源码]]> https://www.iarc.top/479.html 2025-01-27T13:23:00+08:00 2025-01-27T13:23:00+08:00 青帝 http://icp.iarc.top 效果图

新年快乐

源码介绍

魔幻粒子新年祝福是一段基于HTML5 Canvas制作的粒子爆炸,矩阵显字的动画特效代码,给人一种非常大气的视觉感,欢迎对此段代码感兴趣的朋友前来下载使用。

源码由HTML+CSS+JS组成,记事本打开源码文件可以进行内容文字之类的修改

下载地址

{cloud title="魔幻粒子新年祝福源码" type="default" url="https://pan.quark.cn/s/3323cd0b8b51" password=""/}

]]>
<![CDATA[大陆和香港高性价比云服务器推荐两家,都有着十几年沉淀的大厂]]> https://www.iarc.top/461.html 2024-07-24T01:14:00+08:00 2024-07-24T01:14:00+08:00 青帝 http://icp.iarc.top 本文所提及的服务器商都是本站所用过至少1年的,2核2G服务器每年的价格都是在100元以下(续费不涨价),比一些小厂的还实惠,个人感觉没必要按月去租,既用了就买个一年的更具性价比。

阿里云

1年配置
99元2核2G,3M固定带宽不限流量,40G ESSD Entry云盘

{abtn icon="fa-diamond" color="#ff6800" href="https://www.aliyun.com/benefit?scm=20140722.M_185600978.P_114.MO_2274-ID_10517682-MID_10517682-CID_31491-ST_11142-V_1&source=5176.29345612&userCode=m2urtzth" radius="5px" content="点我前往阿里云活动页"/}

阿里云

性价比

{progress percentage="90%" color="#fff56b"/}
宽带只有3M,装个win10系统当成云电脑从网上下文件网速几十M比3M快多了,但是从服务器上下文件到本地就3M左右,个人博客类的站点够用。

稳定性

{progress percentage="99%" color="#fff56b"/}
排除被人为打黑洞里了一次,用了一年期间没有连不上的情况。

野草云

1年配置
99元2核2G,100Mbps优质BGP宽带每月限600GB流量(超出限速1M),30GB SSD存储

99

香港AMD Linux VPS折后价格表:

1年配置
81.4元1核1G,100Mbps优质BGP,600GB月流量(超出限速1M),15GB SSD存储
96.2元1核2G,100Mbps优质BGP,600GB月流量(超出限速1M),15GB SSD存储

一年付3.8折优惠码:12THBIRTHDAY
81.4
96.2

{abtn icon="fa-diamond" color="#ff6800" href="https://my.yecaoyun.com/aff.php?aff=2415" radius="5px" content="点我前往野草云活动页"/}

性价比

{progress percentage="100%" color="#fff56b"/}
100MbpsBGP线路在国内实测下载速度是10M左右,比3M快了三四倍。就是一个月只有600GB流量,超过600GB就会被限速,我这一年用的过程中一个月最高用的还不到100GB了,正常建网站完全够用,如果用这搭梯子翻墙的话用的可能多一点。下载应用确实比国内服务器舒服,不用弄镜像源了,这可以直连github等代码仓库。

稳定性

{progress percentage="80%" color="#fff56b"/}
一年里有两次断网超过12小时(都是小概率事件都被我撞上了),我看他们公告发了几次重启断网公告,这我倒是没察觉到。
dw1.jpg
财务系统被入侵了,强制给我重置了root密码并关机了 ::(黑线)
dw2.jpg
香港地震给机房震断电了
dw3.jpg

最后

目前我就这两家的服务器用的时长都超过一年了(内陆阿里云,海外野草云),其他家的没用过不做评价。
确实超过一年了
这是第二年的阿里云服务器
腾讯云、华为云、移动云等这些国内有名的也有很多便宜的服务器可以关注一下,但都是大陆空间都需要icp备案。
野草云除了隔几个月用十几分钟重启一下,没有啥毛病了,网速能接受,用来装xui最合适了,也是运营了12年应该不会跑路的。不过要极致稳定就选阿里云,要宽带和基本稳定就选野草云,香港离大陆也不算远,延迟不算高,给网站套个国内的CDN也可以缓解延迟。

如果有更便宜更具性价比的服务器欢迎留言:@(献花)

]]>
<![CDATA[Joe文章列表添加渐变颜色效果]]> https://www.iarc.top/452.html 2024-07-07T00:41:00+08:00 2024-07-07T00:41:00+08:00 青帝 http://icp.iarc.top 一个大气的文章列表CSS渐变动画,也可以使用图片作为渐变背景,,效果如下(鼠标移动到元素上后颜色会更加突出):
  • 日间模式
    1
  • 夜间模式
    2

    接下来需要编辑的文件以及相对Joe主题的文件路径:

  • joe.index.js /Joe/assets/js
  • joe.index.css /Joe/assets/css
  • joe.mode.css/Joe/assets/css

开始(共三部分)

{tabs}
{tabs-pane label="添加HTML代码"}
打开joe.index.js文件找到如图所示位置
3
可以直接搜joe_list__item wow default定位到,其实一打开就是了。
在第一个a标签元素后面加入如下代码

<div class="article-banner-wrap"></div>
<div class="article-banner"></div>

4
{/tabs-pane}
{tabs-pane label="添加CSS代码"}
直接将下面的css代码复制粘贴到joe.index.css文件的最后面就行了

/*首页列表渐变*/
.article-banner-wrap {
    position: absolute;
    height: 100%;
    width: 50%;
    right: 0;
    top: 0;
}

.article-banner {
    visibility: hidden;
    opacity: .2;
    position: absolute;
    height: 100%;
    width: 50%;
    right: 0;
    top: 0;
    z-index: 0;
    background-repeat: no-repeat;
    background-size: cover;
    -webkit-background-size: cover;
    -o-background-size: cover;
    background-position: center center;
transition: opacity 0.2s;
-webkit-mask-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%);
border-radius: 8px;
background:linear-gradient(to left,#2BC0E4,#EAECC6);
visibility: visible;
animation: banner-show 1s;
}
.joe_list__item.default:hover .article-banner{opacity: 1;}

5
其中的background可以改成图片地址,这样效果就是图片了,但图片会拖累网站加载速度,可自行决定是否要换成图片。
{/tabs-pane}
{tabs-pane label="适配夜间模式"}
打开joe.mode.css文件,将以下CSS代码加入文件底部即可。

/*首页列表图片渐变夜间模式*/
html[data-night='night'] .article-banner{
    background: linear-gradient(to left,#1F1C2C,#928DAB);
    opacity:0.1
}

6

我这里不是最底部是因为我后来又加其他东西了,其实也不是一定要最底部,只是方便小白操作和自己描述了。
{/tabs-pane}
{/tabs}

]]>
<![CDATA[一款自适应的开源纯静态音乐播放器]]> https://www.iarc.top/446.html 2024-05-05T16:40:00+08:00 2024-05-05T16:40:00+08:00 青帝 http://icp.iarc.top 一个基于AplayerMetingJS的静态音乐播放器

预览

{anote icon="music" href="https://lab.iarc.top/concert/" type="info" content="音乐厅"/}

lvt9j8vv.png
lvta2r0s.png

基本操作

Space空格键:暂停/播放音乐

上/下方向键:增加/减少音量

左/右方向键:上一曲/下一曲

ID

播放列表的id,可以从音乐歌单分享的链接中获取,例如https://y.qq.com/n/ryqq/playlist/8668419170中,id为8668419170
网易云也同理。

Server

播放列表的服务商,例如netease(网易云音乐),tencent(腾讯),kugou(酷狗),xiami(小米音乐),baidu(百度音乐)

使用URL参数(推荐)

支持URL参数 https://lab.iarc.top/concert/?id=+ id +&server= + server

例:
鸡你太美: https://lab.iarc.top/concert/?id=2762963245&server=netease

项目开源地址

原作者开源地址:
{cloud title="原版地址" type="github" url="https://github.com/zhheo/HeoMusic" password=""/}

圆弧派二开地址:
{cloud title="二开地址" type="github" url="https://github.com/QingDi2/lab/tree/main/concert" password=""/}
二开新增功能:下载、标题、网易云歌单id输入框,其余原版功能未做删减。
全开源各位可以随便改

]]>
<![CDATA[用cfpages免费建个干净大气的程序介绍页[附源码]]]> https://www.iarc.top/437.html 2024-05-04T22:35:00+08:00 2024-05-04T22:35:00+08:00 青帝 http://icp.iarc.top 引流方法之一,都知道微信小程序只能在微信内搜索到,在百度搜索引擎等搜不到,所以建个单页有助于从搜索引擎上获得用户。

介绍页演示站:https://mxam.arcpi.cn
演示图:
看破不说破
源码都是静态文件,所以直接用cf pages网站托管平台免费建,当时vercel也可以的。

cf pages官网地址:戳我前往(无需魔法也能正常用)
一级棒
选免费套餐就行,注册个号进去后也不用实名验证啥的,可以直接创建项目,然后把源码压缩包往里面一丢他会自动解压,最后cname解析一下域名就OK了
真心好用的
源码下载:

{hide}

{cloud title="程序介绍页" type="lz" url="https://xql.lanzouw.com/icQsm1xp287c" password=""/}
那个小程序源码好像都泛滥了,要是没泛滥的话留个言,过几天我再发出来吧
{/hide}

]]>