Как стать автором
Обновить

Разработка Python-скрипта с live-счётчиком подписчиков для сайта

Время на прочтение8 мин
Количество просмотров1.9K
Автор оригинала: Jack Blair
Альтернатива традиционному веб-скрейпингу с использованием AppleScript и OCR

На своем личном сайте я отображаю «живой» счетчик общего количества подписчиков на различных платформах: LinkedIn, GitHub, YouTube, Instagram, Twitter, Medium и Facebook. Я стараюсь геймифицировать социальные сети для себя, и точный подсчет подписчиков и данных играет ключевую роль в достижении этой цели.

Смотрите вживую здесь.


«Живой» счетчик подписчиков на моем сайте.

В текущей версии я вручную захожу на каждую платформу, суммирую количество подписчиков и обновляю цифру во Framer. Но я же не просто так работаю data scientist'ом и люблю экспериментировать! Давайте попробуем найти более изящное решение. Моя цель — создать автономный скрипт, который будет автоматически собирать статистику с каждой платформы и подсчитывать итоговое значение.

Автоматизация процесса сбора данных


Попытка 1: Использование сторонних платформ

Сначала я подумал о том, чтобы воспользоваться сторонними сервисами, которые могли бы собрать все данные в одном месте за меня. Такие платформы, как Hootsuite и Funnel.io, предлагают подобные инструменты, но они довольно дорогие и ориентированы на малый бизнес, готовый инвестировать в аналитику. В моем случае мне нужен всего лишь простой скрипт, который просто суммирует количество подписчиков.

Кроме того, у таких крупных платформ есть серьезный недостаток: для работы с ними нужно «подключить» все свои аккаунты, что, по сути, означает передачу им своих паролей и снижение уровня безопасности.

Этот путь явно не подходит для моей цели.

Попытка 2: Использование API социальных сетей

Это второй «с конца» вариант. У каждой социальной сети есть свой API, своя система тарификации, набор функций и ограничения по количеству запросов. Например, существуют Twitter API, Facebook Graph API, Unsplash API и многие другие.

Хотя такие API достаточно безопасны, поскольку они предоставляются самими платформами, их настройка и поддержка требуют огромного количества времени. Кроме того, для работы с ними часто нужно привязывать банковскую карту к разным сервисам, что мне не нравится.

Еще один серьезный минус — вся активность привязана к моему аккаунту, а это повышает риск блокировки за возможное нарушение правил использования API.

Определённо не то, что мне нужно.

Попытка 3: Использование библиотек Python

Давайте проверим, пробовал ли кто-то уже решить эту проблему до меня.

Похоже, кто-то написал API для LinkedIn! Также есть Pytube — API для YouTube.

Однако с Twitter все сложнее — после того, как Илон Маск приобрёл сесть, они заблокировали сторонние API, и теперь за доступ придется платить. Medium, похоже, тоже предоставляет API.

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

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

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

Попытка 4: Парсинг и HTML-скрейпинг (Puppeteer, Chromium и др.)

А вот здесь уже начинается настоящая разработка. Я нашёл код, который получает количество подписчиков в Twitter.

from bs4 import BeautifulSoup
import requests
handle = input('Input your account name on Twitter: ') 
temp = requests.get('https://twitter.com/'+handle)
bs = BeautifulSoup(temp.text,'lxml')
try:
    follow_box = bs.find('li',{'class':'ProfileNav-item ProfileNav-item--followers'})
    followers = follow_box.find('a').find('span',{'class':'ProfileNav-value'})
    print("Number of followers: {} ".format(followers.get('data-count')))
except:
    print('Account name not found...')

Посмотрим, сработает ли это!

image

Окей, это определенно не сработало… Кроме того, на некоторых сайтах всплывающие окна с просьбой войти или зарегистрироваться перекрывают интересующий меня контент.

image

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

Попытка 5: Использование Open-Interpreter

С учетом всего вышесказанного, давайте попробуем автоматически открыть Chrome и получать нужный контент. Недавно я узнал, что Open-Interpreter умеет запускать приложения, так что попробуем попросить его посчитать моих подписчиков на LinkedIn.

image

Это здорово — страница открывается правильно, но проблема в том, что нет способа извлечь информацию с экрана. Open-Interpreter не позволяет получить доступ к HTML-коду страницы, а его возможности по созданию скриншотов все еще нестабильны.

Кстати, я также попробовал JS CLI-инструмент capture-website, который хорошо делает скриншоты, но столкнулся с теми же проблемами, что и Puppeteer и другие аналогичные инструменты.

www.npmjs.com/package/capture-website

Итак, мы можем автоматически переходить на страницы и делать скриншоты вручную. Что дальше?

Попытка 6: Использование AppleScript и Tesseract (OCR)

Мы уже знаем, что можно автоматически переходить на страницы с помощью AppleScript — именно такой механизм работал в Open-Interpreter. Теперь осталось понять, как автоматически делать скриншоты страниц после загрузки.

После этого мы можем использовать OCR (оптическое распознавание символов), например, библиотеку Tesseract, чтобы извлекать текст с экрана.

Это отличное решение, потому что если интерфейс социальных сетей изменится, наш скрипт все равно сможет адаптироваться, не завися от обновлений библиотек или API.

План готов, приступаем к написанию скрипта!

YOUTUBE_LINK = 'https://www.youtube.com/channel/UC-uTdkWQ8doqRwXBlkH67Dw'
LINKEDIN_LINK = 'https://www.linkedin.com/in/jackblair876/'
GITHUB_LINK = 'https://github.com/JackBlair87'
INSTAGRAM_LINK_MAIN = 'https://www.instagram.com/jack.blairr/'
INSTAGRAM_LINK_SECONDARY = 'https://www.instagram.com/jack.bl.ai.rt/'
TWITTER_LINK = 'https://twitter.com/JackBlair87'
MEDIUM_LINK = 'https://medium.com/@jackblair87'
FACEBOOK_LINK = 'https://www.facebook.com/jack.blair.94043/'

PROFILE_LINKS = [{ 'link' : YOUTUBE_LINK, 'platform' : 'youtube', 'account' : 'main' }, 
                 { 'link' : LINKEDIN_LINK, 'platform' : 'linkedin', 'account' : 'main' },
                 { 'link' : GITHUB_LINK, 'platform' : 'github', 'account' : 'main' },
                 { 'link' : INSTAGRAM_LINK_MAIN, 'platform' : 'instagram', 'account' : 'main' },
                 { 'link' : INSTAGRAM_LINK_SECONDARY, 'platform' : 'instagram', 'account' : 'art' },
                 { 'link' : TWITTER_LINK, 'platform' : 'twitter', 'account' : 'main' },
                 { 'link' : MEDIUM_LINK, 'platform' : 'medium', 'account' : 'main' },
                 { 'link' : FACEBOOK_LINK, 'platform' : 'facebook', 'account' : 'main' }]

TOTAL_FOLLOWERS = 0

Сначала формально определим каждый из профилей, которые хотим учитывать. Добавим в словарь переменную account, чтобы можно было суммировать подписчиков с нескольких профилей на одной платформе, например, основного и альтернативного аккаунтов в Instagram.

def take_screenshots():
    for link in tqdm(PROFILE_LINKS):
        temp_link = 'screenshots/' + link['platform'] + '[' + link['account'] + '].png'
        
        #join this path with the current path
        full_link = os.path.join(os.getcwd(), temp_link.replace(' ', '\ '))
        print(full_link)

        r = applescript.run(f"""
            tell application "Google Chrome"
                activate
                open location "{link['link']}"
                set thePath to "{full_link}"
                delay 5
                do shell script ("screencapture " & thePath)
            end tell
            """)
        
        #save it to the desktop
        image1 = pyautogui.screenshot(full_link)
        image1.save(full_link)
        
        r = applescript.run(f"""
            tell application "Google Chrome"
                try
                    tell window 1 of application "Google Chrome" to ¬
                        close active tab
                end try
            end tell
            """)

Теперь мы можем определить функцию, которая будет перебирать список ссылок, переходить на страницу, делать скриншот с помощью pyautogui и сохранять его. Далее используем библиотеку Tesseract OCR, чтобы извлечь текст из скриншотов.

def extract_follower_count(text, platform):
    platform_mappings = {
        'youtube': 'subscribers',
        'instagram': 'followers',
        'twitter': 'followers',
        'facebook': 'friends',
        'github': 'followers',
        'linkedin': 'followers',
        'medium': 'followers'
    }

    if platform in platform_mappings:
        keyword = platform_mappings[platform]
        count_text = text.split(keyword)[0]
        count = list(map(str.strip, count_text.split()))[-1]
        print(f'{platform.capitalize()} count:', count)
        return convert_youtube_strings_to_values(count)
    else:
        print('Platform not supported')
        return None
        
def ocr_image(image_path, platform):
    global TOTAL_FOLLOWERS
    # Load image
    img = cv2.imread(image_path)
    # Convert image to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Apply threshold to convert to binary image
    # threshold_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

    # Pass the image through pytesseract
    text = pytesseract.image_to_string(gray)
    # Print the extracted text
    # print(text)
    
    #save to a text file
    with open('text_files/' + image_path.split('/')[1].split('.')[0] + '.txt', 'w') as f:
        f.write(text)
        
    TOTAL_FOLLOWERS += extract_follower_count(text.lower(), platform)
        
    return text

Пример получившегося скриншота:

image

Пример извлеченного текста:

GM OMOUR®) @ oO © © S CG GG CEG 9 sBeg x +

23 https://www.linkedin.com/in/jackblair876/ A small AppleScript to take a
screenshot every 30 seconds for 8...

a: 3 Try 1 month offer i
‘in| Q Search aa _ : yt gist.github.com
My Network Messaging Notifications For Business Premium for $

Profile language V4
English
Public profile & URL V4

www.linkedin.com/in/jackblair876

Ad ee

Get the latest jobs and industry news

i zm Purdue University College
Jack Blair 9 , of Engineering \\
@ PURDUE '26 | @ TJHSST '22 | °. 2x Founder | & Al Researcher |
® Full Stack Developer | »# Eagle Scout Jack, explore relevant opportunities
San Francisco Bay Area - Contact info with Twilio
My Portfolio (7 ( Follow -

\ )

3,706 followers - 500+ connections

t opento J Add profile section )( More )

Open to work o Ron Nachum - ‘st
Software Engineer, System Engineer, Mechanical Engineer and Project Engineer roles Founder | Harvard CS/Stat |
Show details

Other similar profiles

ronnachum.com

Rohin Inani - 2nd
Incoming SWE Intern @

Analytics
© Private to you

$ 845 profile views ul, 4,125 post impressions Q. 339 search appearances Ambarella | CS @ Purdue...
Discover who's viewed your Check out who's engaging with See how often you appear in
profile. your posts. search results. a* Connect
Past 7 days
. Kushagr Khanna - ‘st A Messagin: ow BA
Show all analytics > 9 . we ging

extract_follower_count() находит правильное слово (followers, subscribers, friends) для каждой платформы и извлекает число, которое стоит перед этим словом. Это уже работает довольно хорошо, но для улучшения можно добавить LLM на этапе постобработки.

Давайте посмотрим, как справляется этот скрипт…

image

По состоянию на 8 мая 2024 года скрипт идеально извлекает количество подписчиков, даже при нескольких попытках.

image

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

Что можно улучшить


Размышления и ограничения


Этот скрипт работает очень хорошо. Позже мне нужно будет провести бенчмаркинг, но по моим тестам он уже достаточно стабилен.

Однако у него есть несколько недостатков:
  1. Работает только на Mac.
  2. Компьютер должен быть включен, а пользователь — запускать скрипт вручную.
  3. Во время работы скрипта пользователь не может использовать компьютер.
  4. Проблемы с интернетом (медленный Wi-Fi или его отсутствие) приводят к сбоям.
  5. Нет возможности отслеживать динамику подписчиков на каждой платформе.

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

Но поскольку для работы скрипта требуется, чтобы пользователь был авторизован на всех сервисах, а также имел корректные cookies и сессионные данные, лучшим решением остается локальный запуск на устройстве.

Улучшения


Чтобы копнуть глубже, я хочу исследовать использование Chrome-расширения вместо AppleScript для этого процесса. Насколько я понимаю, у этого подхода есть несколько ключевых преимуществ.

Наши основные операции — открыть Chrome, открыть ссылку в новой вкладке, сделать скриншот веб-страницы (или спарсить HTML), выполнить OCR и разобрать ответ. Поскольку у Tesseract есть библиотека для JavaScript, все вышеперечисленное возможно выполнить с помощью расширения Chrome.

Это решит проблему кроссплатформенности и устранит неудобства, связанные с тем, что во время работы скрипта нельзя пользоваться компьютером. Кроме того, мы сможем запускать расширение в фоновом режиме через определенные интервалы времени и сохранять данные в LocalStorage (или Firebase) для отслеживания количества подписчиков с течением времени.

Если OCR окажется слишком ненадежным, использование расширения Chrome предоставит доступ к сырому HTML. В сочетании с кодом для конвертации HTML в Markdown это позволит экспортировать и анализировать данные, значительно повышая точность.
Теги:
Хабы:
+7
Комментарии1

Публикации

Информация

Сайт
piter.com
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия