From 82525a0dfa5ae20f473caab7c76ef31cbb9f99a7 Mon Sep 17 00:00:00 2001 From: AjaySi Date: Sat, 7 Oct 2023 14:12:45 +0530 Subject: [PATCH] Giving structure to the tool and libraries --- .gitignore | 1 + README.md | 51 +++++++++++ TBD | 9 +- lib/.get_text_response.py.swp | Bin 24576 -> 0 bytes lib/get_text_response.py | 14 +-- lib/seo_module/prompt | 3 + .../README.md | 0 .../wix_integration.py | 48 ++++++++++ .../wordpress_api_integration.py | 0 lib/wordpress_api_integration/V1/main.py | 21 ----- .../V1/test_wordpress_api.py | 30 ------ .../V1/wordpress_api.py | 75 --------------- lib/wordpress_api_integration/V2/main.py | 54 ----------- .../V2/test_wordpress_api_integration.py | 86 ------------------ prompt | 4 - prompts/blog_ideas_prompts.md | 40 ++++++++ 16 files changed, 159 insertions(+), 277 deletions(-) delete mode 100644 lib/.get_text_response.py.swp create mode 100644 lib/seo_module/prompt rename lib/{wordpress_api_integration => webhosting_integrations}/README.md (100%) create mode 100644 lib/webhosting_integrations/wix_integration.py rename lib/{wordpress_api_integration/V2 => webhosting_integrations}/wordpress_api_integration.py (100%) delete mode 100644 lib/wordpress_api_integration/V1/main.py delete mode 100644 lib/wordpress_api_integration/V1/test_wordpress_api.py delete mode 100644 lib/wordpress_api_integration/V1/wordpress_api.py delete mode 100644 lib/wordpress_api_integration/V2/main.py delete mode 100644 lib/wordpress_api_integration/V2/test_wordpress_api_integration.py delete mode 100644 prompt create mode 100644 prompts/blog_ideas_prompts.md diff --git a/.gitignore b/.gitignore index 80319ff0..ea2c618d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc __pycache__ pseo-experiemnts/ +*.swp diff --git a/README.md b/README.md index e69de29b..a34df8cf 100644 --- a/README.md +++ b/README.md @@ -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. + diff --git a/TBD b/TBD index ea142857..b552bd49 100644 --- a/TBD +++ b/TBD @@ -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. diff --git a/lib/.get_text_response.py.swp b/lib/.get_text_response.py.swp deleted file mode 100644 index 0ac235ad8377d73d883d6b090f93cd88e3cf1e09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeI4e~ctYb;lcym>5R$=maD+faiWEU4M~T3J#75Z1Z}H=gL@`Jp z;Pa}gyJz-xeYSC;{OG>>?o4-Ay?XWP)vK!a-tOw$+m?>28(IfFu2*>86R-F!{n!h> z>)mwk9?$>%G>CeAdGoZFD>r+qp9NXo)w9?C&fMG%HQwb49vG%NZtDv}odg3NW$A%1 zSUu3wSv%7gvUZ}=VH~BpH5~0gq<&OOpq9Y1mq4Da&E9a$nL`KX&D3l*UaR)L^31cR zQ`e{^P)neeKrMk<0<{Ec3Dgp(B~VM?f2{a2VVKp89pq`%my4@I~-B@E~{qde5L^X>=d!CS#~;41L_mwVnvz#oF+;0<6NTn!$(+Vk!McY_=(fmed7z@sno zybpmkI0aq{9($?h-3vYh`rviodoS_4uYvo)2DlL%051gp^kUDu3;Z$oBXA778teg2 zUgddz1MUSM0UrhbZ0r^g8V1n0_+!KcAr zf@Sa;@N;DTI1t(Yo5=rpzLdLG!?@SZ;$hHf`$^JD^dR2QQ~UN!ds1MtAB1wJf=Er4 zoL(>mn(Cyfp`ttt)rKGDI#qtur9vkj3`3o1Mb1VZW@*b*n53c>RT!k%R8L1b@iX17 zUZ+#$`??-&#z{AwZl%L8$fg?SqQ_qPUJwMK7So}+Li(Qrh0;ZVhEhRPu3`!F8np`Sn?4pWt< zx~o=4=JnZQfeyP;cqz&>9nV(OFp1Z6ng(&?Q+hMV`lcw4t)x2Svq%l?cX$IyE2ySA z9HpC@R$$&Vi$Di)6poaiuG8dsM4dquDywmxnQ~?zm2Yn}!{FHVlPu^+-xOC9c#j$8O^mINwZm7Mg}d4a~T)}UUK~o>00I|q$4Rm z?*=;RKsr@tyLv5%wC(z~_bX*>GxWY%OQ_eCVPt&#AuTcR{wfS*F*LG1!>6O3-(x1B zf?b#{Nlc2(@4yDbZ*;qdst839sgW&m-86l-?-^25*Q&}{qbG>bjmGIWz1eDg!_6Nd z#9&0Kn3xJJ%}B>mjJnm-RClVuKix+PYk6cIq2t(s%wLzuBa>8}7W*OtZDd>#bu_37 z)gUw62n&d_EY$Am%x7M9jcwRw6c(_GiYw7so2=YMLS@hH>-6KGqtksW*2Y;fg{iW(r>Qz(9z?gDfuMKR*!a?U=B%xj zdcw&Ni<3>QHI@^MBF4npDso%dayNC7NSYEM2HXsxP~|Mp-9qj5TiwPEcV*#z-&PkL?YJbrY*E7M`6S%T_eL z=j z^qeg(JJA#gY{VhmL@0E5tcczF*)?iksw#5Qi(EE5ve)VBaLD>`L3i@Zc7oZk;PwDn z+YSSX-@|Y;<;J8^g_%Ns7UwyUcwR6V#z}@9E53XjvJ zr#-LvJY8N>{we;O-I43E+v>`eCk*3Fky^(e`l|tln?R=v6h}_%^9vct{)GLe*=m$S zWIEJiRW@&f4R&f)G%acKdAd9~|HqugzXIg^U&QDC_FB%e;L||-01tt?z=C2z&wrzz0t_y8puGqu|TnOQ61L3Dgp(B~VMCmOw3mS^~8MY6;X5s3lNK z;CYjP;wqiAO@e%5k(kooUxmHGIO@%c3%(4@*mJu$Ch%Y288p!$afnoBTI2RN5r?x! zB@$-i0Oo->2{`m8dd0X3ijaeFb*zXW;PI0fi!_asLA?J}<8tJc#!M3v!JaB~khP_1 z+XW7afRYU!xGKh7AdQZR;#A%v>Oz!+rnS$P>uJ4b!xLBNpNV=^y{upY#34!5!cv_yOnn_km5Y0$u|CnX~*C!23ZT^uS*5F!B3$fVYDd_z5xl&wwrP z2Vf3-i}vnw?ap(*2RzLEd%+vQ4d6Gx$B5$}1wSNa|EJ&}mraAPfC78KKMBSf{XLZU^kVE^_i()qvNU{^!n<^ z>5~dKyls3ah(wCp5wq94i_m7GTZ4 zDPJfg(U7tDdyrL&%EXi~b=t0|bC#F0LYgb$&^sx-5wf9>K1+4K(tMMa<@)cP7W4m; zr$wm%&2n-yO2yj27}{|Wy=uMP;{4T2uSxd3m*^MPG8KsnM zqa(dkWeSb$HVX+Xu(`SWVsW>1>CV4usWOeL7sp+dhI!A-?o2XPY)Xuz;n-bnf-4NNjP_-DX^ot|Lp`h9sA?l+8;b*)9=bl+qAW zR(85*V$~%ut!fN3dx2E-@_>9PlgCuHQTDW|ZwE?*BF~nQ<7rveL^7&i0l8x*eIq)_ zKr%1oOUvYmNsufhHpMdM2Fwk`vR%sUqJcS=l)8T2S2vmWg<(5-VL?3u#fCZyf!Um( z1i^spCz~p_JR;%3?f@hxECb;bR2Jzx3eM+_ANjjcJ`3#V4xRAlq39p7B%Mt5ymkpT z9TkJmpOg~qA#iF9X_F+b!fdwvpj}LXE_7zpF!Xx?%SbwCo2(O^v?c!5UXM)PAvs|r z3&|g(Qd~`STf8}=HnoaK!;$P3SRSY}CJwuQ)lbQTGDIY^tUAUxlP$S;?BjgGfR31C z>X99mNvsdSP!5H0xqfnvBCRM^x12tHtE3NbOgw z6at2j9lv6wI2K64+&BRi2f1w*tx4u(u`_Dg73P4=&XK0ci`!PeW&0+=x{MBcgv*~@ zr~I+JP%(e!BCb|=cVj9E0#P3MJrHW=D^uiumZ-!rFv6LoEfljagK?DwZNu{UG!~A?v|Q07rTd|o7EcX z9?_vfU0oh;vHm+ERgIE+_lBy8Zeir6lE&|zyM6z;H}7xEuq7ewb4=h>eY?>rT9eH? zwnP$Ob9y|oX%_R-qDYP!bI_#+qY48u9|^Mj=hX2&kv?-1VN3oI~_7LNl=p%K9lZ(VaKXskXyVUmpmUBImf_xjl zC;LPGADnZ!$wIrScG?@6o)&ws1tsZkHnol>$=+n53$yISd@`M9dttolhqJQk%^FiS zYtryiyU0k%arp`hM(Ir>l7(%1*;L0UX?CG3m_}txiJ5Y|3x=#PJz>Alpqt$$wX5F5 zT(t?9vaQQTLv7t4Woy%0qGN7SmrrFzOZ@+5oO55r*;vm1#qaO`;#%_4!K2_2a1S^I z_JPMa`+pfoy#FY8k~9B%z%=+r&ijvm+rZB_)Bgwfd+-4uXa6=h0$Si2@FULn-vplp z_kcB^K^GK$fIWQwDL#OI2ls&+!Q=PzC*vi4&Dvk1&kaJMSay0s3lNK;QylpWRa(-nnJ?Y>LA)6W vZerXZvBD8d_zc%CJ~dAajkpMW7csJ)l`;1~ 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 diff --git a/lib/wordpress_api_integration/V2/test_wordpress_api_integration.py b/lib/wordpress_api_integration/V2/test_wordpress_api_integration.py deleted file mode 100644 index 31fea1e0..00000000 --- a/lib/wordpress_api_integration/V2/test_wordpress_api_integration.py +++ /dev/null @@ -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 diff --git a/prompt b/prompt deleted file mode 100644 index b7f4b816..00000000 --- a/prompt +++ /dev/null @@ -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. diff --git a/prompts/blog_ideas_prompts.md b/prompts/blog_ideas_prompts.md new file mode 100644 index 00000000..7d002413 --- /dev/null +++ b/prompts/blog_ideas_prompts.md @@ -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.