Notice
Recent Posts
Recent Comments
Link
250x250
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 탐욕알고리즘
- API
- codingtest
- 백준
- 개발자
- ChatGPT
- 네트워크
- HTTP상태
- 개발
- 알고리즘코딩테스트
- 정렬알고리즘
- SQLP
- 코딩테스트
- 프로그래머스
- JQuery
- 그리디알고리즘
- 하루코딩
- javascript
- 알고리즘
- 파이썬
- SQL
- 챗지피티
- 서버
- 자바
- Spring
- java
- jsp
- Python
- SQLD
- HTTP
Archives
- Today
- Total
개발자's Life
청약 API 이용하여 워드프레스 자동화 게시글 업로드(코드 공유) 본문
728x90
반응형
안녕하세요 로웬입니다!
우선 말씀드리자면 정말 사용했던 코드를 공유드리는거고 조금 더 세분화하고 세련된 코드 작성이 안된 코드인 부분은 너그러이 넘어가주심 감사하겠슴다.
한 1년전쯔음 청약 내용을 가지고 오는 API 와 워드프레스 게시글 업로드 하는 API 를 활용하였고 파이썬 코드를 작성하였습니다.
작성 후 제 개인 서버에 코드 올린 후 crontab 으로 주기적으로 게시글을 올리는 작업을 하였지만 조회수가 얼마 나오지 않아 멈췄었습니다.
(나름 구글 SEO 노출되는 조건을 최대한 맞추려 했는데 안됬던..)
구조는 아래와 같습니다!
LAND_MARKET
- auto_posting_for_land_market.py (실제 실행되는 파이썬)
- home_apply_api_func.py (청약 홈 API)
- hug_api_func.py (HUG API)
- rank-math.php (워드프레스에서 포커스 키워드를 자동으로 잡게 하기 위한 php 코드)
- slack_alert.py (슬랙 API 를 이용하여 게시글 등록 후 메세지 전달)
- wordpress_article_func.py (청약홈, HUG 순서대로 API 호출하여 게시글 작성)
*DB 나 공통 함수로 사용할 수 있는건 환경설정 파일이나 따로 파이썬 파일을 두고 사용하시는걸 추천드립니다*
home_apply_api_func.py
import requests
import time
import math
import pymysql
from bs4 import BeautifulSoup
from wordpress_article_func import create_article_to_wordpress
from hug_api_func import double_meter_price_each_area_table_html, double_meter_price_each_size_html, new_distribution_cnt_html
from datetime import date, timedelta
# 기본 header
HEADER = {
"Accept": "*/*",
'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
# 청약홈/공공데이터 분양정보 KEY
APPLY_HOME_KEY = "YOUR_API_KEY"
# 청약홈 API 기본 URL
APPLY_HOME_BASE_URL = "https://api.odcloud.kr/api"
# 1개월 이전 날짜
last_date = date.today() - timedelta(days=10)
# APT 무순위/잔여세대 분양정보 API 함수
def apt_no_rank_api():
# 주택관리번호, 공고번호, 주택구분코드, 모집공고일 값을 이용하여 APT 무순위/잔여세대 분양정보의 상세 정보를 제공
API_URL = "/ApplyhomeInfoDetailSvc/v1/getRemndrLttotPblancDetail"
# 호출 URL
REQUEST_URL = APPLY_HOME_BASE_URL + API_URL
RESPONSE_INFO = {
"BSNS_MBY_NM": "사업주체명(시행사)",
"CNTRCT_CNCLS_BGNDE": "계약 시작일",
"CNTRCT_CNCLS_ENDDE": "계약 종료일",
"GNRL_RCEPT_BGNDE": "일반공급접수 시작일",
"GNRL_RCEPT_ENDDE": "일반공급접수 종료일",
"HMPG_ADRES": "홈페이지주소",
"HOUSE_MANAGE_NO": "주택관리번호",
"HOUSE_NM": "주택명",
"HOUSE_SECD": "주택구분코드",
"HOUSE_SECD_NM": "주택구분코드명",
"HSSPLY_ADRES": "주소",
"HSSPLY_ZIP": "우편번호",
"MDHS_TELNO": "문의처",
"MVN_PREARNGE_YM": "입주예정월",
"PBLANC_NO": "공고번호",
"PBLANC_URL": "공고문 바로가기",
"PRZWNER_PRESNATN_DE": "당첨자 발표일",
"RCRIT_PBLANC_DE": "모집공고일",
"SPSPLY_RCEPT_BGNDE": "특별공급 접수 시작일",
"SPSPLY_RCEPT_ENDDE": "특별공급 접수 종료일",
"SUBSCRPT_RCEPT_BGNDE": "청약접수 시작일",
"SUBSCRPT_RCEPT_ENDDE": "청약접수 종료일",
"TOT_SUPLY_HSHLDCO": "모집 세대수"
}
# Page 정보 설정
PAGE = 1
PER_PAGE = 50
# 오늘 날짜 기준 1달전 모집공고 정보 API URL
FULL_URL = f"{REQUEST_URL}?page={PAGE}&perPage={PER_PAGE}&serviceKey={APPLY_HOME_KEY}&cond%5BRCRIT_PBLANC_DE%3A%3AGTE%5D={last_date}"
article_summary_html = ""
article_list = []
# 총 게시글 개수를 위해 API 콜
response = requests.get(url=FULL_URL, headers=HEADER)
if response.status_code == 200:
# 공고 총 개수
match_cnt = response.json()["matchCount"]
# 공고 있을 경우
if match_cnt > 0:
#마지막 페이지 넘버
LAST_PAGE = math.ceil(match_cnt / PER_PAGE)
# 페이지 별 게시글 FOR 문 실행
for i in range(1, LAST_PAGE + 1):
FULL_URL = f"{REQUEST_URL}?page={i}&perPage={PER_PAGE}&serviceKey={APPLY_HOME_KEY}&cond%5BRCRIT_PBLANC_DE%3A%3AGTE%5D={last_date}"
response = requests.get(url=FULL_URL, headers=HEADER)
# return 값
apt_json = {
"status" : ""
}
if response.status_code == 200:
apt_json["status"] = "SUCCESS"
apt_json["data"] = response.json()
for data in apt_json["data"]["data"]:
# 공고번호가 이미 게시한 글인지 확인
# 이미 사용한 키워드 정보 가져오기
conn = pymysql.connect(host='YOUR_DB_HOST', user='YOUR_DB_USER', password='YOUR_DB_PASSWORD', db='WORDPRESS', charset='utf8')
sql_select = "SELECT COUNT(*) FROM WORDPRESS.AH_ARTICLE_LIST WHERE pblanc_no = %s"
with conn:
with conn.cursor() as cur:
cur.execute(sql_select, data["PBLANC_NO"])
article_cnt = cur.fetchall()[0][0]
# 등록된 게시글이 없을경우 게시글 셋팅
if article_cnt == 0:
article_info = {
RESPONSE_INFO["BSNS_MBY_NM"]: data["BSNS_MBY_NM"],
RESPONSE_INFO["CNTRCT_CNCLS_BGNDE"]: data["CNTRCT_CNCLS_BGNDE"],
RESPONSE_INFO["CNTRCT_CNCLS_ENDDE"]: data["CNTRCT_CNCLS_ENDDE"],
RESPONSE_INFO["GNRL_RCEPT_BGNDE"]: data["GNRL_RCEPT_BGNDE"],
RESPONSE_INFO["GNRL_RCEPT_ENDDE"]: data["GNRL_RCEPT_ENDDE"],
RESPONSE_INFO["HMPG_ADRES"]: data["HMPG_ADRES"],
RESPONSE_INFO["HOUSE_MANAGE_NO"]: data["HOUSE_MANAGE_NO"],
RESPONSE_INFO["HOUSE_NM"]: data["HOUSE_NM"],
RESPONSE_INFO["HOUSE_SECD"]: data["HOUSE_SECD"],
RESPONSE_INFO["HOUSE_SECD_NM"]: data["HOUSE_SECD_NM"],
RESPONSE_INFO["HSSPLY_ADRES"]: data["HSSPLY_ADRES"],
RESPONSE_INFO["HSSPLY_ZIP"]: data["HSSPLY_ZIP"],
RESPONSE_INFO["MDHS_TELNO"]: data["MDHS_TELNO"],
RESPONSE_INFO["MVN_PREARNGE_YM"]: data["MVN_PREARNGE_YM"],
RESPONSE_INFO["PBLANC_NO"]: data["PBLANC_NO"],
RESPONSE_INFO["PBLANC_URL"]: data["PBLANC_URL"],
RESPONSE_INFO["PRZWNER_PRESNATN_DE"]: data["PRZWNER_PRESNATN_DE"],
RESPONSE_INFO["RCRIT_PBLANC_DE"]: data["RCRIT_PBLANC_DE"],
RESPONSE_INFO["SPSPLY_RCEPT_BGNDE"]: data["SPSPLY_RCEPT_BGNDE"],
RESPONSE_INFO["SPSPLY_RCEPT_ENDDE"]: data["SPSPLY_RCEPT_ENDDE"],
RESPONSE_INFO["SUBSCRPT_RCEPT_BGNDE"]: data["SUBSCRPT_RCEPT_BGNDE"],
RESPONSE_INFO["SUBSCRPT_RCEPT_ENDDE"]: data["SUBSCRPT_RCEPT_ENDDE"],
RESPONSE_INFO["TOT_SUPLY_HSHLDCO"]: data["TOT_SUPLY_HSHLDCO"]
}
article_list.append(article_info)
if len(article_list) == 1:
break
time.sleep(1)
# 게시글 HTML 형태로 작성
article_summary_html = ""
# 게시글 작성
for article in article_list:
public_url_response = requests.get(url=article["공고문 바로가기"], headers=HEADER)
home_apply_public_html = BeautifulSoup(public_url_response.content, 'html.parser')
html = first_comment_html(article)
html += str(home_apply_public_html.select_one("#printArea"))
sub_html = sub_info_html_list(article["주소"], article["주소"])
html += sub_html
result = create_article_to_wordpress(article["주택명"] + " 분양정보", html)
if result == "SUCESS":
conn = pymysql.connect(host='YOUR_DB_HOST', user='YOUR_DB_USER', password='YOUR_DB_PASSWORD', db='WORDPRESS', charset='utf8')
sql = "INSERT INTO WORDPRESS.AH_ARTICLE_LIST (article_title, pblanc_no, article_type) VALUES (%s, %s, %s)"
with conn:
with conn.cursor() as cur:
cur.execute(sql, (article["주택명"], article["공고번호"], "100-001"))
conn.commit()
sql_update = "UPDATE WORDPRESS.COM_CODE SET common_name = 'apt_detail_api' WHERE common_code = %s"
conn = pymysql.connect(host='YOUR_DB_HOST', user='YOUR_DB_USER', password='YOUR_DB_PASSWORD', db='WORDPRESS', charset='utf8')
with conn:
with conn.cursor() as cur:
cur.execute(sql_update, "101-001")
conn.commit()
return article_summary_html
def apt_detail_api():
# 주택관리번호, 공고번호, 주택구분코드, 모집공고일 값을 이용하여 APT 무순위/잔여세대 분양정보의 상세 정보를 제공
API_URL = "/ApplyhomeInfoDetailSvc/v1/getAPTLttotPblancDetail"
# 호출 URL
REQUEST_URL = APPLY_HOME_BASE_URL + API_URL
RESPONSE_INFO = {
"HOUSE_MANAGE_NO": "주택관리번호",
"PBLANC_NO": "공고번호",
"HOUSE_NM": "주택명",
"HOUSE_SECD": "주택구분코드",
"HOUSE_SECD_NM": "주택구분코드명",
"HOUSE_DTL_SECD": "주택상세구분코드",
"HOUSE_DTL_SECD_NM": "주택상세구분코드명",
"RENT_SECD": "분양구분코드",
"RENT_SECD_NM": "분양구분코드명",
"SUBSCRPT_AREA_CODE": "공급지역코드",
"SUBSCRPT_AREA_CODE_NM": "공급지역명",
"HSSPLY_ZIP": "공급위치 우편번호",
"HSSPLY_ADRES": "공급위치",
"TOT_SUPLY_HSHLDCO": "공급규모",
"RCRIT_PBLANC_DE": "모집공고일",
"RCEPT_BGNDE": "청약접수시작일",
"PBLANC_URL": "공고문 바로가기",
"RCEPT_ENDDE": "청약접수종료일",
"SPSPLY_RCEPT_BGNDE": "특별공급 접수시작일",
"SPSPLY_RCEPT_ENDDE": "특별공급 접수종료일",
"GNRL_RNK1_CRSPAREA_RCPTDE": "1 순위 해당지역 접수시작일",
"GNRL_RNK1_CRSPAREA_ENDDE": "1 순위 해당지역 접수종료일",
"GNRL_RNK1_ETC_GG_RCPTDE": "1 순위 경기지역 접수시작일",
"GNRL_RNK1_ETC_GG_ENDDE": "1 순위 경기지역 접수종료일",
"GNRL_RNK1_ETC_AREA_RCPTDE": "1 순위 기타지역 접수시작일",
"GNRL_RNK1_ETC_AREA_ENDDE": "1 순위 기타지역 접수종료일"
}
# Page 정보 설정
PAGE = 1
PER_PAGE = 50
# 오늘 날짜 기준 1달전 모집공고 정보 API URL
FULL_URL = f"{REQUEST_URL}?page={PAGE}&perPage={PER_PAGE}&serviceKey={APPLY_HOME_KEY}&cond%5BRCRIT_PBLANC_DE%3A%3AGTE%5D={last_date}"
article_summary_html = ""
article_list = []
# 총 게시글 개수를 위해 API 콜
response = requests.get(url=FULL_URL, headers=HEADER)
if response.status_code == 200:
# 공고 총 개수
match_cnt = response.json()["matchCount"]
# 공고 있을 경우
if match_cnt > 0:
#마지막 페이지 넘버
LAST_PAGE = math.ceil(match_cnt / PER_PAGE)
# 페이지 별 게시글 FOR 문 실행
for i in range(1, LAST_PAGE + 1):
FULL_URL = f"{REQUEST_URL}?page={i}&perPage={PER_PAGE}&serviceKey={APPLY_HOME_KEY}&cond%5BRCRIT_PBLANC_DE%3A%3AGTE%5D={last_date}"
response = requests.get(url=FULL_URL, headers=HEADER)
# return 값
apt_json = {
"status" : ""
}
if response.status_code == 200:
apt_json["status"] = "SUCCESS"
apt_json["data"] = response.json()
for data in apt_json["data"]["data"]:
# 공고번호가 이미 게시한 글인지 확인
# 이미 사용한 키워드 정보 가져오기
conn = pymysql.connect(host='YOUR_DB_HOST', user='YOUR_DB_USER', password='YOUR_DB_PASSWORD', db='WORDPRESS', charset='utf8')
sql_select = "SELECT COUNT(*) FROM WORDPRESS.AH_ARTICLE_LIST WHERE pblanc_no = %s"
with conn:
with conn.cursor() as cur:
cur.execute(sql_select, data["PBLANC_NO"])
article_cnt = cur.fetchall()[0][0]
# 등록된 게시글이 없을경우 게시글 셋팅
if article_cnt == 0:
article_info = {
RESPONSE_INFO["HOUSE_MANAGE_NO"]: data["HOUSE_MANAGE_NO"],
RESPONSE_INFO["PBLANC_NO"]: data["PBLANC_NO"],
RESPONSE_INFO["HOUSE_NM"]: data["HOUSE_NM"],
RESPONSE_INFO["HOUSE_SECD"]: data["HOUSE_SECD"],
RESPONSE_INFO["HOUSE_SECD_NM"]: data["HOUSE_SECD_NM"],
RESPONSE_INFO["HOUSE_DTL_SECD"]: data["HOUSE_DTL_SECD"],
RESPONSE_INFO["HOUSE_DTL_SECD_NM"]: data["HOUSE_DTL_SECD_NM"],
RESPONSE_INFO["RENT_SECD"]: data["RENT_SECD"],
RESPONSE_INFO["RENT_SECD_NM"]: data["RENT_SECD_NM"],
RESPONSE_INFO["SUBSCRPT_AREA_CODE"]: data["SUBSCRPT_AREA_CODE"],
RESPONSE_INFO["SUBSCRPT_AREA_CODE_NM"]: data["SUBSCRPT_AREA_CODE_NM"],
RESPONSE_INFO["HSSPLY_ZIP"]: data["HSSPLY_ZIP"],
RESPONSE_INFO["PBLANC_URL"]: data["PBLANC_URL"],
RESPONSE_INFO["HSSPLY_ADRES"]: data["HSSPLY_ADRES"],
RESPONSE_INFO["TOT_SUPLY_HSHLDCO"]: data["TOT_SUPLY_HSHLDCO"],
RESPONSE_INFO["RCRIT_PBLANC_DE"]: data["RCRIT_PBLANC_DE"],
RESPONSE_INFO["RCEPT_BGNDE"]: data["RCEPT_BGNDE"],
RESPONSE_INFO["RCEPT_ENDDE"]: data["RCEPT_ENDDE"],
RESPONSE_INFO["SPSPLY_RCEPT_BGNDE"]: data["SPSPLY_RCEPT_BGNDE"],
RESPONSE_INFO["SPSPLY_RCEPT_ENDDE"]: data["SPSPLY_RCEPT_ENDDE"],
RESPONSE_INFO["GNRL_RNK1_CRSPAREA_RCPTDE"]: data["GNRL_RNK1_CRSPAREA_RCPTDE"],
RESPONSE_INFO["GNRL_RNK1_CRSPAREA_ENDDE"]: data["GNRL_RNK1_CRSPAREA_ENDDE"],
RESPONSE_INFO["GNRL_RNK1_ETC_GG_RCPTDE"]: data["GNRL_RNK1_ETC_GG_RCPTDE"],
RESPONSE_INFO["GNRL_RNK1_ETC_GG_ENDDE"]: data["GNRL_RNK1_ETC_GG_ENDDE"],
RESPONSE_INFO["GNRL_RNK1_ETC_AREA_RCPTDE"]: data["GNRL_RNK1_ETC_AREA_RCPTDE"],
RESPONSE_INFO["GNRL_RNK1_ETC_AREA_ENDDE"]: data["GNRL_RNK1_ETC_AREA_ENDDE"]
}
article_list.append(article_info)
if len(article_list) == 1:
break
time.sleep(1)
# 게시글 작성
for article in article_list:
public_url_response = requests.get(url=article["공고문 바로가기"], headers=HEADER)
home_apply_public_html = BeautifulSoup(public_url_response.content, 'html.parser')
html = first_comment_html(article)
html += str(home_apply_public_html.select_one("#printArea"))
sub_html = sub_info_html_list(article["공급지역명"], article["공급위치"])
html += sub_html
result = create_article_to_wordpress(article["주택명"] + " 분양정보", html)
if result == "SUCESS":
conn = pymysql.connect(host='YOUR_DB_HOST', user='YOUR_DB_USER', password='YOUR_DB_PASSWORD', db='WORDPRESS', charset='utf8')
sql = "INSERT INTO WORDPRESS.AH_ARTICLE_LIST (article_title, pblanc_no, article_type) VALUES (%s, %s, %s)"
with conn:
with conn.cursor() as cur:
cur.execute(sql, (article["주택명"], article["공고번호"], "100-001"))
conn.commit()
sql_update = "UPDATE WORDPRESS.COM_CODE SET common_name = 'apt_no_rank_api' WHERE common_code = %s"
conn = pymysql.connect(host='YOUR_DB_HOST', user='YOUR_DB_USER', password='YOUR_DB_PASSWORD', db='WORDPRESS', charset='utf8')
with conn:
with conn.cursor() as cur:
cur.execute(sql_update, "101-001")
conn.commit()
def first_comment_html(article):
address = article.get("주소") or article.get("공급위치")
apt_name = article["주택명"]
collect_date = article["모집공고일"]
apply_start_date = article.get("청약접수시작일") or article.get("청약접수 시작일")
apply_end_date = article.get("청약접수종료일") or article.get("청약접수 종료일")
first_comment_html = f'<div id="first_comment_area"><span>이번에 소개드릴 분양정보는 <span>{address}</span>에 위치한 <span>{apt_name}</span> 입니다. <br> 모집공고일은 <span>{collect_date}</span> 이고 청약 접수는 <span>{apply_start_date} ~ {apply_end_date}</span> 입니다. <br> <p>해당 내용 참고 부탁드리고 자세한 내용은 아래에서 확인하실 수 있습니다!<p></span></div>'
first_comment_html += f"""
<span id="sub_comment">
<span style="color:red">단지의 위치, 교통 편의성, 주변 환경, 교육 여건, 생활 인프라</span> 등을 꼼꼼히 살펴보는 것이 중요합니다. 이 외에도 <span style="color:red;">분양가, 계약 조건, 입주 시기 </span>등을 미리 확인하여 자신의 재정 상황과 생활 계획에 맞는 선택을 해야 합니다.
<span style="color:blue;">모집공고일, 청약 접수일, 당첨자 발표일, 계약일 </span>등을 미리 체크하여 일정에 맞춰 준비해야 합니다.
{apt_name}뿐만 아니라 다른 분양 아파트도 동일하게 이러한 요소들을 검토하며 분양을 고려하는 모두에게 도움이 되길 바라며, 모집공고문을 참조하시기 바랍니다.
</span>
"""
return first_comment_html
def sub_info_html_list(area_name, address):
html = ""
dobule_meter_price_html = double_meter_price_each_area_table_html(area_name)
dobule_meter_each_size_html = double_meter_price_each_size_html(area_name)
new_distribution_html = new_distribution_cnt_html(area_name)
html += dobule_meter_price_html
html += dobule_meter_each_size_html
html += new_distribution_html
html += f"<div id='go_map_div'><a id='go_map' href='https://map.kakao.com/link/search/{address}'>KAKAO MAP 위치보기</a></div>"
return html
def price_sale_each_month():
html = ""
page = 9
perPage = 1000
SUB_URL = f"/15061057/v1/uddi:09916f8a-3cfa-4c9f-8b04-e49969ae839d?page={page}&perPage={perPage}&serviceKey={APPLY_HOME_KEY}"
FULL_URL = APPLY_HOME_BASE_URL + SUB_URL
response = requests.get(url=FULL_URL, headers=HEADER)
if response.status_code == 200:
print(response.json())
hug_api_func.py
import requests
import json
import xmltodict
from datetime import datetime, timedelta
# 기본 header
HEADER = {
"Accept": "*/*",
'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
BASE_URL = "https://www.khug.or.kr"
area_code = {
"서울":"01",
"부산":"02",
"대구":"03",
"인천":"04",
"광주":"05",
"대전":"06",
"경기":"07",
"강원":"08",
"충북":"09",
"충남":"10",
"전북":"11",
"전남":"12",
"경북":"13",
"경남":"14",
"제주":"15",
"울산":"16",
"세종":"17"
}
area_full_name_code = {
"서울":"01",
"부산":"02",
"대구":"03",
"인천":"04",
"광주":"05",
"대전":"06",
"경기":"07",
"강원":"08",
"충청북도":"09",
"충청남도":"10",
"전라북도":"11",
"전라남도":"12",
"경상북도":"13",
"경상남도":"14",
"제주":"15",
"울산":"16",
"세종":"17"
}
def double_meter_price_each_area_table_html(area_name):
# 포함된 키와 값을 찾기
included_key = next((key for key in area_code if key in area_name), None)
table_html = ""
area_code_temp = area_code
if not included_key:
included_key = next((key for key in area_full_name_code if key in area_name), None)
area_code_temp = area_full_name_code
if included_key:
HUG_API_KEY = "YOUR_HUG_API_KEY_1"
a=datetime.now()-timedelta(days=365)
START_YYM = str(a.strftime('%Y-%m')).replace("-", "")
END_YYM = str(datetime.now().strftime('%Y-%m')).replace("-", "")
SUB_URL = f"/priceDistributedPrice3dot3.do?API_KEY={HUG_API_KEY}&START_YYM={START_YYM}&END_YYM={END_YYM}&AREA_DCD={area_code_temp[included_key]}"
FULL_URL = BASE_URL + SUB_URL
response = requests.get(url=FULL_URL, headers=HEADER)
if response.status_code == 200:
xpars = xmltodict.parse(response.text)
jsonDump = json.dumps(xpars)
jsonBody = json.loads(jsonDump)
double_meter_info = jsonBody["response"]["body"]["items"]["item"]
area_name = included_key
table_html = f"<h5 class='sub_sub_tit mt_30'>지역별 ㎡당 분양가격</h5>"
table_html += "<table class='tbl_st tbl_row tbl_col tbl_center'>"
table_html += "<tr>"
table_html += "<th>지역</th>"
table_html += "<th>연월</th>"
table_html += "<th>가격</th>"
table_html += "</tr>"
for info in double_meter_info:
year_mm = info["YEAR_MM"]
year_mm =year_mm[0:4]+'-'+year_mm[4:]
price = "-"
print(info["YEAR_VAL"])
if info["YEAR_VAL"] != None:
price = format(int(info["YEAR_VAL"]), ',d')
table_html += "<tr>"
table_html += f"<td>{area_name}</td>"
table_html += f"<td>{year_mm}</td>"
table_html += f"<td>{price}</td>"
table_html += "</tr>"
table_html += "</table>"
return table_html
def double_meter_price_each_size_html(area_name):
# 포함된 키와 값을 찾기
included_key = next((key for key in area_code if key in area_name), None)
table_html = ""
area_code_temp = area_code
if not included_key:
included_key = next((key for key in area_full_name_code if key in area_name), None)
area_code_temp = area_full_name_code
if included_key:
HUG_API_KEY = "YOUR_HUG_API_KEY_2"
a=datetime.now()-timedelta(days=365)
START_YYM = str(a.strftime('%Y-%m')).replace("-", "")
END_YYM = str(datetime.now().strftime('%Y-%m')).replace("-", "")
SUB_URL = f"/distributedBySize.do?API_KEY={HUG_API_KEY}&START_YYM={START_YYM}&END_YYM={END_YYM}&AREA_DCD={area_code_temp[included_key]}"
FULL_URL = BASE_URL + SUB_URL
response = requests.get(url=FULL_URL, headers=HEADER)
table_html = ""
if response.status_code == 200:
xpars = xmltodict.parse(response.text)
jsonDump = json.dumps(xpars)
jsonBody = json.loads(jsonDump)
area_name = included_key
if jsonBody["response"]["body"] is not None:
double_meter_info = jsonBody["response"]["body"]["items"]["item"]
table_html += f"<h5 class='sub_sub_tit mt_30'>규모별 ㎡당 분양가격 - {area_name}</h5>"
table_html += "<table class='tbl_st tbl_row tbl_col tbl_center'>"
table_html += "<tr>"
table_html += "<th>연월</th>"
table_html += "<th>전용면적 60㎡ 이하</th>"
table_html += "<th>전용면적 60㎡초과 85㎡이하</th>"
table_html += "<th>전용면적 85㎡초과 102㎡이하</th>"
table_html += "<th>전용면적 102㎡초과</th>"
table_html += "</tr>"
for info in double_meter_info:
year_mm = info["YEAR_MM"]
year_mm =year_mm[0:4]+'-'+year_mm[4:]
below60 = int(info["BELOW60"])
below85 = int(info["BELOW85"])
below102 = int(info["BELOW102"])
excess102 = int(info["EXCESS102"])
table_html += "<tr>"
table_html += f"<td>{year_mm}</td>"
table_html += f"<td>{format(below60, ',d')}</td>"
table_html += f"<td>{format(below85, ',d')}</td>"
table_html += f"<td>{format(below102, ',d')}</td>"
table_html += f"<td>{format(excess102, ',d')}</td>"
table_html += "</tr>"
table_html += "</table>"
return table_html
def new_distribution_cnt_html(area_name):
# 포함된 키와 값을 찾기
included_key = next((key for key in area_code if key in area_name), None)
table_html = ""
area_code_temp = area_code
if not included_key:
included_key = next((key for key in area_full_name_code if key in area_name), None)
area_code_temp = area_full_name_code
if included_key:
HUG_API_KEY = "YOUR_HUG_API_KEY_3"
a=datetime.now()-timedelta(days=365)
START_YYM = str(a.strftime('%Y-%m')).replace("-", "")
END_YYM = str(datetime.now().strftime('%Y-%m')).replace("-", "")
SUB_URL = f"/newDistributionNumber.do?API_KEY={HUG_API_KEY}&START_YYM={START_YYM}&END_YYM={END_YYM}&AREA_DCD={area_code_temp[included_key]}"
FULL_URL = BASE_URL + SUB_URL
response = requests.get(url=FULL_URL, headers=HEADER)
if response.status_code == 200:
xpars = xmltodict.parse(response.text)
jsonDump = json.dumps(xpars)
jsonBody = json.loads(jsonDump)
double_meter_info = jsonBody["response"]["body"]["items"]["item"]
area_name = included_key
table_html = f"<h5 class='sub_sub_tit mt_30'>신규 분양세대수</h5>"
table_html += "<table class='tbl_st tbl_row tbl_col tbl_center'>"
table_html += "<tr>"
table_html += "<th>지역</th>"
table_html += "<th>연월</th>"
table_html += "<th>세대수</th>"
table_html += "</tr>"
for info in double_meter_info:
year_mm = info["YEAR_MM"]
year_mm =year_mm[0:4]+'-'+year_mm[4:]
new_distribution_cnt = info["YEAR_VAL"]
table_html += "<tr>"
table_html += f"<td>{area_name}</td>"
table_html += f"<td>{year_mm}</td>"
table_html += f"<td>{new_distribution_cnt}</td>"
table_html += "</tr>"
table_html += "</table>"
return table_html
slack_alert.py
import requests
# Slack Webhook URL
SLACK_WEBHOOK_URL = 'YOUR_SLACK_WEBHOOK_URL'
def SendMessage(msg, title='myAutobot'):
try:
# 메시지 전송
requests.post(
SLACK_WEBHOOK_URL,
headers={ # 'header'가 아닌 'headers'로 수정
'content-type': 'application/json'
},
json={
'text': title,
'blocks': [
{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': msg
}
}
]
}
)
except Exception as ex:
print(ex)
wordpress_article_func.py (해당 부분에는 구글 인덱스 잡는 코드도 있는 부분 참고!)
import json
import requests
from urllib.parse import urljoin
from slack_alert import SendMessage
import random
from oauth2client.service_account import ServiceAccountCredentials
import httplib2
from PIL import Image, ImageDraw, ImageFont
import textwrap
import random
import os
def run(file_path, file_name, astr):
para = textwrap.wrap(astr, width=11)
MAX_W, MAX_H = 480, 480
bg_color = 'rgb(214, 230, 245)'
im = Image.new('RGB', (MAX_W, MAX_H), bg_color)
draw = ImageDraw.Draw(im)
current_dir = os.path.dirname(os.path.abspath(__file__))
font_path = os.path.join(current_dir, "font", "NanumSquareRoundB.ttf")
font = ImageFont.truetype(font_path, size=46)
font_color = 'rgb(0, 0, 0)'
current_h, pad = 160, 10
for line in para:
_, _, w, h = draw.textbbox((0, 0), text=line, font=font)
draw.text(((MAX_W - w) / 2, current_h), line, font=font, fill=font_color)
current_h += h + pad
im.save(f'{file_path}')
# 워드프레스 기본 정보
WP_URL = 'YOUR_WORDPRESS_URL' # 자신의 워드프레스 주소
WP_USERNAME = 'YOUR_WP_USERNAME' # 워드프레스 사용자이름
WP_PASSWORD = 'YOUR_WP_APPLICATION_PASSWORD' # 어플리케이션 비밀번호
status = 'publish' # 즉시발행:publish, 임시저장:draft
tag_ids = [1] # 태그아이디도 카테고리 아이디 찾는 방법과 동일 --> TODO: DB 로 코드 관리 필요
category_ids = [1] # 카테고리 아이디는 글/카테고리/ 해당카테고리에 커서를 가져가면 하다나에 카테고리 아이디값이 나온다. 숫자다 --> TODO: DB 로 코드 관리 필요
res_from_wordpress = requests.get(urljoin(WP_URL, "/wp-json/wp/v2/posts"),
headers={'Content-type': "application/json"},
auth=(WP_USERNAME, WP_PASSWORD))
title_list = []
def create_article_to_wordpress(title, article_content):
title_list.append(f'{title} 놓치지 말아야 할 주요 포인트')
title_list.append(f'이번 달 놓칠 수 없는 분양 아파트: {title}')
title_list.append(f'분양 신청 전 필독! {title} 청약 관련 모든 정보')
title_list.append(f'{title}의 모든것')
title_list.append(f'{title} 분양과 함께하는 내 집 마련의 꿈')
title_list.append(f'{title} 분양 시작, 일정 및 상세한 정보 확인')
random_num = random.randint(0, 5)
result = ""
wp_title = title_list[random_num]
slug = title
indexing_url = f'{WP_URL}/{slug}'
post_list = []
article_content += ' <div id="article_footer_coment">'
article_content += ' 출처: 청약홈, 주택도시보증공사 '
article_content += ' </div><br><br>'
article_content += ' <div id="another_aritcle_area">'
article_content += ' <h3 id="another_aritcle_area_title">LAND MARKET 의 분양정보</h3>'
# 랜드마켓 홈페이지에 있는 게시글 랜덤 3개
for j in range(0, 3):
num = 0
while num in post_list :
num = random.randrange(0, len(res_from_wordpress.json()))
post_list.append(num)
article_content += '<a href="' + res_from_wordpress.json()[num]['link'] + '">' + res_from_wordpress.json()[num]['title']['rendered'] + '</a><br>'
article_content += '</div>'
content = article_content
current_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_dir, "thumb_img", f"{title}.png")
file_name = f"{title}.png"
run(file_path, file_name, f"{title}")
# 저장된 파일 업로드할 이미지 셋팅
url = urljoin(WP_URL, '/wp-json/wp/v2/media/')
f = open(file_path, 'rb')
image_data = f.read()
f.close()
espSequence = bytes(file_name, "utf-8").decode("unicode_escape")
headers = {
'Content-Type': 'image/png',
'Content-Disposition': 'attachment; filename=%s' % espSequence,
}
res2 = requests.post(
url,
data=image_data,
headers=headers,
auth=(WP_USERNAME, WP_PASSWORD),
)
media_info = res2.json()
media_id = media_info['id']
payload = {"status": status,
"slug": slug,
"title": wp_title,
"content": content,
"categories": category_ids,
"tags": tag_ids,
}
# 이미지 있을 경우 이미지 정보도 삽입
if media_id is not None:
payload['featured_media'] = media_id
res = requests.post(urljoin(WP_URL, "/wp-json/wp/v2/posts"),
data=json.dumps(payload),
headers={'Content-type': "application/json"},
auth=(WP_USERNAME, WP_PASSWORD))
if res.ok:
print(f'''성공 code:{res.status_code}
{wp_title}
{WP_URL}
{slug}
{category_ids}
{tag_ids}
''')
SendMessage(f"분양정보 게시글 등록완료 : {wp_title}")
# 구글 인덱스 요청 API
# TODO : 경로 변경 후 정상적으로 GA 인덱스 콜 하는지 확인
# JSON_KEY_FILE = "YOUR_GOOGLE_API_CREDENTIALS_PATH"
# SCOPES = [ "https://www.googleapis.com/auth/indexing" ]
# ENDPOINT = "https://indexing.googleapis.com/v3/urlNotifications:publish"
# # Authorize credentials
# credentials = ServiceAccountCredentials.from_json_keyfile_name(JSON_KEY_FILE, scopes=SCOPES)
# http = credentials.authorize(httplib2.Http())
# # Build the request body
# content = {}
# content['url'] = indexing_url
# content['type'] = "URL_UPDATED"
# json_content = json.dumps(content)
# response, content = http.request(ENDPOINT, method="POST", body=json_content)
# result = json.loads(content.decode())
result = "SUCESS"
else:
print(f"실패 code:{res.status_code} reason:{res.reason} msg:{res.text}")
result = "FAIL"
return result
위 코드 공유 드리고 참고하여 자동화 게시글 코드 구현해보면 나름 좋은 경험이라고 생각합니다!
개발자들 화이팅
728x90
Comments