Пользовательский ввод от HTML для использования с Python и Selenium - PullRequest
1 голос
/ 01 мая 2020

У меня есть приложение python, которое использует PySimple GUI для ввода пользовательских данных (имя, дата и файл), навигации по веб-сайту и ввода данных на основе указанного ввода. Я хочу разместить эту программу на pythonanywhere, но так как gui не поддерживается, мне нужно найти другой способ получить ввод пользователя. Я создал HTML веб-форму, но не уверен, что делать дальше.

1) Будет ли работать request.get для получения имени, даты и файла?

2) Selenium не контролирует открытую веб-страницу, отправив форму HTML. Мне нужно явно вызвать браузер (открыть). Поскольку Selenium не привязан к открывающейся странице HTML, код выполняется перед отправкой веб-формы, и я получаю исключение тайм-аута. С ранее использованным GUI оставшийся код не будет выполняться до тех пор, пока после отправки (что идеально).

Я хочу либо:

  • использовать Selenium для управления сетью страница, открытая путем отправки формы HTML

ИЛИ

  • , не позволяет запустить мой код до отправки формы HTML. После отправки закройте форму и запустите код.

Есть мысли?

Ниже я включил файл HTML, код Python, который я пытаюсь приступить к работе, и соответствующая часть программы, используя PySimple GUI, которая работает как нужно.

<!DOCTYPE html>
<html>
<body>

<label for="opt_select">Select an Option:</label>
<select id="opt"
        name="opt_list">
  <option value="AA">AA</option>
  <option value="BB">BB</option>
  <option value="CC">CC</option>
</select>

</body>

<form action="/action_page.php">
  <label>Date:</label>
  <input type="date" id="sum_date" name="sum_start">
</form>
</body>
<form target="_blank" action="http://awebsite"
      method="post" id="submitted_form"
      name="submission" class="validate">
</form>
<form>
  <label for="myfile">Select a file:</label>
  <input type="file" id="myfile" name="myfile"><br><br>
  <input type="submit">
</form>
</html>
    import pandas as pd
    from datetime import datetime
    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.common.action_chains import ActionChains
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from flask import Flask, render_template, request

    app = Flask(__name__)

    @app.route('/hello', methods=['POST'])
    def hello():
        return render_template('gui.html')

    def user_data():
        data = request.GET['opt_list']

    browser = webdriver.Chrome()
    browser.get('https:/awebsite')
    type(browser)
    delay = 20

    if data == "AA":
        WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'AALanding')))
        browser.find_element_by_id('AALanding').click()
    if data == "BB":
        WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'BBLanding')))
        browser.find_element_by_id('BBLanding').click()
    if data == "CC":
        WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'CCLanding')))
        browser.find_element_by_id('CCLanding').click()

    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=3000)

import tkinter as tk
import time
import pandas as pd
import PySimpleGUI as sg
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

sg.theme('DARKTEAL')
layout = [[sg.Text('Select Student', key='-STUOUTPUT-', font=('Arial', 10))],
          [sg.Combo(['AA', 'BB', 'CC', 'DD'], size=(5, None), font=('Arial', 10),
                    key='-OPT-')],
          [sg.Text('Date to Start Summing', font=('Arial', 10), visible=True),
           sg.In(key='-CAL-', size=(12, None), default_text='MM/DD/YYYY')],
          [sg.CalendarButton('Calendar', key='-OUTPUT-', target='-CAL-', pad=None, size=(10, None), font=('Arial', 10),
                             format='%m/%d/%Y')],
          [sg.Text('Filename', key='-FOUTPUT-', font=('Arial', 10))],
          [sg.In(visible=False),
           sg.Input(key='-DIR-', size=(20, None)),
           sg.FileBrowse('Browse', target='-DIR-', font=('Arial', 10))],
          [sg.OK(font=('Arial', 10)), sg.Cancel(font=('Arial', 10))]]

window = sg.Window('Data Collector', layout, grab_anywhere=False, size=(400, 280), return_keyboard_events=True,
                   finalize=True)

event, values = window.read()
window['-STUOUTPUT-'](values['-STUIN-'])
window['-OUTPUT-'](values['-CAL-'])
window['-FOUTPUT-'](values['-DIR-'])
acedate = (values['-CAL-'])
opt = (values['-OPT-'])
file = (values['-DIR-'])
window.close()

browser = webdriver.Chrome()
browser.get('awebsite')
type(browser)

delay = 20

df = pd.read_excel(file, Sheet_name=0, header=None)

def bx_select():
    if data == "AA":
    WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'AALanding')))
    browser.find_element_by_id('AALanding').click()
if data == "BB":
    WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'BBLanding')))
    browser.find_element_by_id('BBLanding').click()
if data == "CC":
    WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'CCLanding')))
    browser.find_element_by_id('CCLanding').click()

def clear():
    ActionChains(browser) \
        .send_keys(Keys.CLEAR) \
        .perform()
def tab():
    ActionChains(browser) \
        .send_keys(Keys.TAB) \
        .perform()
def enter():
    ActionChains(browser) \
        .send_keys(Keys.ENTER) \
        .perform()
def page_up():
    ActionChains(browser) \
        .send_keys(Keys.CONTROL + Keys.HOME) \
        .perform()

bx_select()

clear()


def autosum():
    # length of bx measures
    x = len(df.columns)
    # used to determine when at end of row
    z = 1
    # location of column to start summing
    b = 1
    # number of days in the month
    c = len(df.index)
    # used to stop once last day of month reached
    y = 1
    # slices date chosen from calendar (dd) to determine where to start summing
    n = int(values['-CAL-'][3:5])
    # today's date (used to stop once current day is reached)
    d = datetime.today().strftime('%Y-%m-%d')

    while n < c:
        while z < x:
            m = df.iloc[n, b]
            z = z + 1
            b = b + 1
            if pd.isnull(m):
                tab()
                continue
            else:
                ActionChains(browser) \
                    .send_keys(str(m)) \
                    .perform()
            if z == x:
                n = n + 1
                y = y + 1
                z = 1
                b = 1
                enter()
                page_up()
                if n == c or str(pd.to_datetime(df.iloc[n, 0]).date()) == d:
                    return
                WebDriverWait(browser, delay).until(EC.visibility_of_element_located(
                    (By.CSS_SELECTOR,
                     'div.ZForm:nth-child(5) > div:nth-child(1) > div:nth-child(1) > h5:nth-child(1)')))
                bx_select()
                clear()
            else:
                tab()
                time.sleep(0.5)
autosum()

Ответы [ 2 ]

0 голосов
/ 10 мая 2020

Для ответа 1)

Вам нужно исправить файл HTML и поместить все поля ввода (те, которые вам нужны в process_form () ниже) в тот же тег <form action="...">, указывая на ваш Flask обработчик представления (см. Ниже). Например, если вы хотите обработать 'opt_list', вам нужно переместить его под тег <form>. Я также рекомендую использовать метод POST (вместо GET). Таким образом, структура gui. html должна выглядеть примерно так:

<!DOCTYPE html>
<html>
<body>
<form action="/process_url" method="post" enctype="multipart/form-data">
  <label for="opt_select">Select an Option:</label>
  <select id="opt"
        name="opt_list">
    <option value="AA">AA</option>
    <option value="BB">BB</option>
    <option value="CC">CC</option>
  </select>
  <br/>
  <label>Date:</label>
  <input type="date" id="sum_date" name="sum_start">
  <br/>
  <label for="myfile">Select a file:</label>
  <input type="file" id="myfile" name="myfile"><br><br>
  <input type="submit">
</form>
</html>

Чтобы ответить 2)

Вам необходимо переместить код Selenium в функцию, которая называется только когда ваша форма отправлена ​​(а не в теле кода с отступом).

from flask import Flask, render_template, request

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024


# This is the Flask handler to show your form
@app.route('/', methods=['GET'])
def hello():
    return render_template('gui.html')

# Add a Flask handler to process your form submission.
# (You can also use POST method instead of GET if you don't
# want your form content to show in the address bar)
@app.route('/process_url', methods=['POST'])  
def process_form():
    # Read form values
    opt = request.form['opt_list']
    sum_start = request.form['sum_start']
    myfile = request.files['myfile']
    file_content = myfile.stream.read().decode('utf-8', 'ignore')
    # Do Work
    my_work(opt, sum_start, file_content)
    # Return an HTML output of your results
    html = f"""
    
      
        Result page
        opt: {opt}
sum_start: {sum_start}
myfile.filename: {myfile.filename}
myfile.stream:
{file_content}
"" "return html def my_work (opt, sum_start, file_content): # TODO : Поместите здесь свой код Selenium, если __name__ == '__main__': app.run (host = '0.0.0.0', port = 3000, debug = True)

Кроме того, старайтесь избегать длинных время выполнения вашего кода Selenium для предотвращения тайм-аута браузера.

С этими рекомендациями, я надеюсь, вы сможете решить вашу проблему.

0 голосов
/ 10 мая 2020

Так что мне кажется, что этот вопрос больше касается Flask, чем селена или HTML. Кажется, вы хотите разрешить пользователю вводить данные в форму HTML и для этой формы вызывать некоторую функцию в вашем скрипте python. Вы можете сделать это не так уж сложно. Я считаю, что этот вопрос хорошо решает вашу проблему.

Как только ваша форма вызовет нужный сценарий, вы можете использовать входные данные этого метода, чтобы запустить селен и ввести его в свои данные. в нужном месте.

Это то, что вы ищете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...