吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1044|回复: 15
收起左侧

[Python 原创] 简单的使用python获取一言

  [复制链接]
Serendisand 发表于 2026-8-2 18:18
本帖最后由 Serendisand 于 2026-8-3 13:07 编辑

一言语录获取工具 - 完整技术文档

项目简介

一言语录获取工具是一个简单而强大的Python程序,用于从 一言 API 获取随机的中文语录。该工具提供了多种HTTP请求实现方案,并包含友好的命令行交互界面。

功能特点

  • 🔄 获取随机中文语录
  • 📝 显示语录来源和作者信息
  • 🏷️ 显示语录分类
  • 🔌 支持4种不同的HTTP请求方式
  • 🛡️ 完善的错误处理机制
  • 🎨 友好的命令行界面

问题背景

一言API默认会屏蔽不包含 User-Agent 头的请求,特别是使用Python标准库 urllib 时,默认的User-Agent会被识别并拒绝访问。

错误示例:

# ❌ 这样会失败
import urllib.request
response = urllib.request.urlopen('https://v1.hitokoto.cn/')
# 返回:403 Forbidden
解决方案: 在请求头中添加合法的 User-Agent。

解决方案

方案对比

方案 优点 缺点 推荐度
方案1 urllib 标准库,无需安装 API较原始 ⭐⭐⭐
方案2 requests API友好,功能丰富 需第三方库 ⭐⭐⭐⭐⭐
方案3 httpx 支持HTTP/2,异步 需第三方库 ⭐⭐⭐⭐
方案4 aiohttp 纯异步,高性能 需第三方库 ⭐⭐⭐

完整代码

方案1:使用 urllib(标准库)

import json
import urllib.request
import urllib.error

def get_hitokoto():
    """
    使用urllib获取一言语录

    Returns:
        dict: 包含语录信息,失败返回None
    """
    try:
        url = "https://v1.hitokoto.cn/"

        # 创建请求并添加User-Agent
        req = urllib.request.Request(url)
        req.add_header(
            'User-Agent',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        )

        # 发送请求
        with urllib.request.urlopen(req, timeout=10) as response:
            data = response.read()
            result = json.loads(data.decode('utf-8'))

            return {
                'hitokoto': result['hitokoto'],
                'from': result.get('from', ''),
                'from_who': result.get('from_who', ''),
                'type': result['type'],
                'id': result.get('id', '')
            }

    except urllib.error.HTTPError as e:
        print(f"HTTP错误: {e.code} - {e.reason}")
        return None
    except urllib.error.URLError as e:
        print(f"网络错误: {e.reason}")
        return None
    except json.JSONDecodeError as e:
        print(f"数据解析错误: {e}")
        return None
    except Exception as e:
        print(f"未知错误: {e}")
        return None

def main():
    """主程序"""
    print("=" * 50)
    print("一言语录获取工具 v1.0 (urllib)")
    print("=" * 50)

    while True:
        print("\n1. 获取随机语录")
        print("2. 退出程序")
        choice = input("\n请选择操作 (1/2): ").strip()

        if choice == '1':
            print("\n正在获取语录...")
            quote = get_hitokoto()

            if quote:
                print("\n" + "=" * 40)
                print(f"「{quote['hitokoto']}」\n")

                # 显示来源信息
                if quote['from_who'] or quote['from']:
                    print("——", end="")
                    if quote['from_who']:
                        print(f" {quote['from_who']}", end="")
                    if quote['from']:
                        if quote['from_who']:
                            print(f" 《{quote['from']}》")
                        else:
                            print(f" 《{quote['from']}》")
                    else:
                        print()

                print(f"分类: {quote['type']}")
                print("=" * 40)
            else:
                print("❌ 获取失败,请检查网络连接!")

        elif choice == '2':
            print("\n感谢使用,再见!👋")
            break
        else:
            print("❌ 无效选择,请输入1或2!")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n程序被中断,再见!👋")

方案2:使用 requests(推荐)

import requests
import json

def get_hitokoto():
    """
    使用requests获取一言语录

    Returns:
        dict: 包含语录信息,失败返回None
    """
    try:
        url = "https://v1.hitokoto.cn/"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Accept': 'application/json',
            'Accept-Language': 'zh-CN,zh;q=0.9'
        }

        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()  # 检查HTTP错误

        result = response.json()

        return {
            'hitokoto': result['hitokoto'],
            'from': result.get('from', ''),
            'from_who': result.get('from_who', ''),
            'type': result['type'],
            'id': result.get('id', '')
        }

    except requests.exceptions.HTTPError as e:
        print(f"HTTP错误: {e.response.status_code}")
        return None
    except requests.exceptions.ConnectionError:
        print("网络连接失败,请检查网络")
        return None
    except requests.exceptions.Timeout:
        print("请求超时")
        return None
    except json.JSONDecodeError as e:
        print(f"数据解析错误: {e}")
        return None
    except Exception as e:
        print(f"未知错误: {e}")
        return None

def display_quote(quote):
    """显示语录"""
    if not quote:
        print("❌ 获取失败")
        return

    print("\n" + "=" * 40)
    print(f"「{quote['hitokoto']}」\n")

    # 构建来源信息
    source_parts = []
    if quote['from_who']:
        source_parts.append(quote['from_who'])
    if quote['from']:
        source_parts.append(f"《{quote['from']}》")

    if source_parts:
        print("—— " + " ".join(source_parts))

    print(f"分类: {quote['type']}")
    print("=" * 40)

def main():
    """主程序"""
    print("=" * 50)
    print("一言语录获取工具 v1.0 (requests)")
    print("=" * 50)

    while True:
        print("\n1. 获取随机语录")
        print("2. 退出程序")
        choice = input("\n请选择操作 (1/2): ").strip()

        if choice == '1':
            print("\n正在获取语录...")
            quote = get_hitokoto()
            display_quote(quote)
        elif choice == '2':
            print("\n感谢使用,再见!👋")
            break
        else:
            print("❌ 无效选择,请输入1或2!")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n程序被中断,再见!👋")

方案3:使用 httpx(支持HTTP/2)

import httpx
import json

def get_hitokoto():
    """
    使用httpx获取一言语录

    Returns:
        dict: 包含语录信息,失败返回None
    """
    try:
        url = "https://v1.hitokoto.cn/"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        }

        with httpx.Client(http2=True, timeout=10.0) as client:
            response = client.get(url, headers=headers)
            response.raise_for_status()

            result = response.json()

            return {
                'hitokoto': result['hitokoto'],
                'from': result.get('from', ''),
                'from_who': result.get('from_who', ''),
                'type': result['type'],
                'id': result.get('id', '')
            }

    except httpx.HTTPStatusError as e:
        print(f"HTTP错误: {e.response.status_code}")
        return None
    except httpx.ConnectError:
        print("网络连接失败")
        return None
    except httpx.TimeoutException:
        print("请求超时")
        return None
    except json.JSONDecodeError as e:
        print(f"数据解析错误: {e}")
        return None
    except Exception as e:
        print(f"未知错误: {e}")
        return None

def main():
    """主程序"""
    print("=" * 50)
    print("一言语录获取工具 v1.0 (httpx)")
    print("=" * 50)

    while True:
        print("\n1. 获取随机语录")
        print("2. 退出程序")
        choice = input("\n请选择操作 (1/2): ").strip()

        if choice == '1':
            print("\n正在获取语录...")
            quote = get_hitokoto()

            if quote:
                print("\n" + "=" * 40)
                print(f"「{quote['hitokoto']}」\n")

                if quote['from_who'] or quote['from']:
                    print("——", end="")
                    if quote['from_who']:
                        print(f" {quote['from_who']}", end="")
                    if quote['from']:
                        if quote['from_who']:
                            print(f" 《{quote['from']}》")
                        else:
                            print(f" 《{quote['from']}》")
                    else:
                        print()

                print(f"分类: {quote['type']}")
                print("=" * 40)
            else:
                print("❌ 获取失败,请检查网络连接!")

        elif choice == '2':
            print("\n感谢使用,再见!👋")
            break
        else:
            print("❌ 无效选择,请输入1或2!")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n程序被中断,再见!👋")
方案4:使用 aiohttp(异步)
python
import asyncio
import aiohttp
import json

async def get_hitokoto_async():
    """
    异步获取一言语录

    Returns:
        dict: 包含语录信息,失败返回None
    """
    try:
        url = "https://v1.hitokoto.cn/"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        }

        timeout = aiohttp.ClientTimeout(total=10)

        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers, timeout=timeout) as response:
                if response.status != 200:
                    print(f"HTTP错误: {response.status}")
                    return None

                result = await response.json()

                return {
                    'hitokoto': result['hitokoto'],
                    'from': result.get('from', ''),
                    'from_who': result.get('from_who', ''),
                    'type': result['type'],
                    'id': result.get('id', '')
                }

    except aiohttp.ClientConnectorError:
        print("网络连接失败")
        return None
    except asyncio.TimeoutError:
        print("请求超时")
        return None
    except json.JSONDecodeError as e:
        print(f"数据解析错误: {e}")
        return None
    except Exception as e:
        print(f"未知错误: {e}")
        return None

def get_hitokoto():
    """同步包装器,调用异步函数"""
    return asyncio.run(get_hitokoto_async())

async def get_multiple_hitokoto_async(count=5):
    """异步批量获取多条语录"""
    tasks = [get_hitokoto_async() for _ in range(count)]
    results = await asyncio.gather(*tasks)
    return [r for r in results if r is not None]

def get_multiple_hitokoto(count=5):
    """同步批量获取多条语录"""
    return asyncio.run(get_multiple_hitokoto_async(count))

def main():
    """主程序"""
    print("=" * 50)
    print("一言语录获取工具 v1.0 (aiohttp)")
    print("=" * 50)

    while True:
        print("\n1. 获取随机语录")
        print("2. 批量获取5条语录")
        print("3. 退出程序")
        choice = input("\n请选择操作 (1/2/3): ").strip()

        if choice == '1':
            print("\n正在获取语录...")
            quote = get_hitokoto()

            if quote:
                print("\n" + "=" * 40)
                print(f"「{quote['hitokoto']}」\n")

                if quote['from_who'] or quote['from']:
                    print("——", end="")
                    if quote['from_who']:
                        print(f" {quote['from_who']}", end="")
                    if quote['from']:
                        if quote['from_who']:
                            print(f" 《{quote['from']}》")
                        else:
                            print(f" 《{quote['from']}》")
                    else:
                        print()

                print(f"分类: {quote['type']}")
                print("=" * 40)
            else:
                print("❌ 获取失败,请检查网络连接!")

        elif choice == '2':
            print("\n正在批量获取5条语录...")
            quotes = get_multiple_hitokoto(5)

            if quotes:
                print("\n" + "=" * 40)
                for i, quote in enumerate(quotes, 1):
                    print(f"{i}. 「{quote['hitokoto']}」")
                    if quote['from_who'] or quote['from']:
                        source = []
                        if quote['from_who']:
                            source.append(quote['from_who'])
                        if quote['from']:
                            source.append(f"《{quote['from']}》")
                        print(f"   —— {' '.join(source)}")
                    print()
                print("=" * 40)
            else:
                print("❌ 获取失败,请检查网络连接!")

        elif choice == '3':
            print("\n感谢使用,再见!👋")
            break
        else:
            print("❌ 无效选择,请输入1、2或3!")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n程序被中断,再见!👋")

使用说明

安装依赖
方案1(urllib)

# 无需安装额外依赖,使用Python标准库即可

方案2(requests)

pip install requests

方案3(httpx)

pip install httpx```
方案4(aiohttp)
```bash
pip install aiohttp```
## 运行程序
```bash
# 直接运行
python hitokoto.py```

## API参数说明
一言API支持多种查询参数,可以根据需要定制:

参数        类型        说明        可选值
c        string        分类筛选        a(动画), b(漫画), c(游戏), d(文学), e(原创), f(网络), g(其他), h(影视), i(诗词), j(网易云), k(哲学), l(抖机灵)
encode        string        返回格式        json(默认), text
charset        string        字符编码        utf-8(默认)

### 带参数的示例
```python
def get_hitokoto_by_category(category='a'):
    """
    获取指定分类的语录

    Args:
        category: 分类代码 (a,b,c,d,e,f,g,h,i,j,k,l)
    """
    try:
        url = f"https://v1.hitokoto.cn/?c={category}"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }

        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()

        result = response.json()
        return result['hitokoto']

    except Exception as e:
        print(f"获取失败: {e}")
        return None

使用示例

quote = get_hitokoto_by_category('a')  # 获取动画分类的语录
print(quote)

分类代码对照表
代码        分类        代码        分类
a        动画        g        其他
b        漫画        h        影视
c        游戏        i        诗词
d        文学        j        网易云
e        原创        k        哲学
f        网络        l        抖机灵

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
木木小白 + 1 + 1 我很赞同!
fengzhongdexin + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

symbx 发表于 2026-8-3 09:27
[Python] 纯文本查看 复制代码
import json
import urllib.request
import urllib.parse

def get_hitokoto():
    """使用urllib获取一言语录"""
    try:
        # 一言API地址
        url = "https://v1.hitokoto.cn/"

        # 创建请求(hitokoto API 要求带 User-Agent,否则返回 403)
        req = urllib.request.Request(url, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                          '(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Accept': 'application/json',
        })

        # 发送请求并获取响应
        with urllib.request.urlopen(req, timeout=10) as response:
            # 读取响应内容
            data = response.read()
            # 解码JSON
            result = json.loads(data.decode('utf-8'))

            return {
                'hitokoto': result['hitokoto'],
                'from': result.get('from', ''),
                'from_who': result.get('from_who', ''),
                'type': result['type']
            }

    except Exception as e:
        print(f"获取失败: {e}")
        return None

def main():
    """主程序"""
    print("=" * 50)
    print("一言语录获取工具")
    print("=" * 50)

    while True:
        try:
            print("\n1. 获取随机语录")
            print("2. 退出程序")
            choice = input("\n请选择操作 (1/2): ").strip()

            if choice == '1':
                print("\n正在获取语录...")
                quote = get_hitokoto()

                if quote:
                    print("\n" + "=" * 40)
                    print(f"「{quote['hitokoto']}」\n")

                    if quote['from_who'] or quote['from']:
                        print("——", end="")
                        if quote['from_who']:
                            print(f" {quote['from_who']}", end="")
                        if quote['from']:
                            if quote['from_who']:
                                print(f" 《{quote['from']}》")
                            else:
                                print(f" 《{quote['from']}》")
                        else:
                            print()

                    print(f"分类: {quote['type']}")
                    print("=" * 40)
                else:
                    print("获取失败,请检查网络连接!")

            elif choice == '2':
                print("\n感谢使用,再见!")
                break
            else:
                print("无效选择,请输入1或2!")

        except KeyboardInterrupt:
            print("\n\n程序被中断,再见!")
            break
        except Exception as e:
            print(f"发生错误: {e}")

if __name__ == "__main__":
    main()




少了个User-Agent 请求头,现在不会出现403
rocwang 发表于 2026-8-3 01:33
正在获取语录...
获取失败: HTTP Error 403: Forbidden
获取失败,请检查网络连接!

1. 获取随机语录
2. 退出程序
wu1357924680 发表于 2026-8-2 23:17
开创者 发表于 2026-8-2 23:59
试了一下,直接返回403
AAAZeus 发表于 2026-8-3 01:15
想进步还得来这啊!感谢分享
rocwang 发表于 2026-8-3 01:28
然后用到哪里呢
木木小白 发表于 2026-8-3 09:16
开创者 发表于 2026-8-2 23:59
试了一下,直接返回403

一言API 屏蔽了 Python 默认的请求头(User-Agent)。
木木小白 发表于 2026-8-3 09:17
rocwang 发表于 2026-8-3 01:33
正在获取语录...
获取失败: HTTP Error 403: Forbidden
获取失败,请检查网络连接!

一言API 屏蔽了 Python 默认的请求头(User-Agent)。
huaconglan 发表于 2026-8-3 09:24
代码多了。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-18 22:48

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表