admin管理员组

文章数量:1401176

from flask import Flask, request, render_template, Response
import pandas as pd
from selenium import webdriver
from selenium.webdrivermon.by import By
import time
from tqdm import tqdm
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager


app = Flask(__name__)
data_store = {}

class LocationAutomation:
    def __init__(self):
        self.driver = None

    def setup_driver(self, headless=False):
        options = webdriver.ChromeOptions()

        if headless:
            options.add_argument('--headless')  # Only add if running in headless mode
        options.add_argument('--start-maximized')  # Open in full-screen
        options.add_argument('--disable-blink-features=AutomationControlled')  # Helps avoid detection

        service = Service(ChromeDriverManager().install())

        self.driver = webdriver.Chrome(service=service, options=options)

        # Go to the login page
        self.driver.get('')
        if not headless:
            input("Please log in manually in the browser, then press Enter to continue...")

    def locationsave(self, df, length):
        if self.driver is None:
            self.setup_driver()

        df['SiteId'] = df['SiteId'].str.lower()
        df['id'] = df['id'].str.lower()
        df = df.drop_duplicates(subset=['id', 'SiteId'])
        df['Links'] = '/' + df['SiteId'] + '/location/' + df['id'] + '/about'

        errors = []
        total = min(length, len(df))
        for i in range(min(length, len(df))):
            self.driver.get(df['Links'].iloc[i])
            time.sleep(5)
            try:
                plus = self.driver.find_element(By.XPATH, '//location-profile-settings/mat-card/div[1]/button')
                plus.click()
                time.sleep(1)
                save_button = self.driver.find_element(By.XPATH, '//fuse-sidebar[1]/drawer/div[2]/div[1]/div[2]/button/span[1]')
                save_button.click()
                time.sleep(5)
            except Exception:
                errors.append(df.iloc[i])

            progress = int((i + 1) / total * 100)  # ➡️ Calculate percentage progress
            yield f"data: {progress}\n\n"  # ➡️ Send progress update to frontend

        if errors:
            error_df = pd.DataFrame(errors)
            error_df.to_excel('LocationSave_Errors.xlsx', index=False)
            yield "data: 100\n\n"  # ➡️ Ensure progress bar reaches 100%
            yield "data: Some locations failed. Check 'LocationSave_Errors.xlsx'.\n\n"  # ➡️ Streaming error message
        else:
            yield "data: 100\n\n"  # ➡️ Ensure progress bar reaches 100%
            yield "data: All locations processed successfully!\n\n"  # ➡️ Streaming success message


automation = LocationAutomation()

@app.route("/")
def home():
    return render_template("index.html", dataframes=list(data_store.keys()), message=None, preview=None)

@app.route("/upload_excel", methods=["POST"])
def upload_excel():
    file = request.files['file']
    name = request.form['name']

    if not file or not name:
        return render_template("index.html", message="Please upload a file and provide a name.", 
                               dataframes=list(data_store.keys()), preview=None)

    df = pd.read_excel(file)
    data_store[name] = df
    return render_template("index.html", message=f"DataFrame '{name}' uploaded successfully.",
                           dataframes=list(data_store.keys()), preview=None)

@app.route("/run/getsql", methods=["POST"])
def run_getsql():
    name = request.form['name']

    if name not in data_store:
        return render_template("index.html", message=f"Data '{name}' not found.", 
                               dataframes=list(data_store.keys()), preview=None)

    df = data_store[name]
    preview = df.head(10).to_html(classes="table table-bordered table-striped")

    return render_template("index.html", message=f"GetSQL Function executed for '{name}'.",
                           dataframes=list(data_store.keys()), preview=preview)

@app.route("/progress/locationsave", methods=["GET"])  # ✅ Only allow GET requests
def run_locationsave():
    name = request.args.get("name")  # ✅ Use request.args for GET requests
    length = request.args.get("length")

    if not name or name not in data_store:
        return Response("data: 0\n\n", mimetype="text/event-stream")  # ✅ Return valid event-stream format

    df = data_store[name]
    length = int(length) if length else len(df)  # ✅ Ensure length is an integer

    return Response(automation.locationsave(df, length), mimetype="text/event-stream")
  # ➡️ Return a streaming response


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000,debug=True)

Below is the html file

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Excel Automation App</title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
    <div class="container">
        <h1>Excel Automation App</h1>

        <div class="section">
            <h2>Upload Excel File</h2>
            <form action="/upload_excel" method="post" enctype="multipart/form-data">
                <input type="text" name="name" placeholder="Data Name" required>
                <input type="file" name="file" required>
                <button type="submit">Upload</button>
            </form>
        </div>

        {% if message %}
        <div class="message">{{ message }}</div>
        {% endif %}

        {% if dataframes %}
        <div class="section">
            <h2>DataFrame Actions</h2>
            <form action="/run/getsql" method="post">
                <label>Select DataFrame:</label>
                <select name="name" required>
                    {% for name in dataframes %}
                    <option value="{{ name }}">{{ name }}</option>
                    {% endfor %}
                </select>
                <button type="submit">Run GetSQL (Preview)</button>
            </form>

            <form id="locationsaveForm" onsubmit="startLocationSave(); return false;">  <!-- ✅ Prevents page reload -->
                <label>Select DataFrame:</label>
                <select id="dataframeName" name="name" required>
                    {% for name in dataframes %}
                    <option value="{{ name }}">{{ name }}</option>
                    {% endfor %}
                </select>
                 <!-- ➡️ Added input field for length -->
                 <label for="length">Number of Rows to Process:</label>  
                 <input type="number" id="length" name="length" placeholder="Enter row count" min="1">  
 
                 <button type="submit">Run LocationSave</button>
            </form>  <!-- ➡️ End of modified form -->
        </div>
        {% endif %}

        {% if preview %}
        <div class="section">
            <h2>Preview (First 10 Rows)</h2>
            {{ preview|safe }}
        </div>
        {% endif %}
        <h2>Progress</h2>
        <progress id="progressBar" value="0" max="100"></progress>
        <div id="progressText">0%</div>  <!-- ✅ Display percentage -->
        <script>
            function startLocationSave() {
                let name = document.getElementById("dataframeName").value;
                let length = document.getElementById("length").value;
        
                // ✅ Reset progress bar before starting
                document.getElementById("progressBar").value = 0;
                document.getElementById("progressText").innerText = "0%";
        
                // ✅ Ensure query parameters are passed correctly
                let url = `/progress/locationsave?name=${encodeURIComponent(name)}&length=${encodeURIComponent(length)}`;
                
                let eventSource = new EventSource(url);  // ✅ Streaming request using GET
                
                eventSource.onmessage = function(event) {
                    let progress = parseInt(event.data);
                    document.getElementById("progressBar").value = progress;
                    document.getElementById("progressText").innerText = progress + "%";
        
                    if (progress >= 100) {
                        eventSource.close();
                    }
                };
        
                eventSource.onerror = function(event) {
                    console.error("EventSource error:", event);
                    eventSource.close();
                };
            }
        </script>
        
        
        
    </body>
    </html>

I am getting the below error while clicking the runlocation function Method Not Allowed The method is not allowed for the requested URL.

please help I am in a learning process.

it was working fine before but when I modified the code for the progress bar it is suddenly giving an error. It seems it is because of the method. Please help.

本文标签: pythonFlask application getting problem in creating the live progress bar in the UIStack Overflow