CoderCastrov logo
CoderCastrov
Парсер

Парсинг онлайн-газеты и отображение горячих тем в виде облака слов - Python

Парсинг онлайн-газеты и отображение горячих тем в виде облака слов - Python
просмотров
3 мин чтение
#Парсер

I. Парсинг

Мы будем получать данные с выбранной нами онлайн-газеты. В качестве примера я использовал USA Today. (https://eu.usatoday.com/)

Сначала установите несколько библиотек: nltk, wordcloud, matplotib, requests, bs4, numpy и Pillow. Вы можете выполнить следующую команду в терминале (замените 'библиотека'):

pip install библиотека

Затем мы импортируем библиотеку requests для выполнения HTTP-запроса к веб-странице, которую мы хотим спарсить, а затем библиотеку BeautifulSoup для анализа содержимого этой веб-страницы и извлечения соответствующей информации.

import requests
from bs4 import BeautifulSoup

url = "https://eu.usatoday.com/"
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html')

Теперь у нас есть "суп", то есть синтаксическое дерево со всей видимой информацией веб-страницы. Давайте посмотрим на нашу веб-страницу (нажмите fn F12, чтобы увидеть структуру веб-страницы, как показано справа).

Мы видим, что заголовок содержится в теге div с классом "display-6 p13-title".

Если мы ищем этот элемент в нашем супе, мы находим только два заголовка:

soup.find_all("div", {"class": "display-6 p13-title"})

Итак, мы собираемся искать элементы, содержащиеся в тегах типа "div", но на этот раз мы собираемся искать классы, содержащие слово "title", чтобы расширить наш поиск.

for EachPart in soup.select('div[class*="title"]'):
    print(EachPart.get_text())

Это гораздо лучше.

Мы видим, что есть дубликаты, но нам нужен список всех заголовков без дубликатов, потому что при создании облака слов частота появления каждого слова будет влиять на его размер. Мы собираемся сначала собрать все заголовки в список, а затем обработать этот список, чтобы удалить дубликаты.

II. Обработка и отображение данных в виде облака слов

Сначала соберите все заголовки в список:

L_titles = []
for EachPart in soup.select('div[class*="title"]'):
    L_titles.append(EachPart.get_text())

Удалите дубликаты:

L_titles = list(set(L_titles))
print(L_titles)

Можно заметить, что осталось несколько дубликатов, но они не являются точными дубликатами, потому что в некоторых заголовках есть дополнительное слово в конце.

def is_duplicate(L_titles):
    for el in L_titles:
        S = 0
        # Мы сравниваем половину заголовка с другими половинами заголовков, чтобы определить, является ли он дубликатом
        for title in L_titles:
            min_len = min(len(el), len(title))
            if el[:min_len//2] == title[:min_len//2]:
                S+=1
        if S==2: # Элемент присутствует 2 раза в списке
            L_titles.remove(el)
    return L_titles

L_titles = is_duplicate(L_titles)

Теперь у нас есть чистый список. Но слова вроде "I" или "so" не будут полезны для представления текущих тем, поэтому мы их удалим. Эти слова называются "стоп-словами":

import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
print(stopwords.words('russian'))

Удалим стоп-слова из наших заголовков и объединим их в одно большое предложение.

all_titles = ""
for title in L_titles:
    title_to_add = ' '.join([word for word in title.split() if word not in stopwords.words("russian")])
    all_titles += " " + title_to_add
    
print(all_titles)

Теперь перейдем к представлению облака слов:

import numpy as np
from PIL import Image
from wordcloud import WordCloud, ImageColorGenerator
import matplotlib.pyplot as plt

wordcloud = WordCloud().generate(all_titles)
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
Word Cloud

Появляются такие темы, как "Рождество", "COVID", "Праздник" и "Омикрон".

А теперь возьмите изображение по вашему выбору с цветной формой и белым фоном, например, такое:

Mask Image

Мы будем использовать это изображение для создания "маски": слова будут заполнять пространство цветной области и будут иметь такой же цвет.

mask = np.array(Image.open("путь_к_вашему_изображению.jpg"))
wordcloud = WordCloud(background_color="white", max_words=10000, mask=mask).generate(all_titles)
colors_from_image = ImageColorGenerator(mask)
plt.figure(figsize=[10,10])
plt.imshow(wordcloud.recolor(color_func=colors_from_image))
plt.axis("off")
plt.savefig("HotTopics.png", format="png")
plt.show()
Word Cloud with Mask

Et Voilà!