naver크롤링 && wp api를 이용한 임시글 등록구현

This commit is contained in:
icurfer 2025-01-19 23:58:30 +09:00
parent da51f38e3c
commit 084f46edd9
10 changed files with 164 additions and 13 deletions

View File

@ -1,9 +1,24 @@
# wp-post-automation
## 목적
* 워드프레스 포스팅 자동화 기능 구현.
## 주요내용
### 프로젝트 소개
2025.01.19 - 네이버 블로그 스크랩 및 워드프레스 임시글 등록 기능 구현
* 초기 기능 구현 완료.
2024.10.04 - 테스트 완료. 프로젝트 1차 종료.
* 워드프레스 포스팅 자동화 프로젝트.
* make.com을 이용해서 만든 AutoMation Flow를 Python을 이용하여 변환.
## 기존 Flow
### 사용방법
* sample.env.dev를 복사하여 루트 디렉토리에 .env.prd | .env.dev | .env 중 하나로 생성하여 사용 합니다.
* main.py가 기본 자동화 프로세스 입니다.
* 크롤링된 게시물을 OpenAI가 변형하여 마크다운으로 등록합니다.
* main_naver_blog_html은 네이버 블로그 전용 프로세스 입니다.
* 크롤링된 게시물을 그대로 마크다운으로 등록합니다.
---
## 참고 워크 플로우
* MariaDB에 저장된 최신 참고 url정보를 얻어온다.
* HTTP모듈을 이용하여 참고 자료를 가져온다.
* 가져온 HTML형태의 자료를 Text만 추출한다.
@ -15,35 +30,48 @@
* WordPress에 포스팅을 한다.
## 개발 계획
### 2025.01.19
* 네이버 블로그 포스트를 크롤링한다.
* API로 워드프레스에 임시글로 등록한다.
### 2024.10.04
* 기존 Flow를 Python으로 개발한다.
* 트리거가 발생하면 실행시키는 컨테이너로 빌드한다.
* kubectl create -f file.yaml을 이용하여 1회성 동작 하도록 구현한다.
### Python 개발 순서
## Python 개발 순서
### 2025.01.19
* 현재 DB연동 기능은 없음. 실행시키면 URL을 넣어야동작합니다(완료).
* url을 이용해서 파싱하고 텍스트만 추출하는 기능 구현(완료).
* 마크다운 형태로 추출(완료).
* HTML문서 변환 코드 작성(완료).
* 워드프레스 API를 이용한 임시 포스트 등록(완료).
### 2024.10.04
* DB에서 url을 가져오는 코드작성(완료).
* url을 이용해서 파싱하고 텍스트만 추출하는 기능 구현(완료).
* OpenAI이용 코드 작성(완료)-비용 절감을 위하여 제목, 이미지 생성 제외.
* HTML문서 변환 코드 작성(완료).
* 워드프레스 등록 플로우 코드 작성(완료).
### 코드 리팩토링.
## 코드 리팩토링.
### 2024.10.04
* 전체 리팩토링(완료).
* 모듈화, 패키지화(완료).
## Docker Image Build
2024.10.04 업데이트
### 2024.10.04 업데이트
* Dockerfile 추가(완료).
## Kubernetes manifests
2024.10.04 업데이트
### 2024.10.04 업데이트
* 샘플 템플릿 작성(완료)
* 쿠버네티스 환경 테스트(완료).
---
## 코드 이슈
### 네이버 블로그 크롤링
2024.10.02 기준
* 현재 일반 뉴스 기사는 잘 동작되는 것으로 보임.
* 네이버 블로그는 js이슈로 크롤링이 안되는 것으로 추측. selenium검토 필요.
* 특이사항 없음.
---
## 라이선스
### 라이선스 검토 대상

View File

@ -0,0 +1,37 @@
import requests
from bs4 import BeautifulSoup
def get_naver_blog_content(url):
# 네이버 블로그의 모바일 버전으로 리다이렉트
mobile_url = url.replace("blog.naver.com", "m.blog.naver.com")
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
# HTTP 요청
response = requests.get(mobile_url, headers=headers)
if response.status_code != 200:
print(f"Failed to fetch the page: {response.status_code}")
return None
# BeautifulSoup으로 HTML 파싱
soup = BeautifulSoup(response.text, 'html.parser')
# 본문 추출 (모바일 버전의 본문 클래스 사용)
content = soup.find("div", class_="se-main-container")
if content:
return content.get_text(strip=True)
else:
print("Failed to extract the blog content.")
return None
# 예제 URL
url = "https://blog.naver.com/kte1909/223724132196"
blog_content = get_naver_blog_content(url)
if blog_content:
print("Blog Content:")
print(blog_content)

View File

@ -8,9 +8,10 @@ config = GetConfig()
dict_data = config.get_config_as_dict()
# 2024-10-03 db에서 url정보 호출
# DB없이 url을 직접 넣어서 동작시켜도 가능합니다. - 2025.01.19
print('### Get URL From DB')
db = MariaDB(dict_data)
url = db.fetch_data_from_mariadb()['url']
url = db.fetch_data_from_mariadb()['url'] # 최근 항목 조회. - 2025.01.19
# 2024-10-03 url을 이용해서 text추출
print('### Get content From URL')

78
main_naver_blog_html.py Normal file
View File

@ -0,0 +1,78 @@
import requests
from bs4 import BeautifulSoup
from markdownify import markdownify as md
from package import GetConfig, MariaDB, ChangeTextToPost, WordPress
import markdown
# 현재 DB연동 기능은 없음. 실행시키면 URL을 넣어야동작합니다.
def get_naver_blog_content_as_markdown(url):
# 네이버 블로그의 모바일 버전으로 리다이렉트
mobile_url = url.replace("blog.naver.com", "m.blog.naver.com")
# 웹브라우저 위장 --------------------------------------------------
# 제외 하여도 이상 없이 동작하여 제외.
# headers = {
# "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
# }
# response = requests.get(mobile_url, headers=headers)
# ---------------------------------------------------------------
response = requests.get(mobile_url)
if response.status_code != 200:
print(f"Failed to fetch the page: {response.status_code}")
return None
# BeautifulSoup으로 HTML 파싱
soup = BeautifulSoup(response.text, 'html.parser')
# 본문 추출 (모바일 버전의 본문 클래스 사용)
content = soup.find("div", class_="se-main-container")
if content:
html_content = str(content)
markdown_content = md(html_content) # HTML → Markdown 변환
# 빈 줄 제거
markdown_content = "\n".join([line for line in markdown_content.splitlines() if line.strip()])
return markdown_content
else:
print("Failed to extract the blog content.")
return None
# 2024-10-03 환경 변수 호출
print('### Get values From .env')
config = GetConfig()
dict_data = config.get_config_as_dict()
# 예제 URL
url = input("Enter your blog address : ")
# markdown_content = get_naver_blog_content_as_markdown(url)
post_article = get_naver_blog_content_as_markdown(url)
# if markdown_content:
# print("Markdown Content:")
# print(markdown_content)
# Markdown 파일로 저장
# with open("blog_content.md", "w", encoding="utf-8") as file:
# file.write(markdown_content)
# print("Blog content saved as blog_content.md")
print('### Convert to HTML - markdown to html')
# 2024-10-03 Markdown을 HTML로 변환
html = markdown.markdown(post_article)
# 2024-10-03 워드프레스 포스팅 임시등록
print('### Create post')
wp = WordPress(dict_data)
rs = wp.create_post(2,html)
if __name__ == "__main__":
# print(post_article)
print("추가 확인을 위한 출력")
if rs.ok:
print(f"### 성공 code:{rs.status_code}")
else:
print(f"### 실패 code:{rs.status_code} reason:{rs.reason} msg:{rs.text}")

View File

@ -3,10 +3,13 @@ from dotenv import load_dotenv
# 우선순위: .env.prd > .env.dev > .env
if os.path.exists('.env.prd'):
print("Read ::: .env.prd")
load_dotenv('.env.prd')
elif os.path.exists('.env.dev'):
print("Read ::: .env.dev")
load_dotenv('.env.dev')
else:
print("Read ::: .env")
load_dotenv('.env') # 기본 .env 파일
class GetConfig:

View File

@ -29,7 +29,6 @@ class WordPress():
def __init__(self, dict):
self.wp_url = dict['wp_url']
self.wp_user = dict['wp_user']
self.wp_user = dict['wp_user']
self.wp_api_key = dict['wp_api_key']
def create_post(self, category_id, content, media_id = None, status = "draft", title="파이썬 자동 포스팅"):

View File

@ -3,6 +3,7 @@ anyio==4.6.0
beautifulsoup4==4.12.3
certifi==2024.8.30
charset-normalizer==3.3.2
chromedriver-py==132.0.6834.83
colorama==0.4.6
distro==1.9.0
exceptiongroup==1.2.2
@ -12,12 +13,14 @@ httpx==0.27.2
idna==3.10
jiter==0.5.0
Markdown==3.7
markdownify==0.14.1
mysql-connector-python==9.0.0
openai==1.51.0
pydantic==2.9.2
pydantic_core==2.23.4
python-dotenv==1.0.1
requests==2.32.3
six==1.17.0
sniffio==1.3.1
soupsieve==2.6
tqdm==4.66.5

View File

@ -6,4 +6,4 @@ OPENAI_API_KEY=demo
WP_URL='https://www.example.com'
WP_USER='demo'
WP_API_KEY='demo'
WP_POST_STYLE="문장"
WP_POST_STYLE="문장" # OpenAI에 사용되는것.

2
tempCodeRunnerFile.py Normal file
View File

@ -0,0 +1,2 @@
if rs.ok:

View File

@ -1 +1 @@
0.1.0
0.1.1