Адаптировать алгоритм с интерфейсом, сделанным в Tkinter - PullRequest
0 голосов
/ 17 января 2020

Разработал этот очень простой алгоритм, который фильтрует ответы по поисковому запросу от Brainly.com site:

Алгоритм:

from bs4 import BeautifulSoup
import requests
import time


while True:

    buscar = input('\033[6;32;1mDigite o Termo de Buscar:\033[m ')
    print('Buscando Repostas ....')
    data = [{"operationName": "SearchQuery", "variables": {"query":buscar, "after": None, "first": 90},
         "query": "query SearchQuery($query: String!, $first: Int!, $after: ID) {\n  questionSearch(query: $query, first: $first, after: $after) {\n    count\n    edges {\n      node {\n        id\n        databaseId\n        author {\n          id\n          databaseId\n          isDeleted\n          nick\n          avatar {\n            thumbnailUrl\n            __typename\n          }\n          rank {\n            name\n            __typename\n          }\n          __typename\n        }\n        content\n        answers {\n          nodes {\n            thanksCount\n            ratesCount\n            rating\n            __typename\n          }\n          hasVerified\n          __typename\n        }\n        __typename\n      }\n      highlight {\n        contentFragments\n        __typename\n      }\n      __typename\n    }\n    __typename\n  }\n}\n"}]
    r = requests.post("https://brainly.com.br/graphql/pt", json=data).json()

    p=[]
    for item in r[0]['data']['questionSearch']['edges']:
        rst=(f"https://brainly.com.br/tarefa/{item['node']['databaseId']}")
        p.append(rst)


    for ele in p:
        r = requests.get(ele).text
        soup = BeautifulSoup(r,'html.parser')

        for n in soup.find_all('div', attrs={'class': 'brn-content-image'}):
            ty = (n.find('h1').text)
            print("\033[37;31;1m[Title]:\033[m {0}".format(ty))

            for t in soup.find_all('div', attrs={'class': 'sg-text js-answer-content brn-rich-content'}):
                u=(t.text)
                print("\033[6;33;1mResposta: \n \033[m{0}".format(u)) 

И для работы с этим алгоритмом Я сделал очень простой c интерфейс, созданный в Tkinter:

from tkinter import *
def resposta():
    b['text'] = '  Aguarde! , Procurando Respostas ....  '
    b['fg'] = 'green'
    b['bg'] = 'white'
    b['font'] = ('Verdana','9','bold')

i = Tk()

i.title('Respostas Brainly')

i.geometry('800x600')
t = Label(i, text = 'Buscador de Respostas Brainly : ',fg = 'red', font = ('Arial','13','bold'),padx=0, pady=10)
t.pack()
e = Entry(i)
b =Button(i, text = '   Clique   ',font = ('Verdana','10','bold'), fg = 'grey', command = resposta,bg = 'black')
e.pack()
'\n'
b.pack()
i.mainloop()

Но я сомневаюсь, что вы заставляете мой алгоритм взаимодействовать с интерфейсом:

Пример: я набираю какой-то запрос термин в поле, и он запускает алгоритм и печатает ответы на экране интерфейса Tkinter.

То же, что в консоли:

Ответы [ 2 ]

1 голос
/ 17 января 2020

Вы можете использовать Text виджет для хранения результатов поиска. Переместите логику поиска c в функцию resposta():

from tkinter import *
import requests
from threading import Thread
from bs4 import BeautifulSoup

def append_text(txt):
  result_log.insert(END, txt)
  result_log.see(END)

def resposta(buscar, max_results=10):
  data = [{
    "operationName": "SearchQuery",
    "variables": {
      "query": buscar,
      "after": None, 
      "first": 90
    },
    "query": """
      query SearchQuery($query: String!, $first: Int!, $after: ID) {
        questionSearch(query: $query, first: $first, after: $after) {
          count
          edges {
            node {
              id
              databaseId
              author {
                id
                databaseId
                isDeleted
                nick
                avatar {
                  thumbnailUrl
                  __typename
                }
                rank {
                  name
                  __typename
                }
                __typename
              }
              content
              answers {
                nodes {
                  thanksCount
                  ratesCount
                  rating
                  __typename
                }
                hasVerified
                __typename
              }
              __typename
            }
            highlight {
              contentFragments
              __typename
            }
            __typename
          }
          __typename
        }
      }
    """
  }]
  resp = requests.post('https://brainly.com.br/graphql/pt', json=data).json()
  cnt = 0
  for item in resp[0]['data']['questionSearch']['edges']:
    url = f"https://brainly.com.br/tarefa/{item['node']['databaseId']}"
    r = requests.get(url).content
    soup = BeautifulSoup(r, 'html.parser')
    for n in soup.find_all('div', attrs={'class': 'brn-content-image'}):
      ty = n.find('h1').text
      result.set(f'[Title #{cnt+1}]: {ty}\n')
      for t in soup.find_all('div', attrs={'class': 'sg-text js-answer-content brn-rich-content'}):
        result.set(f'[Resposta]: {t.text}\n')
    cnt += 1
    if cnt == max_results: break
  # thread task completed, reset thread ID
  global tid
  tid = None

def start_search():
  global tid
  # start a new thread if no thread task is running
  if tid is None:
    result_log.delete(1.0, END) # clear last result log
    tid = Thread(target=resposta, args=(e.get(),), daemon=1)
    tid.start()


tid = None   # hold the thread ID

root = Tk()
root.title('Respostas Brainly')
root.geometry('800x600')

# use for transfer result from running thread
result = StringVar()
result.trace('w', lambda *a: append_text(result.get()))

frm = Frame(root)
frm.pack(fill=X)

Label(frm, text='Buscador de Respostas Brainly:', fg='red', font=('Arial','13','bold'), padx=0, pady=10).pack(side=LEFT)

e = Entry(frm)
e.pack(side=LEFT)

Button(frm, text='Clique', font=('Verdana','10','bold'), fg='grey', command=start_search, bg='black').pack(side=LEFT)

frm = Frame(root)
frm.pack(fill=BOTH, expand=1)

# use a Text box to hold the search result
result_log = Text(frm)
result_log.pack(side=LEFT, fill=BOTH, expand=1)

sb = Scrollbar(frm, orient=VERTICAL, command=result_log.yview)
sb.pack(side=RIGHT, fill=Y)

result_log.config(yscrollcommand=sb.set)

root.mainloop()
1 голос
/ 17 января 2020

На самом деле логика c того, что вы хотите сделать, такая же, как в этом маленьком примере. В этом примере у меня есть GUI интерфейс, который просто запускает al oop. В нижней части GUI есть запись, ограниченная локальным словарем. Когда пользователь вводит слово и нажимает кнопку поиска, если слово найдено, он возвращает результат (в этом примере единственными ключевыми словами, которые возвращают результат, является workd: 'keyword'). L oop помещается в Thread с использованием модуля threading для асинхронного запуска и не блокирует основной tkinter l oop,.

В вашем случае вместо кнопки остановки, если я для правильного понимания вам нужна только запись (чтобы пользователь мог ввести ключевые слова для исследования) и кнопку запуска, чтобы начать просмотр website, функция, которая очищает сайт, должна быть в Thread, потому что она использует бесконечное число l oop, что в противном случае блокировало бы tkinter l oop и поэтому GUI

import tkinter as tk
import threading as th
import time



class App:

    def __init__(self):
        self.root = tk.Tk()

        self.run = True
        self.search_dict = {'keyword': 'keyword value'}
        self.counter = 0

    def build(self):
        self.counter_label = tk.Label(text=self.counter)
        self.counter_label.pack()



        self.keyword_variable = tk.StringVar()
        self.entry = tk.Entry(textvariable=self.keyword_variable)
        self.entry.pack()

        self.search_button = tk.Button(text='search', command=self.run_counter)
        self.search_button.pack()

        self.stop_button = tk.Button(text='stop', command=self.stop_counter)
        self.stop_button.pack()

    def start_counter(self):
        while self.run:
            current__keyword = self.keyword_variable.get().strip()
            if current__keyword in self.search_dict:
                result = self.search_dict[current__keyword]
            else:
                result = 'Keyword is empy or not in the dictionary'
            self.counter += 1
            self.counter_label.configure(text='Keyword found: ' + result + ', Search process number: ' + str(self.counter))
            time.sleep(1)

    def run_counter(self):
        self.my_thread = th.Thread(target=self.start_counter) # create new thread that runs the self.start_counter() function
        self.my_thread.start() # start the threading

    def stop_counter(self):
        self.counter_label.configure(text="counter stopped")
        self.run = False # set the variable to false so that the while loop inside the threading stops
        self.my_thread.join() # this destoy the created threading

    def start_loop(self):
        self.root.mainloop() # starts the tkinter mainloop

app = App()
app.build()

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