Exemplo de multithreading em Python – 03

Resumo : neste tutorial, você aprenderá como usar o módulo de threading Python para desenvolver um programa multithread.

Estendendo a classe Thread

Desenvolveremos um programa multithread que extrai os preços das ações do site do Yahoo Finance .

Para fazer isso, usaremos dois pacotes de terceiros:

  • requests– para obter o conteúdo de uma página da web.
  • lxml– para selecionar um elemento específico de um documento HTML.

Primeiro, instale os módulos requestse lxmlusando o comando pip :

pip install request lxmlLinguagem de código:  Python  ( python )

A seguir, defina uma nova classe chamada Stockque herda da Threadclasse do threadingmódulo. Colocaremos a classe Stock no stock.pymódulo:

import threading

class Stock(threading.Thread):
   passLinguagem de código:  Python  ( python )

Em seguida, implemente o __init__()método que aceita um símbolo e inicializa a urlvariável de instância com base no símbolo:

import threading
import requests
from lxml import html


class Stock(threading.Thread):
    def __init__(self, symbol: str) -> None:
        super().__init__()

        self.symbol = symbol
        self.url = f'https://finance.yahoo.com/quote/{symbol}'
        self.price = NoneLinguagem de código:  Python  ( python )

Por exemplo, se você passar o símbolo GOOGpara o __init__()método, a URL será:

https://finance.yahoo.com/quote/GOOGLinguagem de código:  Python  ( python )

Depois disso, substitua o run()método da Threadclasse. O run()método obtém o conteúdo de self.urle obtém o preço da ação:

class Stock(threading.Thread):
    def __init__(self, symbol: str) -> None:
        super().__init__()

        self.symbol = symbol
        self.url = f'https://finance.yahoo.com/quote/{symbol}'
        self.price = None

    def run(self):
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
        }
        response = requests.get(self.url, headers=headers)
        if response.status_code == 200:
            # parse the HTML
            tree = html.fromstring(response.text)
            # get the price in text
            price_text = tree.xpath(
                '//*[@id="quote-header-info"]/div[3]/div[1]/div[1]/fin-streamer[1]/text()')
            if price_text:
                try:
                    self.price = float(price_text[0].replace(',', ''))
                except ValueError:
                    self.price = None

    def __str__(self):
        return f'{self.symbol}\t{self.price}'Linguagem de código:  Python  ( python )

Como funciona.

Faça uma solicitação ao URL usando o requests.get()método:

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
response = requests.get(self.url, headers=headers)Linguagem de código:  Python  ( python )

Observe que sem cabeçalhos válidos, o Yahoo retornará 404 em vez de 200.

Se a solicitação for bem-sucedida, o código de status HTTP será 200. Nesse caso, obtemos o conteúdo HTML da resposta e o passamos para a fromstring()função do htmlmódulo do lxmlpacote:

if response.status_code == 200:
   tree = html.fromstring(response.text)Linguagem de código:  Python  ( python )

Cada elemento de uma página da web pode ser selecionado usando algo chamado XPath.

Para obter o XPath de um elemento usando o Google Chrome, inspecione a página, clique com o botão direito no elemento, selecione copiar e Copiar XPath.

O XPath do preço das ações no momento da redação deste tutorial é o seguinte:

//*[@id="quote-header-info"]/div[3]/div[1]/div[1]/fin-streamer[1]Linguagem de código:  Python  ( python )

Para obter o texto do elemento, anexe no text()final do XPath:

//*[@id="quote-header-info"]/div[3]/div[1]/div[1]/fin-streamer[1]/text()Linguagem de código:  Python  ( python )

Observe que se o Yahoo alterar a estrutura da página, você precisará alterar o XPath de acordo. Caso contrário, o programa não funcionará conforme esperado:

price_text = tree.xpath('//*[@id="quote-header-info"]/div[3]/div[1]/div[1]/fin-streamer[1]/text()')Linguagem de código:  Python  ( python )

Depois de obter o preço como texto, removemos a vírgula e o convertemos em um número:

if price_text:
    try:
        self.price = float(price_text[0].replace(',', ''))
    except ValueError:
        self.price = NoneLinguagem de código:  Python  ( python )

Por fim, adicione o __str__()método que retorna a representação em string do objeto Stock:

import threading
import requests
from lxml import html


class Stock(threading.Thread):
    def __init__(self, symbol: str) -> None:
        super().__init__()

        self.symbol = symbol
        self.url = f'https://finance.yahoo.com/quote/{symbol}'
        self.price = None

    def run(self):
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
        }
        response = requests.get(self.url, headers=headers)
        if response.status_code == 200:
            # parse the HTML
            tree = html.fromstring(response.text)
            # get the price in text
            price_text = tree.xpath(
                '//*[@id="quote-header-info"]/div[3]/div[1]/div[1]/fin-streamer[1]/text()')
            if price_text:
                try:
                    self.price = float(price_text[0].replace(',', ''))
                except ValueError:
                    self.price = None

    def __str__(self):
        return f'{self.symbol}\t{self.price}'
Linguagem de código:  Python  ( python )

Usando a classe Estoque

O main.pymódulo a seguir usa a Stockclasse do stock.pymódulo:

from stock import Stock

symbols = ['MSFT', 'GOOGL', 'AAPL', 'META']
threads = []

for symbol in symbols:
    t = Stock(symbol)
    threads.append(t)    
    t.start()
    

for t in threads:
    t.join()
    print(t)
Linguagem de código:  Python  ( python )

Saída:

MSFT    253.67
GOOGL   2280.41
AAPL    145.86
META    163.27Linguagem de código:  Python  ( python )

Como funciona.

Primeiro, importe a Stockclasse do stock.pymódulo:

from stock import StockLinguagem de código:  Python  ( python )

Segundo, inicialize uma lista de símbolos:

symbols = ['MSFT', 'GOOGL', 'AAPL', 'META']Linguagem de código:  Python  ( python )

Terceiro, crie um thread para cada símbolo, inicie-o e anexe o thread à lista de threads:

threads = []
for symbol in symbols:
    t = Stock(symbol)
    threads.append(t)    
    t.start()
    Linguagem de código:  Python  ( python )

Por fim, aguarde a conclusão de todos os threads da lista de threads e imprima o preço das ações:

for t in threads:
    t.join()
    print(t)Linguagem de código:  Python  ( python )

Resumo

  • Defina uma classe que herde da threading.Threadclasse e substitua o run()método.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *