정적 웹페이지,
동적 웹페이지 - CSR, SSR
한번 페이지 띄우고 바뀔일 없는 페이지에서는
서버사이드 렌더링 효율적 -> jinja2 사용
페이지 연결
#script 없이 html에 바로 입력
<button onclick="window.location.href = '/'">메인으로 돌아가기</button>
#script 함수 입력
<script>
function tomain(){
window.location.href = "/"
}
</script>
Jinja2 템플릿 언어
#flask
@app.route('/')
def main():
myname = "sparta"
return render_template("index.html", name=myname)
#html
<h3>Hello, {{ name }}!</h3>
jinja2 api받아오기
ctrl alt s -> Template Languages -> jinja2선택
r = requests.get('http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99')
response = r.json()
rows = response['RealtimeCityAir']['row']
jinja2 HTML
<ul id="gu-list">
#반복문
{% for row in rows %}
#변수설정
{% set gu_name = row['MSRSTE_NM']%}
{% set gu_mise = row['IDEX_MVL']%}
{% if gu_mise >= 35 %}
<li>{{gu_name}}: {{gu_mise|int}}</li>
{% endif %}
{% endfor %}
</ul>
#정보 호출 방식 HTML
<h1 id="word" style="display: inline;">{{ result['word' }}</h1>
<h1 id="word" style="display: inline;">{{ result.word }}</h1>
<h1 id="word" style="display: inline;">{{ word }}</h1>
#null, none 값 없애기
#safe-> 전송되는 html태그기능 사용
{% if definition.example %}
<span class="example">{{ definition.example|safe }}</span>
{% endif %}
#특수문자 없애기
<span class="example">{{ definition.example.encode('ascii', 'ignore').decode('utf-8')|safe }}</span>
#정상값 출력 안되면
if r.status_code != 200:
return redirect('/') // return redirect(url_for('main', msg='단어가 이상해요'))
function find_word(){
let word = $('#input-word').val().toLowerCase() #소문자로만 받기
if (word_list.includes(word)){
$(`#word-${word}`).addClass('highlight') #js클래스 추가 함수
(`#word-${word}`)[0].scrollIntoView() #스크롤 이동 함수
}else{
window.location.href= `/detail/${word}?status_give=new`
}
}
셀레니움 스크래핑
동적인 웹페이지 스크래핑 시 활용
셀레니움 설치필요 -> 크롬드라이버다운
크롬버전확인
다운
다운받은 드라이버 -> 프로젝트 폴더에 복사(스크래핑 파일과 같은 위치에)
from bs4 import BeautifulSoup
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome('./chromedriver') # 드라이버를 실행합니다.
url = "https://www.melon.com/chart/day/index.htm"
# headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
# data = requests.get(url, headers=headers)
driver.get(url) # 드라이버에 해당 url의 웹페이지를 띄웁니다.
sleep(5) # 페이지가 로딩되는 동안 5초 간 기다립니다.
req = driver.page_source # html 정보를 가져옵니다.
driver.quit() # 정보를 가져왔으므로 드라이버는 꺼줍니다.
# soup = BeautifulSoup(data.text, 'html.parser')
soup = BeautifulSoup(req, 'html.parser') # 가져온 정보를 beautifulsoup으로 파싱해줍니다.
songs = soup.select("#frm > div > table > tbody > tr")
print(len(songs))
for song in songs:
title = song.select_one("td > div > div.wrap_song_info > div.rank01 > span > a").text
artist = song.select_one("td > div > div.wrap_song_info > div.rank02 > span > a").text
# likes = song.select_one("td > div > button.like > span.cnt").text
likes_tag = song.select_one("td > div > button.like > span.cnt")
likes_tag.span.decompose() # span 태그 없애기
likes = likes_tag.text.strip() # 텍스트화한 후 앞뒤로 빈 칸 지우기
print(title, artist, likes)
이미지 스크래핑
from bs4 import BeautifulSoup
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome('./chromedriver')
url = "https://search.naver.com/search.naver?where=image&sm=tab_jum&query=%EC%95%84%EC%9D%B4%EC%9C%A0"
driver.get(url)
sleep(10)
driver.execute_script("window.scrollTo(0, 1000)") # 1000픽셀만큼 내리기
sleep(3)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 바닥까지 내리기
sleep(10)
req = driver.page_source
driver.quit()
soup = BeautifulSoup(req, 'html.parser')
images = soup.select(".tile_item._item ._image._listImage")
print(len(images))
for image in images:
src = image["src"]
print(src)
네이버 지도 api
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<title>간단한 지도 표시하기</title>
<script type="text/javascript"
src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=nzoyx5ujzu"></script>
<script src=" https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
#map {
width: 100%;
height: 400px;
}
</style>
<script>
$(document).ready(function () {
// let map = new naver.maps.Map('map', {
// center: new naver.maps.LatLng(37.4981125, 127.0379399),
// zoom: 10
// });
let map = new naver.maps.Map('map', {
center: new naver.maps.LatLng(37.4981125, 127.0379399),
zoom: 10,
zoomControl: true,
zoomControlOptions: {
style: naver.maps.ZoomControlStyle.SMALL,
position: naver.maps.Position.TOP_RIGHT
}
});
let marker = new naver.maps.Marker({
position: new naver.maps.LatLng(37.4981125, 127.0379399),
map: map,
icon: "{{ url_for('static', filename='rtan_heart.png') }}"
});
let infowindow = new naver.maps.InfoWindow({
content: `<div style="width: 50px;height: 20px;text-align: center"><h5>안녕!</h5></div>`,
});
naver.maps.Event.addListener(marker, "click", function () {
console.log(infowindow.getMap()); // 클릭 이벤트로 인포윈도우 여닫기,정보창이 열려있을 때는 연결된 지도를 반환하고 닫혀있을 때는 null을 반환
if (infowindow.getMap()) {
infowindow.close();
} else {
infowindow.open(map, marker);
}
});
})
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
geocoding 좌표받기
headers = {
"X-NCP-APIGW-API-KEY-ID": "[내 클라이언트 아이디]",
"X-NCP-APIGW-API-KEY": "[내 클라이언트 시크릿 키]"
}
r = requests.get(f"https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query={address}", headers=headers)
response = r.json()
Font Awesome 링크
```html
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">