2026/02/22

오늘의 이야기

앱에서 지원하고 싶은 것중 우선 나의 주변에 버스 정류소를 찾는다. 어떻게 찾을까 ?   모든 데이터는 data.go.kr 공공데이터 포털을 중심으로 ... 찾아보니 제주도에서 제공하는 버스 정보가 있다.


 


http://www.jeju.go.kr/help/open.htm?page=3&act=view&seq=967654 


다만, 가이드의 정보를 기준으로 보면 http:// 으로 시작하는 기본url 과 xml 형식으로 자료를 전송한다는 것이 조금 예전 방식인 것 같은 생각이 들었다.  


 


이제 앱에 retrofit 통신을 하기 위한 준비를 해 보자.  gradle 파일에 수정을 


    // 데이터 주고 받기
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-simplexml:2.1.0'

retrofit 과 xml 파싱을 위해서 추가 했다.


 


다음은 manifest 에 internet 접속을 위한 권한 등록


 


    <uses-permission android:name="android.permission.INTERNET" />

이제 준비는 되었고.  그럼 데이터를 가져오기 위해서 일단 open api 가 제공하는 데이터 구조를 확인해 보아야겠다.


 


xml 샘플


xml 마지막 부분



데이터는 이렇게 조회가 되고 있고, open api 가이드의 내용도 이와 같다.  그래서 일단은 데이터를 받아올 class 을 만들어 보았다. 


 


맨 먼저 제일 바깥쪽에 구성되는 class 부터


import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;


@Root(name="response", strict = false)
public class StationBean {
@Element(name="header")
HeaderClass headerClass;
@Element(name="body")
BodyClass bodyClass ;

public HeaderClass getHeaderClass() {
return headerClass;
}

public BodyClass getBodyClass() {
return bodyClass;
}

public void setHeaderClass(HeaderClass headerClass) {
this.headerClass = headerClass;
}

public void setBodyClass(BodyClass bodyClass) {
this.bodyClass = bodyClass;
}
}

Root 는 response 로 구성 되며, 그 안에는 header 와 body 가 들어간다. 


다음은 header class


import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name="header", strict = false)
public class HeaderClass {
@Element(name="resultCode")
String resultCode;
@Element(name="resultMsg")
String resultMsg ;

public String getResultCode() {
return resultCode;
}

public String getResultMsg() {
return resultMsg;
}

public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}

public void setResultMsg(String resultMsg) {
this.resultMsg = resultMsg;
}
}

header 에는 resultCode, 와 resultMsg 만 들어 있고, 실제 데이터는 body 에 들어간다.  다음은 body class


import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;

import java.util.ArrayList;

@Root(name="body", strict = false)
public class BodyClass {
@ElementList(entry = "items")
ArrayList<ItemClass> items ;
@Element(name="numOfRows")
String numOfRows ;
@Element(name="pageNo")
String pageNo ;
@Element(name="totalCount")
String totalCount ;

public ArrayList<ItemClass> getItems() {
return items;
}

public String getNumOfRows() {
return numOfRows;
}

public String getPageNo() {
return pageNo;
}

public String getTotalCount() {
return totalCount;
}

public void setItems(ArrayList<ItemClass> items) {
this.items = items;
}

public void setNumOfRows(String numOfRows) {
this.numOfRows = numOfRows;
}

public void setPageNo(String pageNo) {
this.pageNo = pageNo;
}

public void setTotalCount(String totalCount) {
this.totalCount = totalCount;
}
}

body 에는 데이터가 들어가는 items 와 건수등을 표시하는 데이터 들이 들어 있는데, 구현하면서 조금 방황(?)한 부분은 ArrayList 로 표시하는 items 에 대한 구현을 어떻게 해야 하는 가에 대한 부분 이었다.  gson 으로 파싱을 할 때는 그런거 없이 수월했는데, xml 형식에서는 EntryList 가 표현이 되도록 구현을 해야 되는 것이었다.


 


다음은 item이 들어가는 item class 


import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name="item", strict = false)
public class ItemClass {
@Element(name="dirTp")
String dirTp ;
@Element(name="govNm")
String govNm;
@Element(name="localX")
double localX ;
@Element(name="localY")
double localY ;
@Element(name="mobiNum")
String mobiNum ;
@Element(name="stationId")
String stationId ;
@Element(name="stationNm")
String stationNm ;
@Element(name="upd")
String upd ;
@Element(name="useYn")
String useYn ;

public double getLocalX() {
return localX;
}

public double getLocalY() {
return localY;
}

public String getMobiNum() {
return mobiNum;
}

public String getDirTp() {
return dirTp;
}

public String getGovNm() {
return govNm;
}

public String getStationId() {
return stationId;
}

public String getStationNm() {
return stationNm;
}

public String getUpd() {
return upd;
}

public String getUseYn() {
return useYn;
}

public void setDirTp(String dirTp) {
this.dirTp = dirTp;
}

public void setGovNm(String govNm) {
this.govNm = govNm;
}

public void setLocalX(double localX) {
this.localX = localX;
}

public void setLocalY(double localY) {
this.localY = localY;
}

public void setMobiNum(String mobiNum) {
this.mobiNum = mobiNum;
}

public void setStationId(String stationId) {
this.stationId = stationId;
}

public void setStationNm(String stationNm) {
this.stationNm = stationNm;
}

public void setUpd(String upd) {
this.upd = upd;
}

public void setUseYn(String useYn) {
this.useYn = useYn;
}
}

이렇게 구현 하면 데이터를 받아올 준비는 되었다.  이제 interface 을 구현해 볼 차례 인데,    openapi 에는 호출시 파라미터를 last 와 serviceKey 를 받는다고 되어 있지만, 현재( 2021.12.19 )에는 아무것도 전달하지 않아도 되고, last 뒤에 날자만 전달해도 된다. last 을 넣어보내면 최근 업데이트 된 정보만 받아오는 것으로 확인이 되었다.  다만, 나의 앱에서는 정보가 처음이라, 전체 데이터를 받기 위해서 아무것도 파라미터로 사용하지 않다. 


 


import retrofit2.Call;
import retrofit2.http.GET;

public interface RetrofitApi {
String baseURL = "http://busopen.jeju.go.kr";
String getStation = "/OpenAPI/service/bis/Station";

@GET(getStation)
Call<StationBean> getStationInfo();
}

 interface class 는 이렇게 구성을 했다. query 가 없어서 아무것도 전달하지는 않았다.


이번에는 activity 에서 호출을 해 보도록 하겠다.


 


public class MainActivity extends AppCompatActivity {

...

Retrofit retrofit ;
RetrofitApi service ;

...


private void doGetBusStation() {

retrofit = new Retrofit.Builder()
.baseUrl(RetrofitApi.baseURL)
.client(new OkHttpClient())
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
service = retrofit.create(RetrofitApi.class);

service.getStationInfo().enqueue(new Callback<StationBean>() {
@Override
public void onResponse(Call<StationBean> call, Response<StationBean> response) {
Log.e(TAG, "response=" + response.code() + " Total=" + response.body().getBodyClass().getTotalCount());
for(ItemClass item : response.body().getBodyClass().getItems()) {
Log.e(TAG, item.getStationNm());
}
}

@Override
public void onFailure(Call<StationBean> call, Throwable t) {
Log.e(TAG, "ERROR=" + t.toString()) ;
}
});

}


...


}

아직 데이터를 받아와서 어떻게 하고자 하는 지 결정을 하지 못했다. 일단, 데이터가 들어 오는 것은 확인을 하였다.  이 구현을 하는데,  CLEARTEXT communication to XXXX not permitted by network security policy 을 만나게 되면, 어떻게 할 것인가를 고민하지 말고 다음을 따라해 보면 된다. 이유는 http:// 으로 된 주소에 통신을 시도하기 때문에 발생하는 보안 문제인데,  나 앱이 모든 호출에서 http:// 로 할 것이 아니기 때문에 특정 url 만 http 로 호출할 것이라고 등록을 해 주면 된다. 


 


먼저 xml 파일을 하나 만든다.  res/xml/network_config.xml 이라고 .. 그안에는 다음과 같이 넣어 준다. 


<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">busopen.jeju.go.kr</domain>
</domain-config>
</network-security-config>

특정 주소는 http 로 통신을 하겠다는 것이다.  보안정책 때문에 누군가 싫어할지 모르지만.


그리고 다음은 manifest 에 다음을 추가해 준다. 


 


    <application
android:allowBackup="true"
android:icon="@mipmap/ic_info_logo"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_info_logo_round"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_config"

networkSecurityConfig 을 추가해 주면 끝.


 


응답 로그



제주도에는 4358개이 정류소 정보가 있나 보다.  다음엔 이것을 저장해서 데이터로 활용해 보도록 하겠다.


 





오늘의 이야기


#billcorea #운동동아리관리앱
🏸 شنيدل، تطبيق ضروري لأندية كرة الريشة!
👉 مباراة اللعب - سجل النتائج وابحث عن المعارضين 🎉
مثالي لأي مكان، بمفردك، مع الأصدقاء، أو في النادي! 🤝
إذا كنت تحب كرة الريشة، جربها بالتأكيد

اذهب إلى التطبيق 👉 https://play.google.com/store/apps/details?id=com.billcorea.matchplay




오늘의 이야기

오늘은 정리되고 있는 자료를 타인(?)들과 공유하기 위해서... Firebase 의 Realtime Database 에 저장을 해 보도록 하겠다.


import requests
import sqlite3
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
from firebase_admin import messaging
import datetime

# 서버 운영을 위해서는 firebase 의 설정 정보를 따로 읽어올 수 있어야 함.
cred = credentials.Certificate('./services_firebase.json')
firebase_admin.initialize_app(cred,{
'databaseURL' : 'https://my-appli................ault-rtdb.asia-southeast1.firebasedatabase.app/'
})

conn = sqlite3.connect("opDeGangDB.sqlite", isolation_level=None)
rs = conn.cursor()
rs.execute('''CREATE TABLE IF NOT EXISTS chejuList1
(id integer PRIMARY KEY, url text, Name text, writeDate text)''')

rs.execute('''CREATE TABLE IF NOT EXISTS localAddr
(id integer PRIMARY KEY, url text, address text, lat float, lot float, writeDate text)''')

url = 'https://dapi.kakao.com/v2/local/search/address.json'
urlCategory = 'https://dapi.kakao.com/v2/local/search/category.json'
REST_API_KEY = '6........................................8'
headers = {'Authorization': 'KakaoAK {0}'.format(REST_API_KEY)}
address = '제주 제주시 첨단로 242'

def location_data(address):
params = {'query': '{0}'.format(address)}
resp = requests.get(url, params=params, headers=headers)
#print(resp.status_code)
data = resp.json()['documents'][0]['road_address']
return data

def category_data(y, x):
# FD6 음식점 좌표 주변 20m 검색
params = {'category_group_code': 'FD6', 'x': '{0}'.format(x), 'y': '{0}'.format(y), 'radius': 20}
resp = requests.get(urlCategory, params=params, headers=headers)
#print(resp.status_code) phone, road_address_name, x, y, distance
idx = resp.json()['meta']['total_count']
print(idx)
if idx == 0:
data = {'place_name': 'not found'}
else:
for ix in range(0, idx):
data = resp.json()['documents'][ix]
if idx > 1:
if int(resp.json()['documents'][ix]['distance']) < 10:
break;
return data

# addrStr = location_data(address)
# print(addrStr['address_name'] + ' ' + addrStr['y'] + ' ' + addrStr['x'])
rs.execute('select url, address, lat, lot from localAddr')
row = rs.fetchone()
# print(row[0] + ' ' + row[1] + ' ' + str(row[2]) + ' ' + str(row[3]))
# print(category_data(row[2], row[3]))

jejuFD6info = db.reference('jejuFD6info')

for row in rs.fetchall():
data = category_data(row[2], row[3])
print(row[0] + ' ' + row[1] + ' ' + str(data))
try:
infoData = jejuFD6info.child(data['id'])
infoData.set(data)
infoData.child('url').set(row[0])
except:
print('이미 처리')


print('JOB END')

2) 에서 보았던 소스에 추가적인 작업을 하고 있다. Firebase 의 RealtimeDatabase 와 접속을 위해서 services_firebase.json 파일을 만들어야 하는 데, 그것 이전에 작성했던 포스팅을 참고하면 된다.


https://billcoreapython.tistory.com/29



 


파이썬 자동화 스크립트 : Firebase Cloud Messaging 보내기


오늘은 파이썬으로 메시지를 보내 보도록 하겠다... 어디로 내 안드로이드 폰으로 다가... 그래서 먼저 안드로이드에서 하는 FCM에 대한 이해를 조금해 보아야 하지 않을까 싶다. https://billcorea.tist


billcoreapython.tistory.com




이번에 추가된 부분은 category_data(y, x) 함수 부분인데, 이건 뭘할껀가 하면 주소를 막상 받아오기는 했는데, 그 주소의 정확도(?)를 확인할 방법이 없다. 실제 주소인지도 모르겠고 그렇다고 일일이 다 방문해 보려면 하 세월일 듯 하여,


kakao api을 통해서 검증을 해 보는 것이다. kakao api 에서는 위도, 경도 주변 기준으로 검색을 해주는 서비스를 지원하고 있다. 그 중에서도 특정 카테고리를 선택하면 해당 되는 카테고리 정리를 찾아주기 때문에 그것을 이용해서 주변에 있는 식당을 찾아보는 것이다.


그래서 location_data 에서 받아온 위도, 경도와 근접한(20m 이내) 곳을 검색에서 내가 알려준 위도, 경도와 제일 근접한 곳을 이 위도, 경도의 맛집(?) 이라고 인식하게 하는 것이다.  그렇게 해서 정리를 해 두어야 데이터를 활용하는 측면에서도 유용한 자료가 되지 않을 까 하는 생각이 든다.


ㅋ~


그럼 이제 이것으로 무엇을 할 것 인가 ?  그건 역시 아직은 비밀... ㅋㅋㅋ 


firebase 에 저장된 저장 예시



 





오늘의 이야기

하하.. 제주도에는 어떤 맛집들이 있는지... 오늘도 찾아 본다...  하다 보니... 네이버 블로그는 iframe 으로 둘러 쌓여 있어 한번 더 스크랩을 해야 하는 불편(?)한 점을 발견 했다. 


오늘은 버전은 스크랩 한 자료를 그냥 흘려 버리는 것이 아니라, 파이썬에서 구동 할 수 있는 작은 db 에 저장을 해 보도록 하겠다.


그럼... 소스를 


import requests
from bs4 import BeautifulSoup
import urllib
import sqlite3
from datetime import datetime
import re
import json

conn = sqlite3.connect("opDeGangDB.sqlite", isolation_level=None)
rs = conn.cursor()
rs.execute('''CREATE TABLE IF NOT EXISTS chejuList1
(id integer PRIMARY KEY, url text, Name text, writeDate text)''')

rs.execute('''CREATE TABLE IF NOT EXISTS localAddr
(id integer PRIMARY KEY, url text, address text, lat float, lot float, writeDate text)''')

insSql = '''
insert into chejuList1 (url, name, writeDate)
values ('{0}', '{1}', '{2}')
'''

insJusoSql = '''
insert into localAddr (url, address, lat, lot, writeDate)
values ('{0}', '{1}', {2}, {3}, '{4}')
'''

urlKakao = 'https://dapi.kakao.com/v2/local/search/address.json'
REST_API_KEY = '6................................8'
headers = {'Authorization': 'KakaoAK {0}'.format(REST_API_KEY)}

def location_data(url, address):
params = {'query': '{0}'.format(address)}
resp = requests.get(urlKakao, params=params, headers=headers, verify=True)
rValue = ''
#print(resp.json()['meta'])
try:
if resp.json()['meta']['total_count'] > 0:
rValue = resp.json()['documents'][0]['road_address']
except:
rValue = ''
return rValue

searchKey = '제주맛집'
for idx in range(1, 100):
print(idx)
url = "https://search.daum.net/search?w=blog&m=board&collName=blog_total&q={0}&spacing=0&DA=PGD&p={1}".format(urllib.parse.quote_plus(searchKey), idx)
response = requests.get(url, verify=False)
bs = BeautifulSoup(response.text, 'html.parser')
for item in bs.find_all(class_="f_link_b"):
rs.execute(''' select count(*) from chejuList1 where url = "{0}" '''.format(item['href']))
if rs.fetchone()[0] == 1:
pass
else:
print(item['href'] + ' ' + item.text)
rs.execute(insSql.format(item['href'], item.text.replace("'",""), datetime.today().strftime("%Y%m%d%H%M%S")))

def getAddr(url, text):
if (len(re.findall(r'제주시', text)) > 0 or len(re.findall(r'서귀포시', text)) > 0) and (len(re.findall(r'로', text)) > 0 or len(re.findall(r'면', text)) > 0 or len(re.findall(r'읍', text)) > 0):
strText = re.findall(r'\w+', text)
idx = 0
for iStr in strText:
if '제주' in iStr:
strAddr = ''
for i in range(idx, len(strText)):
strAddr += strText[i] + ' '
addrStr = location_data(url, strAddr)
if addrStr != None and len(addrStr) > 0:
#print(addrStr['address_name'] + ' ' + addrStr['y'] + ' ' + addrStr['x'])
rs.execute(insJusoSql.format(url, addrStr['address_name'], addrStr['y'], addrStr['x'], datetime.today().strftime("%Y%m%d%H%M%S")))
return True
idx += 1
return False
else:
return False

rs.execute(''' select url, Name, writeDate from chejuList1 ''')
items = rs.fetchall()
for item in items:
print(item[0] + ' ' + item[1])
response = requests.get(item[0], verify=True)
bs = BeautifulSoup(response.text, 'html.parser')
text1 = ''
if 'blog.naver' in item[0]:
iframexx = bs.find_all('iframe')
for iframe in iframexx:
res = requests.get('https://blog.naver.com/' + iframe.attrs['src'])
bs = BeautifulSoup(res.text, 'html.parser')
text1 = re.sub('(<([^>]+)>)', '', bs.get_text())
else:
text1 = re.sub('(<([^>]+)>)', '', bs.get_text())
tt = ''
for line in text1.split('\n'):
if line.strip() != '':
text = line.strip()
if getAddr(item[0], line.strip()):
print('R=' + text)

print('Job End')

중간에 있는 location_data 는 카카오 api 을 이용해서 이 주소에 대한 정보를 검증해 보고 있는 중이다... 그리고 그 주소의 위치정보를 기록해 두고 있다. 무엇을 할려고 하는 지는 비밀(?) ㅋㅋㅋ


찾아 가려면 주소를 알아야 하니까 ... 이렇게 수집된 정보를 이용해서 어디 갈 때 좀 편하게 가 보자...


테스트 하면서 작성하는 중이라, 글이 좀 지저분 해도 양해를 부탁 드려요...





오늘의 이야기


#스하리1000명프로젝트,
Perso in Corea? Anche se non parli coreano, questa app ti aiuta a muoverti facilmente.
Parla semplicemente la tua lingua: traduce, cerca e mostra i risultati nella tua lingua.
Ottimo per i viaggiatori! Supporta oltre 10 lingue tra cui inglese, giapponese, cinese, vietnamita e altre.
Provalo adesso!
https://play.google.com/store/apps/details?id=com.billcoreatech.opdgang1127




2026/02/21

오늘의 이야기

제주도를 가고 싶었는데, 아직인 데... 제주도에 가면 어떤 맛집이 있는 지 궁금하기도 하고 해서 


많은 블로거 들이 작성한 글을 찾아서 제주 맛집을 찾아 보려고 한다.


import requests
from bs4 import BeautifulSoup
import urllib
import sqlite3
from datetime import datetime
import re

conn = sqlite3.connect("opDeGangDB.sqlite", isolation_level=None)
rs = conn.cursor()
rs.execute('''CREATE TABLE IF NOT EXISTS chejuList1
(id integer PRIMARY KEY, url text, Name text, writeDate text)''')

insSql = '''
insert into chejuList1 (url, name, writeDate)
values ('{0}', '{1}', '{2}')
'''

searchKey = '제주맛집'
for idx in range(1, 100):
print(idx)
url = "https://search.daum.net/search?w=blog&m=board&collName=blog_total&q={0}&spacing=0&DA=PGD&p={1}".format(urllib.parse.quote_plus(searchKey), idx)
response = requests.get(url)
bs = BeautifulSoup(response.text, 'html.parser')
for item in bs.find_all(class_="f_link_b"):
rs.execute(''' select count(*) from chejuList1 where url = "{0}" '''.format(item['href']))
if rs.fetchone()[0] == 1:
pass
else:
print(item['href'] + ' ' + item.text)
rs.execute(insSql.format(item['href'], item.text.replace("'",""), datetime.today().strftime("%Y%m%d%H%M%S")))

regex = r'(\w+[원,산,남,울,북,천,주,기,시,도]\s*)?' \
r'(\w+[구,시,군]\s*)?(\w+[구,시]\s*)?' \
r'(\w+[면,읍]\s*)' \
r'?(\w+\d*\w*[동,리,로,길]\s*)' \
r'?(\w*\d+-?\d*)?'

rs.execute(''' select url, Name, writeDate from chejuList1 ''')
items = rs.fetchall()
for item in items:
print(item[0] + ' ' + item[1])
response = requests.get(item[0])
bs = BeautifulSoup(response.text, 'html.parser')
text1 = re.sub('(<([^>]+)>)', '', bs.get_text())
tt = ''
for line in text1.split('\n'):
if line.strip() != '':
print(re.search(regex, line.strip()))
#break

일단 할 수 있는 것은 다음 검색에서 제주맛집 을 찾아보자... 그리고 이제 그것을 스크랩해서 제주도에 있는 맞집 리스트를 만들어 보는 것이다.  블로거 들이 작성한 것이기 떄문에 나름 검증은 되었다고 봐도 될 듯 하고, 그 리스트를 잘 정리하면 중복 되는 것도 있을 꺼고... 그렇게 해서 나만의 맛집 목록을 만들어 보는 것이다.


ㅋ~


많은 블로거님들 감사합니다.





오늘의 이야기



#스치니1000프로젝트 #재미 #행운기원 #Compose #Firebase

🎯 야 너 토요일마다 로또 확인하냐?
나도 맨날 "혹시나~" 하면서 봤거든 ㅋㅋ

근데 이제는 그냥 안 해
AI한테 맡겼어 🤖✨

그것도 구글 Gemini로다가!

그래서 앱 하나 만들었지
👉 "로또 예상번호 by Gemini" 🎱

AI가 분석해서 번호 딱! 뽑아줌
그냥 보고 참고만 하면 됨

재미로 해도 좋고…
혹시 모르는 거잖아? 😏


https://play.google.com/store/apps/details?id=com.billcorea.gptlotto1127




오늘의 이야기

앱을 하나 만들다 보니 별점 주기를 해 보고 싶은 생각이 들었다.  그래서 찾아보니 이렇게 있네 ?


Ratingbar ... 화면에 배치를 해 보자.


 


RatingBar 이미지



이제 설정을 해 보자 먼저 몇점까지를 주게 할 것인가 ? 나는 5점 만점으로 정했다. 


 




numStars : 몇점 만점으로 할 것인지 


stepSize : 몇점 단위로 할 것인지 


rating : 선택하기전 처음 점수는 


 


한가지 주의하고 가야할 것이 있다면 layout_width 을 wrap_content 로 해 주어야 한다는 것이다 .


match_parent 을 했을 때는 화면에 표시가능한 만큼 별이 늘어나는 현상이 발생하기 떄문이다. 난 분명 5점 만점으로 하고 싶었지만, 화면이 크기에 따라 별이 늘어나 보인다. step 도 적용이 잘 되지 않는 현상이 생기게 된다.


 


 


 


 


그럼 이제 실제로 적용 되어 움직이는 모양을 확인해 보기로 하겠다.


 





실행을 해 보면 이렇게 선택하는 바에 따라서 동작을 하게 되는 것이였다.  그런데, 난 이걸 사용할 수 가 없다. 데이터를 실시간으로 동기화를 해야 하기 때문에...


 


오늘은 동작이 어떻게 되는지만, 알아 보는 것으로 만족하기로 했다.


 





오늘의 이야기

import sqlite3

conn = sqlite3.connect("opDeGangDB.sqlite", isolation_level=None)
rs = conn.cursor()
rs.execute('''CREATE TABLE IF NOT EXISTS chejuList1
(id integer PRIMARY KEY, url text, Name text, writeDate text)''')

try:
rs.execute('''
alter table chejuList1 add column test varchar(32)
''')
except:
print('이미 처리 됨')

 


이미 만들어 놓은 파일에 저장하고 싶은 항목이 새로 생겼다면... 어떻게 할 것 인가 ? ㅋ~


오라클이나, 다른 db 들 처럼 alter table 을 지원하고 있으니 이 얼마나 좋은 일인가 ?


이렇게 해서 한가지 고민은 또 끝.


 


 


컬럼이 추가된 테이블 조회



 





오늘의 이야기


#스하리1000명프로젝트

스치니들!
내가 만든 이 앱은, 내 폰에 오는 알림 중에서 중요한 키워드가 있는 경우
등록해둔 친구에게 자동으로 전달해주는 앱이야 📲

예를 들어, 카드 결제 알림을 와이프나 자녀에게 보내주거나
이번 달 지출을 달력처럼 확인할 수도 있어!

앱을 함께 쓰려면 친구도 설치 & 로그인해줘야 해.
그래야 친구 목록에서 서로 선택할 수 있으니까~
서로 써보고 불편한 점 있으면 알려줘 🙏

👉 https://play.google.com/store/apps/details?id=com.nari.notify2kakao





오늘의 이야기

    import smtplib
from email.mime.text import MIMEText

smtp = smtplib.SMTP('smtp.gmail.com', 587)
smtp.starttls() # TLS 사용시 필요
smtp.login('....g@gmail.com', '패스워드')
html = '''
<html>
<head>{0}</head>
<body>
<br/>
<a href="{1}">원본출처: 티스토리 바로가기</a>
<br/>
{2}
</body>
</html>
'''
msg = MIMEText(html.format(title, postUrl, content), _subtype='html', _charset='utf-8')
msg['Subject'] = title
# msg['To'] = '......ds@blogger.com'
smtp.sendmail('......g@gmail.com', '.....d@blogger.com', msg.as_string())
smtp.quit()

smtp 을 이용해서 메일 보내는 기능을 구현해 볼 수 있네 ... 올~   이것도 아마 자동화 하는 데 도움이 되지 않을까 해서 


일단은 적어둔다... 이걸루 뭘 할껀가 ?


또 하나의 블로그 게시물을 자동으로 올리는 노동을 해 보는 거다...


이걸 하려면 준비를 해야 할 것이 있다. 


1. 일단 내가 사용하는 구글 계정의 imap 을 이용한 메일 발송을 할 수 있도록 구성


2. 구글에 로그인을 할 때 이런 저런 제약이 있기 때문에 앱에서도 로그인이 될 수 있도록 구성


일단 이 두가지만 준비가 되면 뭔가를 할 수 있을 것 같다. 그 준비는 다음에...


 





오늘의 이야기

앱에서 지원하고 싶은 것중 우선 나의 주변에 버스 정류소를 찾는다. 어떻게 찾을까 ?   모든 데이터는 data.go.kr 공공데이터 포털을 중심으로 ... 찾아보니 제주도에서 제공하는 버스 정보가 있다.   http://www.jeju.go.kr/h...