Извлечение определенных совпадений строк со страницы стандартного веб-сайта

#python #html #beautifulsoup

#python #HTML #beautifulsoup

Вопрос:

Я пытаюсь использовать ограничения фондового рынка webscrape, используя приведенный ниже код. Сначала я традиционно пытался получить список market cap values использования bs4. Когда я print(x.find('span',{'class': 'Trsdu(0.3s)'}).text) делал это, я получал AttributeError: 'NoneType' object has no attribute 'text' ошибку.

   for x in marketCapArray:
        print(x.find('span',{'class': 'Trsdu(0.3s)'}).text)
  

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

Основной код

 import bs4
import re
import requests
from bs4 import BeautifulSoup
from urllib.request import urlopen

def pickTopGainers():
  url =  'https://in.finance.yahoo.com/gainers?offset=0amp;count=100'
  page = urlopen(url)
  soup = bs4.BeautifulSoup(page,"html.parser")
  marketCapArray = soup.find_all('td', {'class': 'Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)',
 'aria-label': 'Market cap'})
  print(str(marketCapArray))
  xi = re.findall("........</span>", str(marketCapArray)) # regex-use-1
  pi = re.sub("(</span>|....>N/A|>|")","", str(xi))
  print(pi)

pickTopGainers()
  

Результаты

Это то, что print(str(marketCapArray) будет выводиться. (вставлена только некоторая часть)

 [<td aria-label="Market cap" class="Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)" colspan="" data-reactid="93"><span class="Trsdu(0.3s)" data-reactid="94">159.404M</span></td>, 
<td aria-label="Market cap" class="Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)" colspan="" data-reactid="119"><span class="Trsdu(0.3s)" data-reactid="120">533.97M</span></td>, 
<td aria-label="Market cap" class="Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)" colspan="" data-reactid="145"><span data-reactid="146">N/A</span></td>, 
<td aria-label="Market cap" class="Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)" colspan="" data-reactid="171"><span class="Trsdu(0.3s)" data-reactid="172">2.952B</span></td>, 
<td aria-label="Market cap" class="Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)" colspan="" data-reactid="197"><span class="Trsdu(0.3s)" data-reactid="198">9.223B</span></td>, 
<td aria-label="Market cap" class="Va(m) Ta(end) Pstart(20px) Pend(10px) W(120px) Fz(s)" colspan="" data-reactid="223"><span data-reactid="224">N/A</span></td>]
  

Это результат print(pi) . Также конечный результат.

 ['159.404M', '533.97M', '', '2.952B', '9.223B', '']

  

Вопрос

Как я могу избежать использования замены регулярных выражений (re.sub) в приведенном выше Main Code для достижения заданного конечного результата pi ? или предложите мне правильный подход для этого. Я чувствую, что мое регулярное выражение неприятно.

Ответ №1:

Вы можете перебирать строку за строкой внутри <table> , где хранится вся информация. Например:

 import requests
from bs4 import BeautifulSoup


url = 'https://in.finance.yahoo.com/gainers?offset=0amp;count=100'

soup = BeautifulSoup(requests.get(url).content, 'html.parser')

fmt_string = '{:<15} {:<60} {:<10} {:<10} {:<10} {:<10} {:<10} {:<10} {:<10}'
print(fmt_string.format('Symbol', 'Name', 'Price(int)', 'Change', '% change', 'Volume', 'AvgVol(3M)', 'Market Cap', 'PE ratio'))
for row in soup.select('table:has(a[href*="/quote/"]) > tbody > tr'):
    cells = [td.get_text(strip=True) for td in row.select('td')]
    print(fmt_string.format(*cells[:-1]))
  

С принтами:

 Symbol          Name                                                         Price(int) Change     % change   Volume     AvgVol(3M) Market Cap PE ratio  
CCCL.NS         Consolidated Construction Consortium Limited                 0.2000      0.0500     33.33%    57,902     290,154    159.404M   N/A       
KSERASERA.NS    KSS Limited                                                  0.2500      0.0500     25.00%    1.607M     2.601M     533.97M    N/A       
BONLON.BO       BONLON INDUSTRIES LIMITED                                    21.60       3.60       20.00%    16,000     N/A        N/A        N/A       
MENONBE.NS      Menon Bearings Limited                                       52.80       8.80       20.00%    2.334M     65,713     2.952B     25.05     
RPOWER.NS       Reliance Power Limited                                       3.3000      0.5500     20.00%    127.814M   18.439M    9.223B     N/A       
11DPD.BO        Nippon India Mutual Fund                                     0.0600      0.0100     20.00%    190        N/A        N/A        N/A       
ABFRLPP-E1.NS   Aditya Birla Rs.5 ppd up                                     105.65      17.60      19.99%    1.238M     N/A        N/A        N/A       
500110.BO       Chennai Petroleum Corporation Limited                        64.55      -0.15      -0.23%     42,765     61,584     9.612B     N/A       
ABFRLPP.BO      Aditya Birla Fashion and Retai                               106.05      17.65      19.97%    387,703    N/A        N/A        N/A       
RADIOCITY.NS    Music Broadcast Limited                                      21.35       3.55       19.94%    12.657M    1.013M     7.38B      124.13    
RADIOCITY.BO    Music Broadcast Limited                                      21.35       3.55       19.94%    898,070    90,236     7.38B      124.13    
MENONBE.BO      Menon Bearings Limited                                       52.65       8.75       19.93%    137,065    8,648      2.951B     24.98     
MTNL.BO         Mahanagar Telephone Nigam Limited                            10.72       1.78       19.91%    1.142M     156,275    6.754B     N/A       

...and so on.
  

Комментарии:

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

2. @Thinker-101 Вы можете сделать, например print( cells[7] ) , для печати только рыночной капитализации. Вы можете сохранить его внутри списка, например, и т.д..