Автонаполняемый блог с почти бесконечным контентом на комментариях из Reddit (Мануал)
Мои 14-летние фантазии об автоблоге начали материализовываться только недавно, но это может стать вашей реальностью уже сегодня! Нет, вам не нужно "знать" python, чтобы запустить этот скрипт. Все, что вам нужно, это IDE на вашей локальной машине, понять, как установить несколько библиотек, и скрипт готов к запуску. Этот скрипт может быть масштабирован до многопоточного монстра, который может обрабатывать 100 параллельно и делать 10 000 000 постов с комментариями каждый день, поэтому я бы рекомендовал установить локальный сервер на virutalbox и экспортировать базу данных позже.
Больше интересных статей о SEO, сайтах, манимейкинге и пр. на канале - https://t.me/jimbo4fun
Что делает скрипт:
Извлекает лучшие посты из reddit вместе с 75-125 комментариями верхнего уровня каждого поста и постит их в wordpress, посты и комментарии - от оригинальных имен авторов с оригинальной временной меткой. Функция многопоточности с текущими настройками может сделать 200 постов со средним количеством 75 комментариев на пост примерно за 16 секунд.
Ограничения:
1. Только 100 запросов в секунду на аккаунт, но я рекомендую использовать количество запросов не более чем в 2 раза больше, чем количество ядер у вас есть. Скрипт засыпает после каждых 100 запросов на 61 секунду.
2. Если вы размещаете свой wordpress локально или на vps или выделенном сервере, то все в порядке, но если вы на виртуальном хостинге, то у вашего хостера могут быть проблемы с многочисленными запросами. Возможно, вам придется настроить ssh-туннель, или создать сайт локально, заполнить базу данных и перенести ее на сервер, или найти способ синхронизировать ее в реальном времени.
3. Если вы запустите скрипт и отойдете от него, и если произойдет потеря связи из-за одного из этих ограничений, скрипт перестанет работать.
4. Вам потребуется учетная запись администратора.
5. В скрипт не включен рерайтер, поэтому контент не является уникальным.
Порядок работы:
1. Если у вас нет среды python или IDE, установите их.
2. Скопируйте код и сохраните его в файл с расширением .py
3. Введите имя пользователя reddit, пароль, client-id и client-secret. Узнайте, как их сделать здесь https://www.geeksforgeeks.org/how-t...nt_secret-for-python-reddit-api-registration/.
4. Введите ваше имя пользователя wordpress и пароль приложения. Обычный пароль не сработает. Руководство по этому вопросу находится здесь https://www.paidmembershipspro.com/create-application-password-wordpress/.
5. Если вам нужна многопоточность, установите флажок в True, но изначально я бы рекомендовал оставить его в False.
6. Вы можете вводить по одному сабреддиту за раз или составить их список по одной строке в файле sr.txt в той же папке, что и файл кода.
7. Запустите скрипт.
import praw, os, requests, time, random, base64, json, secrets, string
from concurrent.futures import ProcessPoolExecutor
from datetime import datetime
redditUsername = ""
redditPassword = ""
redditClientId = ""
redditClientSecret = ""
redditPullLimit = 200
redditUserAgent= "postConsolidator_1.0"
wpDomain = '' ##DO NOT INCLUDE HTTPS OR WWW OR ANY TRAILING SLASHES. ONLY ENTER domainname.tld unless wordpress is located in a subfolder, in which case do not use a trailing slash
wpUsername = 'admin'
wpApplicationPassword = ''
wpHasHTTPS = True
wpPostStatus = 'publish'
wpCommentStatus = 'approve'
multiProcessFlag = False
multiProcessMaxWorkers = 16
reddit = praw.Reddit(username=redditUsername,
password=redditPassword,
client_id=redditClientId,
client_secret=redditClientSecret,
user_agent=redditUserAgent
)
wpCredentials = f'{wpUsername}:{wpApplicationPassword}'
wpCredentialsToken = base64.b64encode(wpCredentials.encode())
wpHeader = {'Authorization': 'Basic ' + wpCredentialsToken.decode('utf-8')}
if wpHasHTTPS:
wpPostAPIURL = f'https://{wpDomain}/wp-json/wp/v2/posts/'
wpCommentsAPIURL = f'https://{wpDomain}/wp-json/wp/v2/comments/'
wpUsersAPIURL = f'https://{wpDomain}/wp-json/wp/v2/users/'
else:
wpPostAPIURL = f'http://{wpDomain}/wp-json/wp/v2/posts/'
wpCommentsAPIURL = f'http://{wpDomain}/wp-json/wp/v2/comments/'
wpUsersAPIURL = f'http://{wpDomain}/wp-json/wp/v2/users/'
main_menu = '''
Howdy!
Hit
1: Input name of Subreddit manually
2: Import from a list of subreddits
3. Exit
Wachawannado? : '''
def post2wp(submission, i):
if str(submission.selftext) == '':
print('nothing to post')
return
wpUserDate = {
'username':str(submission.author).lower().replace('_',"").replace('-',''),
'email':str(submission.author).lower().replace('_',"").replace('-','') + '@' + wpDomain,
'password':''.join(secrets.choice(string.ascii_letters + string.digits + '!@#$%^&*()_+=-`~;:"|?><,./') for i in range(16)),
'roles':['subscriber'],
}
wpUserResponse = requests.post(url=wpUsersAPIURL, headers=wpHeader, json=wpUserDate)
try:
wpPostAuthorID = int(json.loads(wpUserResponse.text)['id'])
except KeyError:
print(f'{submission.author}, not created')
print(wpUserResponse.text)
wpPostAuthorID = 2
print('Author ID', wpPostAuthorID)
wpPostData = {
'title' : submission.title,
'status': wpPostStatus,
'content': submission.selftext,
'date_gmt':datetime.utcfromtimestamp(submission.created).strftime('%Y-%m-%dT%H:%M:%S'),
'author':wpPostAuthorID,
}
wpPostResponse = requests.post(url=wpPostAPIURL, headers=wpHeader, json=wpPostData)
print('wppostresponse', wpPostResponse)
try:
wpPostID = json.loads(wpPostResponse.text)['id']
except KeyError:
j=0
print('Bad Response, skipping post')
return
submission.comments.replace_more(limit=None)
for j, topLevelComment in enumerate(submission.comments):
if topLevelComment is not None:
wpCommentData = {
'post': wpPostID,
'author_name': topLevelComment.author,
'author_email': str(topLevelComment.author) + '@' + wpDomain,
'content': topLevelComment.body,
'status':wpCommentStatus,
'author_ip':str(random.randint(0,255))+'.'+str(random.randint(0,255))+'.'+str(random.randint(0,255))+'.'+str(random.randint(0,255)),
'date_gmt':datetime.utcfromtimestamp(topLevelComment.created).strftime('%Y-%m-%dT%H:%M:%S'),
}
wp_comment_response = requests.post(url=wpCommentsAPIURL, headers=wpHeader, data=wpCommentData)
print(i+1, j+1, wp_comment_response)
if j > random.randint(75,125):
break
print(f'Item no. {i + 1} posted, with {j+1} comments and title{submission.title} and post content \n\n {submission.selftext} \n\n {wpPostResponse}')
if __name__ == '__main__':
startTime = time.perf_counter()
try:
wachawannado = int(input(main_menu))
except ValueError:
print('\nPlease enter a number')
if wachawannado == 1:
subreddit = reddit.subreddit(input("Ok, lets crawl reddit.\nWhats the name of the subreddit? : "))
with ProcessPoolExecutor(max_workers=multiProcessMaxWorkers) as executor:
for i, submission in enumerate(subreddit.top(limit=redditPullLimit)):
if multiProcessFlag:
executor.submit(post2wp, submission=submission, i=i)
else:
post2wp(submission=submission, i=i)
elif wachawannado == 2:
if os.path.exists('sr.txt'):
if not os.stat("sr.txt").st_size == 0:
with open('sr.txt','r') as sr:
with ProcessPoolExecutor(max_workers=multiProcessMaxWorkers) as executor:
for i, line in enumerate(sr):
subreddit = reddit.subreddit(line)
for j, submission in enumerate(subreddit.top(limit=redditPullLimit)):
if multiProcessFlag:
executor.submit(post2wp, submission=submission, i=j)
if j % 99 == 0:
print('yawn')
time.sleep(61)
print('Sorry, dozed off')
else:
post2wp(submission=submission, i=j)
print(f'{i}:{line} done, pulled {j} submissions from {line}')
else:
print('sr.txt is empty')
else:
print('Cant find sr.txt with the list of SubReddits')
elif wachawannado == 3:
print('Bye!')
else:
print('\nHit a valid number\n')
print('Total time for this loop is ', time.perf_counter()-startTime)