Giving structure to the tool and libraries

This commit is contained in:
AjaySi
2023-10-07 14:12:45 +05:30
parent 12010c0478
commit 82525a0dfa
16 changed files with 159 additions and 277 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.pyc
__pycache__
pseo-experiemnts/
*.swp

View File

@@ -0,0 +1,51 @@
## Introduction
Given high level domain keywords like "Fishing baits online" Or any 2-3 main key words that describe, broadly, your business.
This tool will produce a SEO optimized blogs. This tool will suggest most popular blog topics, divide them in sub topics and write content for each sub topic. For each of the paragraphs, we summarise it and pass the line for text to image.
Thus, the generated blog will have text and relevant images.
(TBD) Provide the blog output as plain text, markdown Or HTML.
Presently, wordpress and WIX integration is present for uploading the generated blog, but needs testing.
This is based on openai gpt models for content generation, google bard for keyword research and some basic tools for plagiarism checker, SEO audit and suggestions to improve the generated content.
As prompts are the important ingredients to get the best result, they are stored in prompts folder. Edit these prompts to produce results as per your likings.
API based blog generation are much cheaper, almost 10x, but difficult to use for everyone. We use bard for search related prompts and chatgpt for generative requirements.
Check TBD for features currently under development.
----------------------------------
## How to use this tool
This is in active development and needs ironing out. The main concern is make it general purpose, for all.
Usuability and extendibility are major concerns. This section will be updated soon.
----------------------------------
# The detailed SEO checks are as follows:
- Keyword Density
- Keyword Presence in Title
- Keyword Presence in Image Alt Text
- Headings Text
- Internal Links
- External Links
- Readability Score
- Spelling Errors
- Grammar Errors
- SEO Score
- SEO Suggestions to improve generated content
-----------------------------------
#What to write on ?
This is basically keyword research for a specific domain, narrowed down by blog topics.
We can craft prompts to get an idea on what to generate blogs on. Divide them in topic and write for most searched ones, as below:
#[Prompts]
For more details on prompts used to get blog topics and SEO keyword research, check file blog_ideas.prompts in prompts folder.

9
TBD
View File

@@ -1,2 +1,9 @@
https://github.com/hardikvasa/google-images-download
1). https://github.com/hardikvasa/google-images-download
2). imagen from google
3). dalle-3
4). Bing images
5). Include gpt researcher : https://python.langchain.com/docs/use_cases/web_scraping
6). We need memory to store blogs posts and not repeat them.
Have a database, or query from web hosting, of all the blogs present.

Binary file not shown.

View File

@@ -90,7 +90,7 @@ def generate_detailed_blog(blog_keywords):
while('' in blog_topic_arr):
blog_topic_arr.remove('')
print(f"Generated Blog Topics: {type(blog_topic_arr)}---- {blog_topic_arr}")
print(f"Generated Blog Topics:---- {blog_topic_arr}")
# For each of blog topic, generate content.
for a_blog_topic in blog_topic_arr:
@@ -102,7 +102,7 @@ def generate_detailed_blog(blog_keywords):
a_topic = re.sub(r"^\W*\D*", "", a_blog_topic)
tpc_cnt = generate_topic_content(a_topic)
#print(f"{a_topic} ------ {tpc_cnt}")
print(f"{a_topic} ------ {tpc_cnt}")
# We now need to concatenate all the sections and sew it into blog content.
tmp_blog_markdown_str = blog_markdown_str + " " + a_blog_topic + " " + f"{tpc_cnt}"
@@ -111,7 +111,12 @@ def generate_detailed_blog(blog_keywords):
# print/check the final blog content.
print(f"Final blog content: {blog_markdown_str}")
# Save the blog content as a .md file. Markdown or HTML ?
# Best to name the file
# Use chatgpt to convert the text into HTML or markdown.
# Now, we need perform some *basic checks on the blog content, such as:
# is_content_ai_generated.py, plagiarism_checker_from_known_sources.py
# seo_analyzer.py . These are present in the lib folder.
# prompt: Rewrite, improve and paraphrase [text] and use headings and subheadings to break up the content and make it easier to read using the keyword [keyword].
@@ -195,6 +200,3 @@ def get_long_tailed_keywords(blog_article):
"""
# want you to generate a list of long-tail keywords that are related to the following blog post [Enter blog post text here]
pass

3
lib/seo_module/prompt Normal file
View File

@@ -0,0 +1,3 @@
Act as an SEO specialist, analyze [website URL], and make improvement suggestions regarding technical SEO with the ways to make those improvements listed in a table.

View File

@@ -0,0 +1,48 @@
import requests
import json
def upload_blog_post(wix_site_id, wix_api_key, blog_post_title, blog_post_content):
""" Uploads a blog post to a Wix website.
Args:
wix_site_id: The ID of the Wix website.
wix_api_key: The API key for the Wix website.
blog_post_title: The title of the blog post.
blog_post_content: The content of the blog post.
Returns:
None.
"""
# Create the request body.
request_body = {
"title": blog_post_title,
"content": blog_post_content
}
# Make the request to the Wix API.
response = requests.post(
f"https://{wix_site_id}.wixsite.com/api/v1/blog/posts",
headers={"Authorization": f"Bearer {wix_api_key}"},
json=request_body
)
# Check the response status code.
if response.status_code != 200:
raise Exception(f"Failed to upload blog post: {response.status_code}")
# Print a success message.
print("Blog post uploaded successfully!")
###########################################################################################
# Example usage:
wix_site_id = "1234567890"
wix_api_key = "YOUR_WIX_API_KEY"
blog_post_title = "My first blog post"
blog_post_content = "This is my first blog post."
upload_blog_post(wix_site_id, wix_api_key, blog_post_title, blog_post_content)

View File

@@ -1,21 +0,0 @@
## main.py
from wordpress_api import WordpressAPI
def main():
"""
Main entry point of the program.
"""
# Create WordpressAPI instance
wp_api = WordpressAPI(base_url="https://example.com", username="admin", password="password")
# Authenticate
wp_api.authenticate()
# Upload content
content = "This is a test content"
wp_api.upload_content(content)
if __name__ == "__main__":
main()

View File

@@ -1,30 +0,0 @@
## test_wordpress_api.py
import pytest
from wordpress_api import WordpressAPI
class TestWordpressAPI:
@pytest.fixture
def wp_api(self):
return WordpressAPI(base_url="https://example.com", username="admin", password="password")
def test_authenticate_success(self, wp_api):
wp_api.authenticate()
assert wp_api.authentication.token is not None
def test_authenticate_failure(self, wp_api):
wp_api.authentication.password = "wrong_password"
with pytest.raises(Exception):
wp_api.authenticate()
def test_upload_content_success(self, wp_api):
content = "This is a test content"
wp_api.upload_content(content)
# Add assertions here to verify the success of content upload
def test_upload_content_failure(self, wp_api):
content = "This is a test content"
wp_api.content_upload.base_url = "https://wrong_url.com"
with pytest.raises(Exception):
wp_api.upload_content(content)

View File

@@ -1,75 +0,0 @@
## wordpress_api.py
import requests
import json
class Authentication:
def __init__(self, base_url, username, password):
self.base_url = base_url
self.username = username
self.password = password
self.token = None
def authenticate(self):
"""
Authenticates the user with the Wordpress API.
"""
url = f"{self.base_url}/authenticate"
payload = {
"username": self.username,
"password": self.password
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
self.token = response.json()["token"]
else:
raise Exception("Authentication failed")
class ContentUpload:
def __init__(self, base_url, token):
self.base_url = base_url
self.token = token
def upload_content(self, content):
"""
Uploads the given content to the Wordpress API.
"""
url = f"{self.base_url}/upload"
payload = {
"content": content,
"token": self.token
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code != 200:
raise Exception("Content upload failed")
class WordpressAPI:
def __init__(self, base_url, username, password):
self.base_url = base_url
self.username = username
self.password = password
self.authentication = Authentication(base_url, username, password)
self.content_upload = ContentUpload(base_url, self.authentication.token)
def authenticate(self):
"""
Authenticates the user with the Wordpress API.
"""
self.authentication.authenticate()
def upload_content(self, content):
"""
Uploads the given content to the Wordpress API.
"""
self.content_upload.upload_content(content)

View File

@@ -1,54 +0,0 @@
## main.py
import os
import requests
import json
class WordPressAPIIntegration:
def __init__(self, credentials: dict):
self.credentials = credentials
def upload_file(self, file_path: str) -> bool:
if not self._check_file(file_path):
return False
if not self._authenticate():
return False
if not self._upload_file_to_api(file_path):
return False
return True
def _check_file(self, file_path: str) -> bool:
max_file_size = 10 * 1024 * 1024 # 10MB
file_size = os.path.getsize(file_path)
if file_size > max_file_size:
return False
valid_file_types = ['.jpg', '.jpeg', '.png', '.gif']
file_extension = os.path.splitext(file_path)[1]
if file_extension not in valid_file_types:
return False
return True
def _authenticate(self) -> bool:
url = "https://wordpress-api.com/authenticate"
headers = {'Content-Type': 'application/json'}
data = json.dumps(self.credentials)
response = requests.post(url, headers=headers, data=data)
if response.status_code == 200:
return True
return False
def _upload_file_to_api(self, file_path: str) -> bool:
url = "https://wordpress-api.com/upload"
files = {'file': open(file_path, 'rb')}
response = requests.post(url, files=files)
if response.status_code == 200:
return True
return False

View File

@@ -1,86 +0,0 @@
## test_wordpress_api_integration.py
import os
import pytest
from wordpress_api_integration import WordPressAPIIntegration
class TestWordPressAPIIntegration:
@pytest.fixture
def credentials(self):
return {
"username": "test_user",
"password": "test_password"
}
@pytest.fixture
def valid_file_path(self):
return "path/to/valid/file.jpg"
@pytest.fixture
def invalid_file_path(self):
return "path/to/invalid/file.txt"
def test_upload_file_valid_file(self, credentials, valid_file_path, monkeypatch):
def mock_check_file(file_path):
return True
def mock_authenticate():
return True
def mock_upload_file_to_api(file_path):
return True
monkeypatch.setattr(WordPressAPIIntegration, "_check_file", mock_check_file)
monkeypatch.setattr(WordPressAPIIntegration, "_authenticate", mock_authenticate)
monkeypatch.setattr(WordPressAPIIntegration, "_upload_file_to_api", mock_upload_file_to_api)
api_integration = WordPressAPIIntegration(credentials)
result = api_integration.upload_file(valid_file_path)
assert result is True
def test_upload_file_invalid_file(self, credentials, invalid_file_path, monkeypatch):
def mock_check_file(file_path):
return False
monkeypatch.setattr(WordPressAPIIntegration, "_check_file", mock_check_file)
api_integration = WordPressAPIIntegration(credentials)
result = api_integration.upload_file(invalid_file_path)
assert result is False
def test_upload_file_authentication_failed(self, credentials, valid_file_path, monkeypatch):
def mock_check_file(file_path):
return True
def mock_authenticate():
return False
monkeypatch.setattr(WordPressAPIIntegration, "_check_file", mock_check_file)
monkeypatch.setattr(WordPressAPIIntegration, "_authenticate", mock_authenticate)
api_integration = WordPressAPIIntegration(credentials)
result = api_integration.upload_file(valid_file_path)
assert result is False
def test_upload_file_upload_failed(self, credentials, valid_file_path, monkeypatch):
def mock_check_file(file_path):
return True
def mock_authenticate():
return True
def mock_upload_file_to_api(file_path):
return False
monkeypatch.setattr(WordPressAPIIntegration, "_check_file", mock_check_file)
monkeypatch.setattr(WordPressAPIIntegration, "_authenticate", mock_authenticate)
monkeypatch.setattr(WordPressAPIIntegration, "_upload_file_to_api", mock_upload_file_to_api)
api_integration = WordPressAPIIntegration(credentials)
result = api_integration.upload_file(valid_file_path)
assert result is False

4
prompt
View File

@@ -1,4 +0,0 @@
Move all hard coded values from the modules and put the them in a config file.
Suggest functions that be improved upon on readibility, polymorphism and remove redundany.
Make the code conform to PEP standards.
Include try and except. Include exception at possible places. Include detailed excpetions and error messages.

View File

@@ -0,0 +1,40 @@
#####################################################
#
# Use below prompts to generate Idea or topics, titles to write on.
#
#####################################################
# This is basically keyword research for a specific domain, narrowed down by blog topics.
# We can craft prompts to get an idea on what to generate blogs on.
# Divide them in topic and write for most searched ones, as below:
-------------------------------------------------------------------
--- Write seven subheadings for the blog article with the title [title]; the titles should be catchy and 60 characters max.
--- List the top 5 most popular long tail keywords for the topic [YOUR TOPIC]
--- What Are The {X} Most Popular Sub-topics Related To {Topic}?
--- What Are The {X} Most Popular Sub-topics Related To {Sub-topic}?
--- List Without Description The Top {X} Most Popular Keywords For The Topic Of {X}
--- List Without Description The Top {X} Most Popular Long-tail Keywords For The Topic “{X}”
--- List Without Description The Top Semantically Related Keywords And Entities For The Topic {X}
--- Give me five popular keywords that include “SEO” in the word, and the following letter starts with a. Once the answer has been done, move on to giving five more popular keywords that include “SEO” for each letter of the alphabet b to z.
--- For the topic of “{Topic}” list 10 keywords each for the different types of user personas
--- Generate 50 keywords for the topic “[Topic]” that contain “vs”
--- Perform the following steps in a consecutive order Step 1, Step 2, Step 3, Step 4.
Step 1 Generate the 5 most popular keywords related to the topic of “keyword" with their search intent.
Step 2 For each keyword provide 2 long-tail keywords.
Step 3 Generate the 5 most popular questions that include those keywords.
Step 4 Generate 5 blog article titles based on the keywords from Step 1 and Step 2.
--- As a technical writer experienced in SEO, please create a detailed blog post outline that provides a step-by-step guide
for using [X], targeting beginners with a friendly and helpful tone and a desired length of 800-1000 words.