Для создания базы сначала разберёмся - что это такое? База данных – совокупность данных, хранящихся и упорядоченных в соответствии с определённой структурой. Структура, в свою очередь, определяет то, каким образом данные будут располагаться и как к ним будет предоставляться доступ. Проще говоря — обычная таблица с возможностью настройки условий на столбцы.
Для создания пустой базы я использовал команду CREATE TABLE. Таблица должна будет содержать информацию об аккаунтах пользователей. Столбцы будут содержать соответствующую информацию: идентификатор, имя, местоположение, описание, количество подписчиков, количество друзей, списки, дата создания, количество подписок, количество статусов, почта, телефон, ссылка на сайт аккаунта.
CREATE TABLE "accounts" (
"twitter_id" TEXT,
"name" TEXT,
"location" TEXT,
"description" TEXT,
"followers" INTEGER,
"friends" INTEGER,
"listed" INTEGER,
"created_at" TEXT,
"favourites" INTEGER,
"statuses" INTEGER,
"email" TEXT,
"phone" TEXT,
"url" TEXT
);
Файл, найденный в интернете, имеет расширение json, т.е текстовый формат обмена данными, основанный на JavaScript. Файл был плохо структурирован, что мешало анализировать данные. Для выхода из этой ситуации создадим базу данных в удобном для анализа расширении db (data base) и наполним её данными из найденного файла, параллельно структурируя. Всё это происходит с помощью системы управления базой данных (СУБД), она позволяет создавать, удалять, изменять и делать любые манипуляции с данными базы. Для отправления запросов в СУБД будет использоваться отдельный язык - SQL, язык запросов, предоставляющий возможность манипулировать информацией в базе данных.
Первые строки json файла. (Рис. 1)
Подключившись к пустой базе открываем найденный файл в оперативной памяти и начинаем перенос в ранее открытое хранилище, но продлевается данный процесс не долго, файл, выгруженный в память, весит так много, что занимает все ресурсы системы и тормозит весь компьютер вплоть до системной остановки процесса или отключения компьютера. Для избежания данной проблемы выгружаем только одну строку исходного файла, достаём из неё нужные данные, сохраняем в нашу базу и освобождаем память для нового цикла, пока не будут перенесены все строки найденного в интернете файла.
with open(r'D:\projects\base\twitter.json') as tw_file:
tw_str = 1
while tw_str:
tw = json.loads(tw_str)
tw_str = tw_file.readline()
В процессе заполнения новой базы оказалось, что в исходном файле иногда столбцы с email отсутствовали, а вместо них был столбец с номером телефона. Выходом стала обычная проверка на наличие или отсутствие того или иного столбца перед отправлением запроса. Также находились строки, заполненные иероглифами в несколько десятков символов. Данных строк было четыре из пяти миллионов, так что самым простым решением был их пропуск.
Арабские символы были представлены на кодировке Unicode, включающей в себя знаки почти всех письменных языков мира. (Рис. 2)
Итак, у меня есть систематизированная база данных, как теперь на достать из неё информацию? Изначально я хотел отправлять запросы в нашу базу построчно, но ещё немного изучив виды запросов SQL нашёл функцию, позволяющую делать запрос на поиск по всей базе, при том, что он не станет сильно использовать ресурсы компьютера. Поиск производился только по одному столбцу, который содержит в себе полную дату регистрации пользователя, и считает только те строки, которые содержали нужный год, день недели или час дня. Теперь я мог одним запросом найти количество пользователей в нужную мне дату.
query = 'SELECT count() FROM accounts WHERE created_at LIKE "%' + year + '%"'
Чтобы получить ещё больше информации логичнее всего было рассматривать нужный нам промежуток и строить график по частоте регистраций. Простым способом будет сделать цикл, перебирающий выбранные года, дни недели или время суток, и отправляющий по одному запросу. Теперь мы просто сохраняем ответы и строим по ним график с помощью библиотеки matplotlib, она требует на вход данные точек и названия осей.
def tw_years(years):
year_creating = []
for i in range(len(years)):
year = years[i]
creats = tw_year(year) / 5500000 * 100
year_creating.append(creats)
plot(x=years, y=year_creating, name='year')
def plot(x, y, name):
if name == 'year':
plt.plot(x, y, color='green', marker='o', linestyle='solid')
plt.title('')
plt.xlabel('год')
plt.ylabel('создано аккаунтов в процентах')
plt.show()
Первым делом нужно узнать количество аккаунтов в выбранных странах. Удобнее всего это реализовать через гистограмму, где столбцы - страны, а их высота - количество регистраций. Для этого производим поиск по столбцу местоположения регистрации для каждого региона, сортируем по количесту регистраций и с помощью библиотеки matplotlib строим столбчатый график.
for r in regions_accounts:
query = 'SELECT count() FROM accounts WHERE location LIKE "%' + r + '%"'
cur.execute(query)
data = cur.fetchone()[0]
regions_accounts[r] = data // 1000
index = sorted_regions_accounts.keys()
values = sorted_regions_accounts.values()
plt.bar(index, values)
plt.ylabel('создано аккаунтов тысяч')
plt.show()
Запросы на количество регистраций за нужные время суток и года у нас есть, остаётся только добавить условие на выборку регионов. Добавляем в запрос новое условие на проверку региона с помощью логической операции AND
и сохраняем полученную информацию. Далее строим на одной координатной плоскости графики регистраций по странам и выводим на экран.
query = 'SELECT count() FROM accounts WHERE created_at LIKE "%' + year + '%" ' \
'AND location LIKE "%' + reg + '%"'
plt.plot(years, years_creats, color=colors[regions.index(reg)], marker='o', linestyle='solid',
label=norm_regions[regions.index(reg)])
plt.locator_params(axis='x', nbins=len(years) + 5)
plt.title('')
plt.xlabel('год')
plt.ylabel('создано аккаунтов в процентах')
plt.legend()
plt.show()
Наша программа успешно выполняет свою работу, но для её использования нам требуется изменять файл либо использовать отдельно файлы для нужной функции. Также требуется запуск файла из специальной среды. Для облегчения данного процесса нужно реализовать простой и удобный способ отправки запросов с возможностью выбора функции. В этом мне помогла библиотека argparse, представляющая из себя набор функций для принятия запросов из командной строки консоли.
Пример запроса из командной строки. (Рис. 3)
Идея заключается в том, чтобы одной строкой в консоли можно было получить нужный нам график. Для её реализации с помощью библиотеки argparse принимаем введенный в консоль текст и прогоняем через условия, выбирая нужную функцию, которая будет доставать данные из базы и выводить график.
def create_parser():
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--function', choices=['year', 'day', 'hour', 'years', 'days', 'hours'],
required=True, type=str, nargs=1, help='Варианты функций.')
parser.add_argument('-YS', '--years', choices=['200'+str(i) for i in range(6, 10)]+['20'+str(i) for i in range(10, 21)],
nargs='+', help='По каким годам нужен график?')
def tw_years(years):
year_creating = []
for i in range(len(years)):
year = years[i]
creats = tw_year(year) / 5500000 * 100
year_creating.append(creats)
plot(x=years, y=year_creating, name='year')
if __name__ == '__main__':
token = r'G:\project\dbase\tw_db_5mln\twitter_5mln.db'
parser = create_parser()
func = parser.parse_args(sys.argv[1:])
if func.function[0] == 'years':
years = func.years
tw_years(years)
5. Анализ активности пользователей социальной сети твиттер на основе данных регистраций их аккаунтов
График зависимости регистраций от периода лет (Рис. 4)
Первые три года социальная сеть не имела особой популярности, полным ходом шла разработка и распространение на различных внутререгионных мероприятиях. В 2008 году сеть начали использовать журналисты и политики и уже за 2009 год было зарегистрировано 7% от всех пользователей: 330 миллионов. Дальше, как видно из графика, твиттер набрал огромные обороты и стал популярен во всём мире, и, получив за 2011-2012 года пользователей, основная волна регистраций была пройдена, количество ежегодных регистраций начало сильно падать.
График зависимости регистраций от дней недели (Рис. 5)
Данный график показался мне самым необычным из всех. Оказалось, что люди чаще всего пользуются социальными сетями в будние дни, конкретнее в среду. Скорее всего это происходит из-за того, что после работы людям хочется максимально отвлечся от всех дел и окунуться в новости и прессу. Ну а реже всего, как видим из графика, заходят по субботам и своскресеньям. Объясняется это тем, что на данные дни обычно больше всего планов: убраться по дому, сходить в кино, магазин и т.д.
График зависимости регистраций от времени суток (Рис. 6)
Видно два всплеска. Превый происходит с 11 утра и до 15 часов дня, после чего держится вплоть до 19 часов вечера и идёт на спад, часть людей идёт спать. И второй всплеск виден уже в 1 и 2 час ночи и обусловлен обычным, бессмысленным просмотром прессы после обыденных вечерних дел. Дальше и оставшаяся часть засыпает, начиная новый цикл.
Графики зависимости регистраций по разным дням недели от времени суток (Рис. 7)
По графику видим, что понедельник и вторник не сильно выделяются, находятся где-то между остальных графиков. Среда выделяется наибольшей активностью в ночное время и наименьшей утром, но тоже не сильно. Четверг и пятница имеют наименьшую активность в вечернее время, скорее всего люди хотят хорошо выспаться на выходных. Начало субботы и воскресенья необычные практически полным отсутствием второго, ночного, всплеска. Объясняется это тем, что перед выходным днём все ложаться спать пораньше. Но также выходные особенны наибольшей утренней активностью, обусловленные не рабочим днём.
Гистограмма зависимости количества регистраций от некоторых регионов Евразии (Рис. 8)
Взяты были такие регионы Евразии, как: Япония, Китай, Соединённое Королевство, Россия, Украина, Франция и Германия. Выбор делался на основе расстояния между странами и их важности в различных мировых сферах. Как видим, среди выбраных стран, твиттер наиболее распространён в Германии и наименее в таких восточных странах, как: Китай, Япония. Но остальные страны находятся примерно на одном уровне. Данная информация не в совершенстве точная, т.к. в твиттере со временем менялся способ указания региона и пользователи могли указывать что угодно.
График зависимости регистраций в регионов от периода лет (Рис. 9)
Первее других твиттер стал популярен в Соединённом Королевстве, обогнав по количеству регистраций в 2009 году. С 2010 практически все идут вровень, пик в 2011 и спад к 2018. В Японии и Китае сильно меньше других подъём в 2010-2012 годах, но ярко выделяется 2016 год с неожиданно большим наплывом людей, особенно в Китае, вероятно из-за китайской автогонки чемпионата мира «Формулы-1».
График зависимости регистраций в регионах от времени суток (Рис. 10)
Графики очень разные, но это было ожидаемо, ведь взяты страны с совершенно различными часовыми поясами. Япония и Китай имеют рост к трем часам ночи и спад в три часа дня, это логично, ведь в данных странах часовые пояса UTC+8 и +9. Соединённое Королевство, в свою очередь, имеет рост в шесть утра и спад только к десяти вечера. Здесь UTC+1. График регистраций России идёт рядом с графиком Франции. Он плавно начинает рост в пять утра и меняет направление только к десяти вечера. Украина и Гремания имеют похожие графики, только с разницей в один два часа. Они больше других сходны с графиком внутрисуточной активности: подъём с восьми утра и спад с восьми вечера.