Search code examples
pythonweb-scrapingkivy

App in python together with BeautifulSoup


my goal is to create a simple App based calculator -which converts from one currency to another but thing is that conversion rate should be automatically retrieved from website. for this purpose i decided to use kivy library.based on the following example : kivy calculator i have managed to change some little part and got the following code and result :

here is code of .py file and .kv file

`import kivy

# base Class of your App inherits from the App class.
# app:always refers to the instance of your application
from kivy.app import App

# this restrict the kivy version i.e
# below this kivy version you cannot
# use the app or software
kivy.require('1.9.0')

# for making multiple buttons to arranging
# them we are using this
from kivy.uix.gridlayout import GridLayout

# for the size of window
from kivy.config import Config

# Setting size to resizable
Config.set('graphics', 'resizable', 1)


## Config.set('graphics', 'width', '400')
## Config.set('graphics', 'height', '400')


# Creating Layout class
class CalcGridLayout(GridLayout):

    # Function called when equals is pressed
    def calculate(self, calculation):
        if calculation:
            try:
                # Solve formula and display it in entry
                # which is pointed at by display
                self.display.text = str(eval(calculation))
            except Exception:
                self.display.text = "Error"


# Creating App class
class CalculatorApp(App):

    def build(self):
        return CalcGridLayout()


# creating object and running it
calcApp = CalculatorApp()
calcApp.run()`

and corresponding .kv file

<CustButton@Button>:
    font_size: 32

# Define id so I can refer to the CalcGridLayout
# class functions
# Display points to the entry widget

``<CalcGridLayout>:
    id: calculator
    display: entry
    rows: 6
    padding: 10
    spacing: 10



    # Where input is displayed
    BoxLayout:
        TextInput:
            id: entry
            font_size: 32
            multiline: False

    # When buttons are pressed update the entry
    BoxLayout:
        spacing: 10
        CustButton:
            text: "7"
            on_press: entry.text += self.text
        CustButton:
            text: "8"
            on_press: entry.text += self.text
        CustButton:
            text: "9"
            on_press: entry.text += self.text
        CustButton:
            text: "$"
            on_press: entry.text =entry.text+'/'+ str(2.54)

    BoxLayout:
        spacing: 10
        CustButton:
            text: "4"
            on_press: entry.text += self.text
        CustButton:
            text: "5"
            on_press: entry.text += self.text
        CustButton:
            text: "6"
            on_press: entry.text += self.text
        CustButton:
            text: "yen"
            on_press: entry.text =entry.text+'*'+ str(54.21)

    BoxLayout:
        spacing: 10
        CustButton:
            text: "1"
            on_press: entry.text += self.text
        CustButton:
            text: "2"
            on_press: entry.text += self.text
        CustButton:
            text: "3"
            on_press: entry.text += self.text
        CustButton:
            text: "euro"
            on_press: entry.text =entry.text+'/'+ str(2.8070)

    # When equals is pressed pass text in the entry
    # to the calculate function
    BoxLayout:
        spacing: 10
        CustButton:
            text: "AC"
            on_press: entry.text = ""
        CustButton:
            text: "0"
            on_press: entry.text += self.text
        CustButton:
            text: "="
            on_press: calculator.calculate(entry.text)
        CustButton:
            text: "GBP"
            on_press: entry.text =entry.text+'/'+ str(3.1790)
    BoxLayout:
        CustButton:
            font_size: 20
            text: "Scientific calculator"
            on_press: entry.text = ""

`

when i am running .py file, i am getting this result : result of my code

but thing is that if we look at code : text: "GBP" on_press: entry.text =entry.text+'/'+ str(3.1790) GBP is static, if i want to use beautifull soup to get this data from web, how to combine result to our class? please give me a hint

Edited: as there was unclear comments about previous question that it is unclear what i am asking, i will repeate question : look on the code below :

 text: "GBP"
            on_press: entry.text =entry.text+'/'+ str(3.1790)

instead of writting exchange rate directly, how can i read it from website and include in kivy , what is unclear here? look for instance following link : Exchange rates

can you see information about GBP? how to get this and include in kivy? i know that i can get it through beuatifulsoup, but how include in kivy, is it clear now?


Solution

  • You can use a DictProperty instance variable in your CalcGridLayout class to store exchange rates after scraping and use that in the .kv file. The exchange rates are updated every minute on a separate thread in background.

    def get_exchange_rates():
      # code where you scrape using beautifulsoup and return a dict of 
      # exchange rates
      return {}
    
    
    class CalcGridLayout(GridLayout):
      exchange_rates = DictProperty(get_exchange_rates())
    
      def _update_exchange_rates(self):
        while True:
          self.exchange_rates = DictProperty(get_exchange_rates())
          time.sleep(60). # update every minute
    
      # Function called when equals is pressed
      def calculate(self, calculation):
        if calculation:
          try:
            # Solve formula and display it in entry
            # which is pointed at by display
            self.display.text = str(eval(calculation))
          except Exception:
            self.display.text = "Error"
    
    
    class CalculatorApp(App):
      def build(self):
        layout = CalcGridLayout()
        update_thread = threading.Thread(target=layout._update_exchange_rates)
        update_thread.daemon = True
        update_thread.start()
        return layout
    

    Use exchange_rates in your .kv file like this:

    CustButton:
      text: "GBP"
      on_press: entry.text = entry.text + '/' + str(calculator.exchange_rates['GBP'])