Альтернатива традиционному веб-скрейпингу с использованием 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.
Посмотрим, сработает ли это!
Окей, это определенно не сработало… Кроме того, на некоторых сайтах всплывающие окна с просьбой войти или зарегистрироваться перекрывают интересующий меня контент.
Мне просто нужен способ автоматически открывать Chrome и переходить на сайты, где я уже авторизован. Похоже, что использование автоматизированных браузеров вроде Puppeteer мне не подойдёт, поскольку такие решения плохо масштабируются.
Попытка 5: Использование Open-Interpreter
С учетом всего вышесказанного, давайте попробуем автоматически открыть Chrome и получать нужный контент. Недавно я узнал, что Open-Interpreter умеет запускать приложения, так что попробуем попросить его посчитать моих подписчиков на LinkedIn.
Это здорово — страница открывается правильно, но проблема в том, что нет способа извлечь информацию с экрана. Open-Interpreter не позволяет получить доступ к HTML-коду страницы, а его возможности по созданию скриншотов все еще нестабильны.
Кстати, я также попробовал JS CLI-инструмент capture-website, который хорошо делает скриншоты, но столкнулся с теми же проблемами, что и Puppeteer и другие аналогичные инструменты.
www.npmjs.com/package/capture-website
Итак, мы можем автоматически переходить на страницы и делать скриншоты вручную. Что дальше?
Попытка 6: Использование AppleScript и Tesseract (OCR)
Мы уже знаем, что можно автоматически переходить на страницы с помощью AppleScript — именно такой механизм работал в Open-Interpreter. Теперь осталось понять, как автоматически делать скриншоты страниц после загрузки.
После этого мы можем использовать OCR (оптическое распознавание символов), например, библиотеку Tesseract, чтобы извлекать текст с экрана.
Это отличное решение, потому что если интерфейс социальных сетей изменится, наш скрипт все равно сможет адаптироваться, не завися от обновлений библиотек или API.
План готов, приступаем к написанию скрипта!
Сначала формально определим каждый из профилей, которые хотим учитывать. Добавим в словарь переменную account, чтобы можно было суммировать подписчиков с нескольких профилей на одной платформе, например, основного и альтернативного аккаунтов в Instagram.
Теперь мы можем определить функцию, которая будет перебирать список ссылок, переходить на страницу, делать скриншот с помощью pyautogui и сохранять его. Далее используем библиотеку Tesseract OCR, чтобы извлечь текст из скриншотов.
Пример получившегося скриншота:
Пример извлеченного текста:
extract_follower_count() находит правильное слово (followers, subscribers, friends) для каждой платформы и извлекает число, которое стоит перед этим словом. Это уже работает довольно хорошо, но для улучшения можно добавить LLM на этапе постобработки.
Давайте посмотрим, как справляется этот скрипт…
По состоянию на 8 мая 2024 года скрипт идеально извлекает количество подписчиков, даже при нескольких попытках.
Полный исходный код находится в репозитории. Вы сможете клонировать его и добавить любые ссылки по своему желанию. Я назвал этот проект HyperHerd, так как он связан с «собиранием» (herding) подписчиков.
Размышления и ограничения
Этот скрипт работает очень хорошо. Позже мне нужно будет провести бенчмаркинг, но по моим тестам он уже достаточно стабилен.
Однако у него есть несколько недостатков:
Идеальный вариант — запускать код на сервере, по расписанию, и сохранять данные в облачную базу данных, чтобы затем их можно было запрашивать или отправлять в другие системы.
Но поскольку для работы скрипта требуется, чтобы пользователь был авторизован на всех сервисах, а также имел корректные cookies и сессионные данные, лучшим решением остается локальный запуск на устройстве.
Чтобы копнуть глубже, я хочу исследовать использование Chrome-расширения вместо AppleScript для этого процесса. Насколько я понимаю, у этого подхода есть несколько ключевых преимуществ.
Наши основные операции — открыть Chrome, открыть ссылку в новой вкладке, сделать скриншот веб-страницы (или спарсить HTML), выполнить OCR и разобрать ответ. Поскольку у Tesseract есть библиотека для JavaScript, все вышеперечисленное возможно выполнить с помощью расширения Chrome.
Это решит проблему кроссплатформенности и устранит неудобства, связанные с тем, что во время работы скрипта нельзя пользоваться компьютером. Кроме того, мы сможем запускать расширение в фоновом режиме через определенные интервалы времени и сохранять данные в LocalStorage (или Firebase) для отслеживания количества подписчиков с течением времени.
Если OCR окажется слишком ненадежным, использование расширения Chrome предоставит доступ к сырому HTML. В сочетании с кодом для конвертации HTML в Markdown это позволит экспортировать и анализировать данные, значительно повышая точность.
На своем личном сайте я отображаю «живой» счетчик общего количества подписчиков на различных платформах: 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...')
Посмотрим, сработает ли это!

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

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

Это здорово — страница открывается правильно, но проблема в том, что нет способа извлечь информацию с экрана. 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
Пример получившегося скриншота:

Пример извлеченного текста:
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 на этапе постобработки.
Давайте посмотрим, как справляется этот скрипт…

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

Полный исходный код находится в репозитории. Вы сможете клонировать его и добавить любые ссылки по своему желанию. Я назвал этот проект HyperHerd, так как он связан с «собиранием» (herding) подписчиков.
Что можно улучшить
Размышления и ограничения
Этот скрипт работает очень хорошо. Позже мне нужно будет провести бенчмаркинг, но по моим тестам он уже достаточно стабилен.
Однако у него есть несколько недостатков:
- Работает только на Mac.
- Компьютер должен быть включен, а пользователь — запускать скрипт вручную.
- Во время работы скрипта пользователь не может использовать компьютер.
- Проблемы с интернетом (медленный Wi-Fi или его отсутствие) приводят к сбоям.
- Нет возможности отслеживать динамику подписчиков на каждой платформе.
Идеальный вариант — запускать код на сервере, по расписанию, и сохранять данные в облачную базу данных, чтобы затем их можно было запрашивать или отправлять в другие системы.
Но поскольку для работы скрипта требуется, чтобы пользователь был авторизован на всех сервисах, а также имел корректные cookies и сессионные данные, лучшим решением остается локальный запуск на устройстве.
Улучшения
Чтобы копнуть глубже, я хочу исследовать использование Chrome-расширения вместо AppleScript для этого процесса. Насколько я понимаю, у этого подхода есть несколько ключевых преимуществ.
Наши основные операции — открыть Chrome, открыть ссылку в новой вкладке, сделать скриншот веб-страницы (или спарсить HTML), выполнить OCR и разобрать ответ. Поскольку у Tesseract есть библиотека для JavaScript, все вышеперечисленное возможно выполнить с помощью расширения Chrome.
Это решит проблему кроссплатформенности и устранит неудобства, связанные с тем, что во время работы скрипта нельзя пользоваться компьютером. Кроме того, мы сможем запускать расширение в фоновом режиме через определенные интервалы времени и сохранять данные в LocalStorage (или Firebase) для отслеживания количества подписчиков с течением времени.
Если OCR окажется слишком ненадежным, использование расширения Chrome предоставит доступ к сырому HTML. В сочетании с кодом для конвертации HTML в Markdown это позволит экспортировать и анализировать данные, значительно повышая точность.