#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
это уже целый список.