You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django应用中用Python检测PDF中的选中文本?

在Django应用中捕获PDF查看器内的选中文本

问题分析

你原有的本地脚本通过xdotool模拟Ctrl+C、pyperclip读取剪贴板能获取PDF选中文本,但集成到Django后完全失效,核心原因有两个:

  1. 服务器/客户端隔离:Django运行在服务器进程中,xdotool和pyperclip操作的是服务器的桌面环境与剪贴板,和用户浏览器端的PDF查看器完全无关。
  2. 视图逻辑错误:Django视图必须在单次请求中返回响应,你写的while True会阻塞请求,永远无法正常返回页面。

要实现捕获用户在PDF中主动选中的文本,必须从**客户端(浏览器)**入手,通过前端JavaScript获取选中文本后再发送到后端。

解决方案:用PDF.js实现前端文本捕获

原生<embed>标签无法获取PDF内的选中内容,推荐使用PDF.js(Mozilla开源的PDF渲染库)来渲染PDF,它允许通过JavaScript监听并获取用户选中的文本,再通过AJAX发送到Django后端。

1. 修改前端模板(viewer.html)

替换原生<embed>为PDF.js渲染容器,添加选中文本监听与AJAX发送逻辑:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PDF Viewer</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- 引入PDF.js核心库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
    <style>
        #pdf-container {
            width: 100%;
            height: 600px;
            border: 1px solid #eee;
        }
        #selected-text-result {
            margin-top: 10px;
            padding: 8px;
            background: #f5f5f5;
        }
    </style>
</head>
<body>
    <div id="pdf-container"></div>
    <button id="readButton" style="margin-top:10px;">读取选中内容</button>
    <div id="selected-text-result"></div>

    <script>
        // 配置PDF.js工作线程
        const pdfjsLib = window['pdfjs-dist/build/pdf'];
        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';

        let pdfDoc = null;
        const container = document.getElementById('pdf-container');

        // 渲染PDF页面
        function renderPage(pageNum) {
            pdfDoc.getPage(pageNum).then(page => {
                const viewport = page.getViewport({ scale: 1.5 });
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');
                canvas.height = viewport.height;
                canvas.width = viewport.width;
                container.appendChild(canvas);

                // 渲染PDF到画布
                page.render({ canvasContext: ctx, viewport }).promise.then(() => {
                    // 监听画布上的鼠标松开事件,获取选中文本
                    canvas.addEventListener('mouseup', () => {
                        const selection = window.getSelection();
                        if (selection.toString().trim()) {
                            console.log('当前选中:', selection.toString());
                        }
                    });
                });
            });
        }

        // 加载PDF文件
        pdfjsLib.getDocument('{% static "class3english.pdf" %}').promise.then(pdf => {
            pdfDoc = pdf;
            // 渲染第一页,如需多页可循环调用renderPage
            renderPage(1);
        });

        // 点击按钮发送选中文本到后端
        $(document).ready(() => {
            $('#readButton').click(() => {
                const selectedText = window.getSelection().toString().trim();
                if (!selectedText) {
                    alert('请先选中PDF中的文本');
                    return;
                }

                $.ajax({
                    url: '{% url "detectingWordSentences" %}',
                    type: 'POST',
                    data: {
                        'selected_text': selectedText,
                        'csrfmiddlewaretoken': '{{ csrf_token }}'
                    },
                    success: response => {
                        $('#selected-text-result').text('后端已接收选中文本: ' + response.received_text);
                    },
                    error: (xhr, status, err) => {
                        console.error('请求失败:', err);
                    }
                });
            });
        });
    </script>
</body>
</html>

2. 修改Django视图(views.py)

移除错误的循环逻辑,处理前端发送的POST请求:

from django.shortcuts import render
from django.http import JsonResponse

def get_selected_text_view(request):
    if request.method == 'POST':
        # 获取前端发送的选中文本
        selected_text = request.POST.get('selected_text', '').strip()
        if selected_text:
            print("收到选中文本:", selected_text)
            # 返回响应给前端
            return JsonResponse({'received_text': selected_text})
        else:
            return JsonResponse({'error': '未提供有效选中文本'}, status=400)
    # GET请求返回PDF查看页面
    return render(request, 'grad_school/viewer.html')

3. 配置URL路由

确保你的urls.py中添加对应的路由:

from django.urls import path
from . import views

urlpatterns = [
    path('pdf-viewer/', views.get_selected_text_view, name='detectingWordSentences'),
    # 其他路由...
]

关键说明

  • 所有选中文本的操作都在用户浏览器端完成,避免了服务器与客户端环境隔离的问题。
  • PDF.js提供了完整的PDF渲染与交互API,支持多页渲染、文本选中、搜索等功能,比原生<embed>更可控。
  • Django视图遵循请求-响应模式,不再有阻塞性的循环逻辑,符合Web应用的运行机制。

内容的提问来源于stack exchange,提问作者kishan Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:54:51