Рубрики
Без рубрики

Соскабливание моего социального графика Twitter с помощью Python и Selenium

Использование Python и Selenium, чтобы найти лучшее подход в Twitter. Tagged DataScience, Python, Selenium, JavaScript.

Я был в Твиттере в течение 9 лет, но только только что понял: Twitter в лучшем случае используется, например, Messenger или WhatsApp, а не когда он используется как Facebook.

Другими словами, я получаю максимальную отдачу от Twitter, когда использую его для общения с реальными людьми с общими интересами, а не для того, чтобы не отставать от новостей, компаний или знаменитостей, и определенно не для споров со случайными незнакомцами в Интернете.

Через 9 лет (в основном бездействие) в Твиттере я собрал около 4000 Твиттер следует. Они отражают мой опыт: Некоторые из них являются финансовыми аккаунтами, некоторые музыканты, некоторые продукты/производители, некоторые аккаунты для шуток, некоторые разработчики. Но в соответствии с моим осознанием выше, я обнаружил, что хочу уменьшить шум и превратить свое использование в Твиттере во что -то, что помогает улучшить мою новую карьеру.

К лучшему или худшему, большая часть сообщества разработчиков находится в Твиттере. Я только начал участвовать в «Dev Twitter» в середине Моя карьера переход от финансов к разработке программного обеспечения , но быстро потерялся в диком шуме.

Dev Twitter замечательный: вы можете Взаимодействовать со старшими разработчиками , Получите помощь Когда вы столкнетесь с неприятностями, публиковать свою работу и даже Получите работу Анкет

Однако Twitter также может быть всем Огонь мусора Люди делают это: постоянная какофония запутанных контекстных критических комментариев, охватывающих все, от спорта до политики до знаменитостей, политики и технологий, политики, чтобы финансировать политику для ботов. Даже вне дешевых ударов в политике, вы также получаете случайно Крылы В Dev Twitter, который никто на самом деле не нуждается. (JavaScript даже имеет horse_js , выделенная, но любимая учетная запись Troll, которая вызывает вещи!) Это даже побудило Secondcareerdev’s Кайл Шевлин чтобы сформулировать Правила взаимодействия в Твиттере (Что я очень рекомендую).

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

Твиттер, как и многие социальные платформы, имеет “поверьте мне Я знаю, что лучше для вас ». Алгоритм рекомендации. Когда вы прокручиваете свой основной канал, вы видите твиты от людей, за которыми следуют люди, за которыми вы следуете. Если вы отправитесь на вкладку поиска (в мобильном приложении) и нажимаете Connect, вы увидите список людей, предложенных «потому что вы следите», «Люди, которых вы можете знать» и «на основе вашей активности» (последнее Хуже всего, поскольку это дает рекомендации с одной точки данных). Если вы немного использовали Twitter, вы узнаете группы, которые создают эти алгоритмы: вот группа «Женщины в технологии», вот группа «массово популярные создатели контента». Хотя технически правильные, многие варианты в конечном итоге просто чувствуют себя неправильно Анкет Я следую Реактивная учетная запись Twitter , и это говорит о том, чтобы я следил за Угловой и Emberjs учетные записи. Это отличные рамки, но это просто не учетные записи, которых я хочу следовать в настоящее время. Я не фанат американского футбола Но я бы рискнул, что этот же алгоритм предложит счет Патриотов и фанату Seahawks, как это думает.

Тем не мение.

Пользователи Twitter дополняют эту автоматизированную рекомендацию, ретвитируя других для разоблачения, а также вызывая их в специальных постах. Это даже получило собственный специальный хэштег, известный как #Followfriday Анкет Поскольку случается предвзятость, иногда появляются специальные посты Как эти от выдающихся членов сообщества, помогающих недопредставленным группам. Но это очень специально и ручное.

Так что, будучи разработчиком, возникает естественный вопрос: что, если я возьму алгоритм рекомендации в свои руки?

Разработчики знакомы с идеей, что Все это график Анкет Twitter – это изученный вручную, социальный график пользователей с различным (даже вероятностным) качеством сигнала и неясной, различной функцией оптимизации. Самый высокий сигнал-это следующее, которое является более устойчивым, тогда как лайки, ретвиты, а ответы также являются сигналами, но являются скорее единодушной природой. Если вы следите за кучей людей, которых вы считаете высоким качеством, следует, то их следующие последствия имеют лучшую, чем случайные шансы на вас интересно. Там нет реального термина для «Следующего квадрата», поэтому я взял на себя, чтобы называть их «FoFollows».

Все это, конечно, имеет более академическое обоснование, чем я имею право говорить, но в основном вы захотите изучить Алгоритмы сетевой центральности Чтобы увидеть, как ученые официально определяют различные меры сетевой центральности.

Честно говоря, мне не нравится идея определения «хорошего следующего» по «количеством фофоуллоуз». Поскольку люди (включая меня) следуют менталитету стада, это чрезмерно предубеждения в отношении культуры знаменитостей и недостатки тех, кто также выпускает качественное содержание, но по какой -либо причине еще не получило признания за это. Так, например, этот алгоритм предпочитает кому -то известного, кто только что настроил свою учетную запись в Twitter в CrossPost из Instagram, может получить тонну следующих и лайков и ретвитов, Хотя этот человек даже не использует Twitter Анкет Я определенно предпочитаю тому, кто на самом деле дает вдумчивые ответы людям, но гораздо меньше. У меня есть некоторые идеи о том, как это сделать, но у меня будет место для решения их в будущем. (Я просто хотел зарегистрироваться заранее, что я знаю, что это очень ошибочный алгоритм, и пригласить конструктивные предложения.)

Хотя я не буду вполне в состоянии решить проблемы общества в этом посте только в этом посте, есть несколько интересных вещей, которые мы можем сделать с информацией, которая у нас есть:

  1. Автоматизация: Во -первых, мы должны соскрести наши данные из Twitter. Это будет большая часть стоимости этого поста, если вы кодируетесь.
  2. Анализ: во -вторых, мы должны обработать данные в поверхностные метрики, которые мы хотим, чтобы AKA Engineering Engineering
  3. Дисплей: наконец, мы должны легко понять результаты, чтобы я (и заинтересованным другим) мог выполнить их, а затем, наконец, действовать на них

Эти три вещи очень разные навыки, и в реальной компании было бы куча разных рабочих мест для разных людей. Но я просто делаю это в свое время, чтобы улучшить свою личную ситуацию. Так что, как бы я ни хотел, я хотел бы получить авторитетный результат, я, честно говоря, был бы доволен всего лишь на 10% лучшего опыта (не то, что это даже можно измерить).

Во -первых: я не юридический эксперт, поэтому приступите к своей собственной осторожности. Но давайте просто скажем, что в Twitter есть больше ботов, чем вы, если вы напишете один.

Ok. Хотя я профессиональный парень JS, и есть Способы для соскоба в Nodejs , экосистема царапины питона и числа, разжигая номера, просто существуют уже гораздо дольше, так что я иду.

Чтобы следовать, убедитесь, что у вас есть Записная книжка Юпитера и распределение Anaconda Python Анкет Если вы совершенно новичок в ноутбуке Python/Jupyter, вам нужно будет найти еще один урок, чтобы провести вас через это, мы не делаем здесь вступительные вещи. Следующие фрагменты кода непосредственно соответствуют ячейкам ноутбука Юпитера.

Начало работы с Selenium и Python

Теперь импортируйте все вещи, которые нам понадобятся (PIP установите все, что у вас не хватает):

%matplotlib inline
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import sys

import unittest, time, re
from bs4 import BeautifulSoup as bs
from dateutil import parser
import pandas as pd
import itertools
import matplotlib.pyplot as plt

Теперь вы можете видеть, что мы собираемся использовать Селен Чтобы сделать автоматизацию. Мы будем использовать его для автоматизации Firefox, чтобы он мог продолжаться на заднем плане, пока мы продолжаем в нашем обычном браузере (я знаю Более 60% из вас используют хром )

driver = webdriver.Firefox()
driver.base_url = "https://twitter.com/swyx/following"
driver.get(driver.base_url)

Поменяйте мое имя пользователя на ваше. Если вы запускаете этот кусочек кода, он открывает Firefox на страницу входа в Twitter. Если вы входите в систему со своими собственными учетными данными, он затем переходит на вашу страницу следующих. Проблема с соскобкой этой страницы заключается в том, что это страница «бесконечная прокрутка», поэтому просто соскребает все, что загружается в первом представлении, недостаточно. Вы должны прокрутить вниз, подождать, пока он загрузится, и снова прокрутите вниз, и снова и снова, пока вы не загрузите все. Вы можете попытаться Получите это от официального API Twitter Но они дают вам всего 15 запросов каждые 15 минут. Итак, мы царапаем.

После того, как вы входите в систему, вы можете использовать инспектор Firefox Devtools, чтобы посмотреть на теги HTML и атрибуты, которые вам интересны. Если вы новичок в HTML/Devtools, это тоже нормально, но опять же, у меня нет места, чтобы научить это здесь. Проверить Freecodecamp , Codecademy или Mdn Анкет

Основная бесконечная стратегия прокрутки

Самый простой способ автоматизировать бесконечную свиток – сделать что -то вроде этого:

for i in range(1,230):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(2)
    print(i)

У меня 4000 следует Итак, я прибыл в Диапазон (1230) Просто выполняя несколько тестовых прогонов, а затем рассчитав, сколько петель мне нужно, чтобы покрыть все. Поскольку у других людей будет меньше или более, чем 4000, нам придется сделать эту динамичную стратегию, и я расскажу об этом ниже.

Я использую Time.sleep (2) чтобы позволить нагрузку страницы. Это, вероятно, длиннее, чем мне нужно, основываясь на моем высокоскоростном соединении, но я решил обменять более длительное автоматизированное время выполнения для более низкого риска не загружать все данные, которые мне нужны. Я тоже Распечатать Мой прогресс, как способ, указать, как далеко я нахожусь в своем процессе, так как иногда может быть трудно сказать, насколько я близок к тому, чтобы быть сделанным. В этом случае, чтобы запустить около 8 минут, но мы будем запускать будущие вещи гораздо дольше, и я хотел объяснить основную интуицию.

Сохранение данных

html_source = driver.page_source
sourcedata= html_source.encode('utf-8')
soup=bs(sourcedata)
arr = [x.div['data-screen-name'] for x in soup.body.findAll('div', attrs={'data-item-type':'user'})]
bios = [x.p.text for x in soup.body.findAll('div', attrs={'data-item-type':'user'})]
fullnames = [x.text.strip() for x in soup.body.findAll('a', 'fullname')][1:] # avoid your own name
d = {'usernames': arr, 'bios': bios, 'fullnames': fullnames}
df = pd.DataFrame(data=d)
df.to_csv('data/BASICDATA.csv')

Это дает вам DataFrame дф У этого есть имена пользователей, полные имена и биографии всех, за которыми вы следуете. Уоха! Ты закончил! Правильно??

Неа. Ты только начинаешь.

Теперь мы должны масштабировать то, что вы только что сделали для одного пользователя (вас) для всех ваших пользователей.

Некоторая быстрая автоматическая математика – скажем, все, что мы только что сделали, заняло 10 минут. 10 минут x 4000 000 дней !!! Это не невозможно, но слишком высок, чтобы быть разумным. Как мы можем сделать это в разумное время?

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

Как я обратился к этому, разделив его на 8 блоков из 500 пользователей. Это приблизительно 1,4 часа до 28 дней работы. Не так уж плохо?

К концу этого раздела вы будете делать Total Black Magic с Selenium:

Расскажите 8 различных ноутбуков Jupyter и войдите в Twitter в каждом экземпляре Firefox (см. Драйвер . Firefox () выше). Назовите их четко, чтобы вы не случайно путаете каждый блокнот.

Теперь в каждой ноутбуке вы можете прочитать данные, которые вы выводите из своего первоначального запуска:

df = pd.read_csv('data/BASICDATA.csv', encoding = "ISO-8859-1")
arr = df.usernames

Динамическая бесконечная стратегия прокрутки

Не выполняйте этот код, но просто чтобы показать вам, как сделать основную стратегию бесконечной прокрутки выше более динамичной:

    loopCounter = 0
    lastHeight = driver.execute_script("return document.body.scrollHeight")
    while True:
        if loopCounter > 499:
            break; # if the account follows a ton of people, its probably a bot, cut it off
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(2)
        newHeight = driver.execute_script("return document.body.scrollHeight")
        if newHeight == lastHeight:
            break
        lastHeight = newHeight
        loopCounter = loopCounter + 1

По сути, храните высоту документа, и если он перестает расти после того, как вы прокручиваете дно, затем пришли к выводу, что вы достигли конца ( lastheeth ) и выйдите из петли.

Параллелизированный код

А затем вы устанавливаете свой диапазон для каждого ноутбука. Итак, эта книга охватывает пользователя 500 – 999:

for i in range(500,1000):
    currentUser = arr[i]
    print('now doing user ' + str(i) + ': ' + currentUser)
    driver.base_url = "https://twitter.com/" + currentUser + "/following"
    driver.get(driver.base_url)
    time.sleep(3) # first load
    loopCounter = 0
    lastHeight = driver.execute_script("return document.body.scrollHeight")
    while True:
        if loopCounter > 499:
            break; # if the account follows a ton of people, its probably a bot, cut it off
        if loopCounter > 0 and loopCounter % 50 == 0:
            print(loopCounter)
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(2)
        newHeight = driver.execute_script("return document.body.scrollHeight")
        if newHeight == lastHeight:
            break
        lastHeight = newHeight
        loopCounter = loopCounter + 1
    print('ended at: ' + str(loopCounter))
    html_source = driver.page_source
    sourcedata = html_source.encode('utf-8')
    soup=bs(sourcedata)
    temparr = [x.div['data-screen-name'] for x in soup.body.findAll('div', attrs={'data-item-type':'user'})]
    tempbios = [x.p.text for x in soup.body.findAll('div', attrs={'data-item-type':'user'})]
    fullnames = [x.text.strip() for x in soup.body.findAll('a', 'fullname')][1:] # avoid your own name
    d = {'usernames': temparr, 'bios': tempbios, 'fullnames': fullnames}
    df = pd.DataFrame(data=d)
    df.to_csv('data/' + currentUser + '.csv')

Я хочу быть очень ясно, что происходит, когда я ошибаюсь на чрезмерном сайте журнала. Время от времени при разработке такой автоматизации вы столкнетесь с ошибкой, и вы не хотите возвращаться и перезапустить часы автоматизации, которые работали нормально. Таким образом, способность забрать, где вы разбились, – это хорошо. (Вы также можете реализовать лучшую обработку ошибок, но это ограничит вашу способность отвечать, когда возникнут ошибки, и Исправить будущие ошибки .)

Сбор более глубоких данных для первой степени следует за

В первый раз, когда я это сделал, вышеупомянутое было все, что я сделал, но вскоре я обнаружил, что хочу больше данных для последующего последующего. Поэтому я запустил еще один блокнот. На этот раз я хотел посетить страницу «with_replies» каждого пользователя, чтобы получить некоторые данные с их временной шкалы. При этом я могу получить некоторое представление о «взаимодействии» (общее количество комментариев, лайков и ретвитов оригинального контента) и их позитивности (оценка настроений на основе автоматического анализа твитов, чтобы увидеть, является ли аккаунт в основном положительной или отрицательной).

Сделайте тот же вход в процесс Firefox, что и выше, а затем прочитайте в необработанных данных:

df = pd.read_csv('data/BASICDATA.csv', encoding = "ISO-8859-1")
arr = df.usernames

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

Затем мы инициализируем DataFrame:

main = pd.DataFrame(data = {
        'user': ['swyx'],
        'text': ['text'],
        'tweetTimestamps': ['tweetTimestamps'],
        'engagements': ['engagements'],
        'name': ['name'],
        'loc': ['loc'],
        'url': ['url'],
        'stats_tweets': ['stats_tweets'],
        'stats_following': ['stats_following'],
        'stats_followers': ['stats_followers'],
        'stats_favorites': ['stats_favorites'],
    })

И теперь мы проходим через профиль каждого пользователя в arr множество:

def getTimestamps(x):
    temp = x.findAll('span', '_timestamp')
    if len(temp) > 0:
        return temp[0].get('data-time')
    else:
        return None
# now get the user's own timeline
for i in range(0,len(arr)):
    currentUser = arr[i]
    print('doing user:' + str(i) + ' ' + currentUser)
    driver.base_url = "https://twitter.com/" + currentUser + '/with_replies'
    driver.get(driver.base_url)
    html_source = driver.page_source
    dailyemail_links = html_source.encode('utf-8')
    soup=bs(dailyemail_links, "lxml")
    time.sleep(2)
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(1)
    # name
    name = soup.find('a', "ProfileHeaderCard-nameLink").text
    # loc
    temp = soup.find('span', 'ProfileHeaderCard-locationText')
    temp = temp.text if temp else ''
    loc = temp.strip() if temp else ''
    # url
    temp = soup.find('span', 'ProfileHeaderCard-urlText')
    temp = temp.a if temp else None
    temp2 = temp.get('title') if temp else None
    url = temp2 if temp2 else (temp.get('href') if temp else None)
    # stats
    temp = soup.find('a',{'data-nav': 'tweets'})
    stats_tweets = temp.find('span', 'ProfileNav-value')['data-count'] if temp else 0
    temp = soup.find('a',{'data-nav': 'following'})
    stats_following = temp.find('span', 'ProfileNav-value')['data-count'] if temp else 0
    temp = soup.find('a',{'data-nav': 'followers'})
    stats_followers = temp.find('span', 'ProfileNav-value')['data-count'] if temp else 0
    temp = soup.find('a',{'data-nav': 'favorites'})
    stats_favorites = temp.find('span', 'ProfileNav-value')['data-count'] if temp else 0
    # all text
    text = [''.join(x.findAll(text=True)) for x in soup.body.findAll('p', 'tweet-text')]
    # most recent activity
    alltweets = soup.body.findAll('li', attrs={'data-item-type':'tweet'})
    tweetTimestamps = list(map(getTimestamps, alltweets)) if len(alltweets) > 0 else 0
    # engagements
    noretweets = [x.findAll('span', 'ProfileTweet-actionCount') for x in alltweets if not x.div.get('data-retweet-id')]
    templist = [x.findAll('span', 'ProfileTweet-actionCount') for x in alltweets if not x.div.get('data-retweet-id')]
    templist = [item for sublist in templist for item in sublist]
    engagements = sum([int(x.get('data-tweet-stat-count')) for x in templist if x.get('data-tweet-stat-count')])
    main = pd.concat([main, pd.DataFrame(data = {
        'user': [currentUser],
        'text': [text],
        'mostrecentTimestamp': [tweetTimestamps],
        'engagements': [engagements],
        'name': [name],
        'loc': [loc],
        'url': [url],
        'stats_tweets': [stats_tweets],
        'stats_following': [stats_following],
        'stats_followers': [stats_followers],
        'stats_favorites': [stats_favorites],
    })])
    main.to_csv('data/BASICDATA_profiles.csv')

А теперь наш Главный DataFrame имеет все эти более подробные данные на каждой учетной записи! Он также экспортируется в Basicdata_profiles.csv файл.

В то время как вся эта автоматизация продолжается, мы можем продолжать в нашем основном наборе данных!

Расскажите новую ноутбук Jupyter, на этот раз только для анализа данных. Импортируйте обычные вещи, но на этот раз мы также будем использовать TextBlob для анализа настроений, так что продолжайте и импортируйте TextBlob: от TextBlob Import TextBlob

Обратите внимание, что вам также нужно будет загрузить несколько тел для работы Texblob, но ошибка подсказывает, что при запуске приведенного ниже кода поможет вам выполнить загрузку довольно легко (это один линер в Anaconda).

Мы можем сделать немного инженерии функций на скудных данных, которые мы получаем из Twitter. В частности, мы можем попытаться:

  • классифицировать вид аккаунта (разработчик, производитель, основатель и т. Д.)
  • Угадайте пол учетной записи (на основе полного имени пользователя) – люди хотят следовать за женщинами в технологии
  • Оцените позитивность счетов твитов – люди хотят больше позитивности в своем ленте в Твиттере.

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

df1 = pd.read_csv('data/BASICDATA.csv', encoding = "ISO-8859-1")
df2 = pd.read_csv('data/BASICDATA_profiles.csv', encoding = "ISO-8859-1").set_index('user')[1:].drop(['Unnamed: 0'], axis=1).drop(['tweetTimestamps'], axis=1)
df2['bios'] = df1.set_index('usernames')['bios']
arr = df1.usernames
jslist = [ 'react', 'webpack', ' js', 'javascript','frontend', 'front-end', 'underscore','entscheidungsproblem', 'meteor']
osslist = [' oss', 'open source','maintainer']
designlist = ['css', 'designer', 'designing']
devlist = [' dev','web dev', 'webdev', 'code', 'coding',  'eng',  'software', 'full-stack', 'fullstack', 'backend', 'devops', 'graphql', 'programming',  'computer', 'scien']
makerlist = ['entrepreneur', 'hacker', 'maker', 'founder', 'internet', 'web']
def categorize(x):
    bio = str(x).lower()
    if any(s in bio for s in jslist):
        return 'js'
    elif any(s in bio for s in osslist):
        return 'oss'
    elif any(s in bio for s in designlist):
        return 'design'
    elif any(s in bio for s in devlist):
        return 'dev'
    elif any(s in bio for s in makerlist):
        return 'maker'
    else:
        return ''
df2['cat'] = list(map(categorize,df2['bios']))
df2['stats_followers'] = list(map(lambda x: int(x), df2['stats_followers']))
df2['stats_following'] = list(map(lambda x: int(x), df2['stats_following']))
df2['stats-ratio'] = df2.apply(lambda x: x['stats_followers']/x['stats_following'] + math.sqrt(x['stats_followers']) if x['stats_following'] > 1 else math.sqrt(x['stats_followers']), axis=1) 
df2['stats-ratio'] = list(map(lambda x: min(200,x), df2['stats-ratio']))
df2['positivity'] = df2['text'].apply(lambda y: sum([x.sentiment.polarity for x in TextBlob(' '.join(y)).sentences]))
df2['eng_ratio'] = df2.apply(lambda x: math.log(int(x['engagements']))/math.log(x['stats_followers']) if int(x['engagements']) > 0 and int(x['stats_followers']) > 1 else 0, axis=1)

Так что, если вы проверите DF2 Теперь у вас есть несколько полей, которые вы можете использовать. Поле «кошки» представляет наши усилия по составлению нашего следствия в различных группах, основанных на ключевых словах в их биографии. В той степени, в которой никто не может быть на самом деле поместить в одно ведро, это сизифанская задача, но мы можем попробовать:) (если бы мы применили какое -то машинное обучение к этому, ближайший соседей Здесь, так как мы можем сломать ключевые слова, используя TextBlob)

Вот как разразились мои категории:

print(len(df2[df2['cat'] == 'maker'])) # 573
print(len(df2[df2['cat'] == 'design'])) # 136
print(len(df2[df2['cat'] == 'oss'])) # 53
print(len(df2[df2['cat'] == 'js'])) # 355
print(len(df2[df2['cat'] == 'dev'])) # 758

Хорошо, теперь мы где -то получаем.

Мы также разработаем кучу других метрик, например, Статистика-Ratio , который является соотношением последователей к следующему плюс квадратный корень последователей, при условии максимума 200. Это произвольная формула, позволяющая влиять людей с высоким влиянием, но ограничить влияние суперзвезд.

Eng_ratio Коэффициент взаимодействия, который пытается сделать что -то подобное для взаимодействия (лайки, ретвиты и комментарии оригинального контента) в качестве соотношения для подписчиков (если у вас есть больше подписчиков, у вас, вероятно, есть больше взаимодействия, поэтому лучше всего взглянуть на соотношение).

Мы пропускаем много работы по анализу и инженерии функций, но это то, что у меня сейчас есть:).

Хорошо, это на самом деле самый сложный кусочек. Если я остановлюсь и объединяю свои данные о FoFollower для 355 учетных записей Twitter, классифицированных как разработчики «JS», я получаю более 200 000 ребра между источником и пунктом назначения:

import os.path
def getData(x):
    fp = 'data/' + x + '.csv'
    if  os.path.isfile(fp):
        temp = pd.read_csv(fp, encoding = "ISO-8859-1")[['usernames', 'bios']] 
        temp.columns = ['target', 'bios']
        temp['source'] = x
        temp['cat'] = list(map(categorize,temp['bios'])) # categorize the bios of the fofollows
        return temp
temp = list(map(getData, list(df2[df2['cat'] == 'js'].index)))
combined = pd.concat(temp) # all target-source relationships originating from 'js'

Затем я могу отобразить данные, однако я выберу:

screened = combined.groupby(by='target').count().sort_values(by='source', ascending=False)[:50][['bios']]
screened.columns = ['fofollow_count'] 
screened_with_combined_info = screened
screened_with_combined_info['bios'] = combined.groupby(by='target').first()[['bios']]
screened_with_combined_info['cat'] = combined.groupby(by='target').first()[['cat']]

Форматирование для отображения Markdown …

df = screened_with_combined_info.reset_index()[['target','fofollow_count','cat','bios']]
df['target'] = df['target'].apply(lambda x: "[" + x + "](https://twitter.com/" + x + ")")
# Get column names
cols = df.columns

# Create a new DataFrame with just the markdown
# strings
df2 = pd.DataFrame([['---',]*len(cols)], columns=cols)

#Create a new concatenated DataFrame
df3 = pd.concat([df2, df])

#Save as markdown
df3.to_csv("nor.md", sep="|", index=False)
JS Работа над @reactjs. Соавтор Redux и Create React App. Строительство инструментов для людей. dan_abramov 210
производитель Интернет потрясающий, давайте сделаем это еще лучше? Я работаю над веб -производительностью, @____Lighthouse & @chromedevtools. Большой поклонник ржаного виски, данных и прихоти Paul_irish 190
JS React – это декларативная, эффективная и гибкая библиотека JavaScript для создания пользовательских интерфейсов. Reactjs 189
девчонка Англ. Менеджер Google работает над @googlechrome & Web Devrel? Создатель ToDomvc, @yeoman, Material Design Lite, критический? Team @WorkBoxjs ?? Адёсмани 181
дизайн Отмеченный наградами спикер. Старший Developer Advocate @microsoft. @Vuejs Основная команда, писатель @Real_css_tricks, соучредитель @WebanImworkshop, работа:? Sarah_edo 181
@zeithq Раухг 173
JS Французский фронт-инженер в Facebook. Работая над React, React Native, красивее, йога, нуклида и некоторых других крутых вещей … Vjeux 169
JS Триллер, основатель @reacttraining, creator @unpkg, организатор @shape_hq, участник @ldschurch Мджексон 158
JS Сделать разработку программного обеспечения более доступной · муж, отец, мормон, учитель, OSS, GDE, @TC39 · @paypaleng @eggheadio @frontendmasters? Кенткдоддс 157
JS React JS · TC39 · Facebook · твиты личные Sebmarkbage 157
JS Cofounder @withspectrum Advisor @Educatianc производит стиль-компоненты, React-BoilerPlate и MicroAnalytics Specialty Coffee Geek. MXSTBR 157
JS Владелец http://workshop.me и http://totalreact.com Райанфлорс 156
JS Спикер, инженер, #Webpack Core Team, адвокат разработчика, фермер. Взгляды мои собственные. Tpm @microsoft @msedgedev @edgedevtools.? Теларкинн 155
JS Создатель @JQuery, JavaScript Programer, автор, японский woodblock nerd (http://ukiyo-e.org), работа в @khanacademy. ДЖЕРСИГ 149
JS Австралийский я пишу JavaScript женат на @anagobarreto SEBMCK 147
JS Chrome Devrel в @google. Создатель @preactjs. Делать больше с меньшими затратами. http://github.com/developit _ развивать 145
девчонка Набивая мою голову кодом и превращая ее в @codecartoons. также, Тинкинг с Webassembly, @Servodev и немного @Rustlang в @Mozilla Линкларк 144
JS Мне нравится исправлять вещи. Энг -менеджер @reactjs в Facebook. Бывший@Khanacademy. Она/она. доброта, межсекционный феминизм, музыка. Софиты 143
JS Сопутствующий – Основатель и генеральный директор @hellosmyte. EX-FB и Instagram. Работал над React.js. Floydophone 143
девчонка Сокращение как Shift Reset LLC. Работа над @actualbudget. Создан @prettierCode. Бывший мозилла. Пользуется функциональным программированием. Jlongster 142
Ос Директор OSS @FormidableLabs? Профессиональный американец? Манхилд? Папа ? @Папа Бэконбрикс? Все мнения являются мнением Miller Lite? @toddmotto Fan ken_wheeler 141
Волонтер в сообществе и стюард @babeljs. @Behance, @adobe. Соли Део Глория левый_Пад 140
JS @reactjs Core в Facebook. Привет! acdlite 140
JS Node.js javascript время выполнения Nodejs 137
JS Создатель вещей: ReactJS. Работая над: @Reasonml. AT: Facebook Engineering. Джордвальке 135
девчонка “Как люди строят программное обеспечение. Нужна помощь? Отправьте нам сообщение по адресу http://git.io/c для поддержки ». GitHub 132
JS Создание вещей в Facebook с 2008 года: React, GraphQL, Immutable.js, Mobile, JavaScript, Чертушка доверенный 132
JS Создал JavaScript. Соучредил Mozilla и Firefox. В настоящее время Основатель и генеральный директор @brave Software (https://brave.com/). Бренданих 130
девчонка Ранее Pojer · Engineering Manager в Facebook · Метро · шутка · пряжа CPOJER 129
JS “JavaScript: блог @2alty, books @ExploringJs, обучение, информационный бюллетень @esnextnews. Причинамл: твиты @ReasonMlhub, новостная рассылка?” Раушма 128
JS Fullstack Dev? JS CSS Узел? https://es6.io? https://learnnode.com? http://reactforbeginners.com? http://javascript30.com? Советы ? @Kaitbos? @Syntaxfm Уэсбос 125
Ос Соучредитель Tilde, энтузиаст OSS и мировой путешественник. Wycats 125
девчонка Инженер программного обеспечения в @Google, #RXJS Core Team. Иногда я действую глупо на подкасте @moderndotweb. Взгляды мои собственные. Бенлеш 121
Ос Производитель вещей; Приложения MacOS и инструменты CLI. В настоящее время в Swift и Node.js. Полный рабочий день. Начал @ava__js. Sindresorhus 120
девчонка Основатель и разработчик Solo https://apex.sh, а не стартап. https://github.com/tj https://medium.com/@tjholowaychuk. Асия. Tjholowaychuk 119
девчонка Директор по дизайну продуктов @bustle, Google Dev Expert, & Cohost @Toolsday. Prev ui eng @digitalocean @ibmdesign. Жизнь путешествий: http://instagram.com/unakravets Уна 118
Ос Изучение мира через код, путешествия и инженер с открытым исходным кодом @Apollograpsql Пеггирайзис 117
Элонмуск 117
производитель Google. Я хочу, чтобы Интернет делал то, что нативно делает лучше, и быстро. Никакие мысли не являются неопубликованными. ‘ IMO ‘неявное. Jaffathecake 115
JS Дизайн, код и вещи между ними. Полный рабочий день. Creator @Vuejs, ранее @meteorjs & @google, @parsonsamt выпускник. Youyuxi 115
JS JavaScript Tinkerer, Bug Fixer и Benchmark Runner? Создатель Лодаша? Бывшая чакра перф -премьер -министр? Текущие веб -приложения и фреймворки PM @microsoft. Jdalton 113
Harbourmaster @Google Самкконе 113
дизайн CSS Modules соавтор, @melbjs Organizer. Addict Ecmascript с полным стеком, энтузиаст дизайна пользовательского интерфейса, Designops Designops кофе на @seekjobs Маркдалглиш 113
TheJameskyle 112
JS JavaScript Thinkfluencer Томдейл 112
JS Перед моим именем есть подчеркивание _chenglou 109
JS Я работаю над @V8JS в Google и над ECMASCRICE через TC39. JavaScript, HTML, CSS, HTTP, производительность, безопасность, Bash, Unicode, I18N, MacOS. Матиас 107
девчонка Блокчейн Инженер. Создание новой компании (Schelling). Уважаемый @coinbase @a16z @goldmansachs. Увлечен блокчейном и крипто. Заядлый? iam_preethi 106
JS Entscheidungsproblem Threepointone 106
JS Daily JavaScript / JS News, ссылки и события. Перейдите в @reactdaily для новостей React. JavaScriptDaily 105

Это лучшие 50 разработчиков JS, за которыми следуют другие разработки! Уго! Не плохое место, чтобы получить 4100 слов, а?

У меня, конечно, есть гораздо больше анализа данных, но я постановлю результаты в отдельном сообщении, с большим взаимодействием и следованиями данных, разделенными по полу, местоположению и так далее. Бесстыдное время заглушки: Подписывайтесь на меня Если вы хотите получить уведомление, когда я выпущу!

Что еще вы можете сделать со своими данными? Разместите где -нибудь, и я бы хотел написать в Твиттере!

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

Оригинал: “https://dev.to/swyx/scraping-my-twitter-social-graph-with-python-and-selenium–hn8”