Проблема при построении графика

#python #matplotlib #graph #beautifulsoup

#python #matplotlib #График #beautifulsoup

Вопрос:

Я пытался провести анализ новостных сайтов, в ходе которого сравнивалось, сколько статей о covid было написано на каждом сайте. Мне удалось успешно извлечь названия статей на новостных сайтах, а также выполнить поиск по словам, который показывает, сколько из всех извлеченных статей содержали слово «COVID». Теперь я хочу представить результат поиска по слову в виде гистограммы, я использовал matplotlib, но я получаю сообщение об ошибке, которое я не могу понять. Пожалуйста, помогите.

Ниже приведен код (последняя часть кода посвящена графику, на котором я получаю сообщение об ошибке).:

 from bs4 import BeautifulSoup
from bs4.dammit import EncodingDetector
from newspaper import Article
import requests
import matplotlib.pyplot as plt 
URL=["https://www.timesnownews.com/coronavirus","https://www.indiatoday.in/coronavirus"]
Url_count = []
for url in URL:
    parser = 'html.parser'  
    resp = requests.get(url)
    http_encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
    html_encoding = EncodingDetector.find_declared_encoding(resp.content, is_html=True)
    encoding = html_encoding or http_encoding
    soup = BeautifulSoup(resp.content, parser, from_encoding=encoding)
    
    links = []
    for link in soup.find_all('a', href=True):
        if "javascript" in link["href"]:
            continue
        links.append(link['href'])
            
    count = 0
     
            
    for link in links:
        try:
            article = Article(link)
            article.download()
            article.parse()
            print(article.title)
            if "COVID" in article.title or "coronavirus" in article.title or "Coronavirus"in article.title or "Covid-19" in article.title or "COVID-19" in article.title :
                    count  = 1
    
        except:
            pass
    Url_count.append(count)
    
for url, count in zip(URL, Url_count):
    print("Site:", url, "Count:", count)
    # x-coordinates of left sides of bars  
    left = [URL]
    # heights of bars 
    height=[Url_count]
    # labels for bars 
    tick_label=['timesnow', 'India today']
    # plotting a bar chart 
    plt.bar(left, height, tick_label = tick_label, 
        width = 0.8, color = ['red', 'green']) 
    # naming the x-axis 
    plt.xlabel('News websites') 
    # naming the y-axis 
    plt.ylabel('Number of articles') 
    # plot title 
    plt.title('Media analysis') 
  
    # function to show the plot 
    plt.show() 
 

Ниже приведена ошибка:

 --------------------------------------------------------------------------
UFuncTypeError                            Traceback (most recent call last)
~anaconda3libsite-packagesmatplotlibaxes_axes.py in bar(self, x, height, width, bottom, align, **kwargs)
   2369                 try:
-> 2370                     left = x - width / 2
   2371                 except TypeError as e:

UFuncTypeError: ufunc 'subtract' did not contain a loop with signature matching types (dtype('<U40'), dtype('<U40')) -> dtype('<U40')

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
<ipython-input-1-59393af79dcd> in <module>
     45     tick_label=['timesnow', 'India today']
     46     # plotting a bar chart
---> 47     plt.bar(left, height, tick_label = tick_label, 
     48         width = 0.8, color = ['red', 'green']) 
     49     # naming the x-axis

~anaconda3libsite-packagesmatplotlibpyplot.py in bar(x, height, width, bottom, align, data, **kwargs)
   2405         x, height, width=0.8, bottom=None, *, align='center',
   2406         data=None, **kwargs):
-> 2407     return gca().bar(
   2408         x, height, width=width, bottom=bottom, align=align,
   2409         **({"data": data} if data is not None else {}), **kwargs)

~anaconda3libsite-packagesmatplotlib__init__.py in inner(ax, data, *args, **kwargs)
   1563     def inner(ax, *args, data=None, **kwargs):
   1564         if data is None:
-> 1565             return func(ax, *map(sanitize_sequence, args), **kwargs)
   1566 
   1567         bound = new_sig.bind(ax, *args, **kwargs)

~anaconda3libsite-packagesmatplotlibaxes_axes.py in bar(self, x, height, width, bottom, align, **kwargs)
   2370                     left = x - width / 2
   2371                 except TypeError as e:
-> 2372                     raise TypeError(f'the dtypes of parameters x ({x.dtype}) '
   2373                                     f'and width ({width.dtype}) '
   2374                                     f'are incompatible') from e

TypeError: the dtypes of parameters x (<U40) and width (float64) are incompatible
 

Ответ №1:

Способ, которым вы используете гистограмму, неверен. Вам не нужен цикл for для построения нескольких столбцов. вы можете указать plt.bar(x, y) x и y, где x — список координат стержней, а y — список высот. Я рекомендую вам ознакомиться с документацией по гистограмме

Что было бы неплохо, особенно если вы собираетесь сделать это для многих веб-сайтов, так это создать список из списка URL-адресов, содержащий только название веб-сайта, поэтому удалите «www.» и «.com /….», поэтому вам нужно только предоставить вашей программе списокurl-адреса, и он сделает эту работу за вас.

Чтобы решить вашу проблему, замените последний цикл for следующим кодом:

 import numpy as np 

# make an array for the x-axis from the URL List 
nx = np.arange(len(URL)) 

labels = ['timessnownews', 'indiatoday']

fig = plt.figure()
ax = fig.gca()
ax.set_title('Media analysis')
ax.bar(nx, Url_count)
ax.set_xticks(nx)
ax.set_xticklabels(labels)
ax.set_ylabel('Number of articles')
ax.set_xlabel('News Websites')
 

Ответ №2:

left Параметр должен представлять собой массив значений по оси x. Вы передаете список строк. И я не совсем понимаю, почему вы делаете это в цикле, когда каждый раз строите весь набор.

Кроме того, height должен быть список высот планки, но вы делаете это списком списка. Помните, Url_count это уже целый список.