zenwalker
3/13/2016 - 12:29 AM

Transfer YouTube subscriptions to another account

Transfer YouTube subscriptions to another account

"""
Automatic migration of subscriptions to another
YouTube account with Python and Selenium.

Tested with:
 - selenium 3.0
 - firefox 49.0
 - python 3.5

 1. Install selenium from pypi:
    $ pip install selenium

 2. Go to the down of page https://www.youtube.com/subscription_manager
    and download your current subscriptions feed.
    Save file as subscription_manager.xml.

 4. Run script, enter your credentials and go to drink coffee.
    It will take some time.

Note YouTube will temporary block you if you have more that 80 subscriptions.
Just restart the script in a few hours.
"""

from collections import namedtuple
from selenium import webdriver
from xml.dom import minidom
import time
import re


def main():
    driver = webdriver.Firefox()
    sign_in(driver)
    for channel in load_subcribtions():
        subscribe(driver, channel)
    driver.close()


def sign_in(driver):
    email, password = input('Email: '), input('Password: ')

    driver.get('https://www.youtube.com')
    driver.find_element_by_css_selector('.signin-container button').click()
    time.sleep(1)

    driver.find_element_by_id('Email').send_keys(email)
    driver.find_element_by_id('next').click()
    time.sleep(1)

    driver.find_element_by_id('Passwd').send_keys(password)
    driver.find_element_by_id('signIn').click()
    time.sleep(1)


def load_subcribtions():
    xmldoc = minidom.parse('subscription_manager.xml')
    itemlist = xmldoc.getElementsByTagName('outline')
    channel_id_regexp = re.compile('channel_id=(.*)$')
    Channel = namedtuple('Channel', ['id', 'title'])
    subscriptions = []

    for item in itemlist:
        try:
            feed_url = item.attributes['xmlUrl'].value
            channel = Channel(id=channel_id_regexp.findall(feed_url)[0],
                              title=item.attributes['title'].value)
            subscriptions.append(channel)
        except KeyError:
            pass

    return subscriptions


def subscribe(driver, channel):
    channel_url = 'https://www.youtube.com/channel/' + channel.id
    driver.get(channel_url)
    time.sleep(1)

    button = driver.find_element_by_css_selector('.channel-header-subscription-button-container > button')
    is_subscribed = button.get_attribute('data-is-subscribed')

    if not is_subscribed:
        button.click()

    print('{:.<50}{}'.format(channel.title, 'skip' if is_subscribed else 'done'))
    time.sleep(1)


if __name__ == '__main__':
    main()