Web/Flask

Flask와 MongoDB를 활용한 웹 애플리케이션 만들기(2) | GET, POST 요청 보내기, Meta og 태그 크롤링

daeunnniii 2021. 7. 24. 21:22
728x90
반응형

이전에 "책 리뷰 게시판" 웹 애플리케이션을 만들면서 Flask로 GET, POST 요청을 보내는 과정을 정리했다. 

https://daeunnniii.tistory.com/104

 

Flask와 MongoDB를 활용한 웹 애플리케이션 만들기(1) | GET, POST 요청 보내기

"책 리뷰 게시판" 웹 애플리케이션을 만드는 과정을 통해 Flask로 GET, POST 요청을 보내는 부분을 정리하려고 한다. 1. POST 요청 실습 - 리뷰 저장하기 A. 요청 정보 - 요청 URL= /review , 요청 방식

daeunnniii.tistory.com

 

이번에는 Flask, MongoDB과 더불어 Beautifulsoup4을 활용하여 "나홀로 링크 메모장" 웹 애플리케이션을 만들어보려고 한다.

 

나홀로 링크 메모장 완성 화면

 

 

1. Beautifulsoup4을 활용한 og 메타 태그 스크래핑

1) meta 태그? meta 데이터?

meta 태그는 눈에 보이는 것 외에 사이트의 속성을 설명해주는 태그이며, <head></head>부분에 들어간다. meta 데이터는 쉽게 말하면 해당 웹페이지를 구성하는 여러 구조화된 정보들 제목, 설명, 이미지 등을 아예 명시적으로 웹페이지쪽에서 직접 정해서 표기해준 것을 말한다. 기본적인 메타 데이터로는 제목(title), 설명(description), 대표 이미지(image), 표준 링크(url) 등이 있다.

 

2) 그러면 og 메타 태그란? 

og는 Open Graph의 약자이고 어떤 HTML 문서의 메타 정보를 쉽게 표시하기 위해서 메타 정보에 해당하는 제목, 설명, 문서의 타입, 대표 url 등 다양한 요소들에 대해 사람들이 통일해서 쓸 수 있도록 정해놓은 프로토콜이다.

 

이러한 오픈 그래프 Open Graph는 아래와 같이 사용자가 클릭하기 전 크롤러가 해당 웹사이트를 방문하여 HTML의 head의 메타데이터를 크롤링하여 미리보기 화면을 생성해줄 수 있도록 한다!

3) og 메타 태그 스크래핑

먼저 크롤링하고자하는 사이트의 소스코드를 확인해보면 다음과 같이 HTML의 head 부분에 og 메타태그가 있는 것을 확인할 수 있다. og:title 라인에서 오른쪽 마우스>copy>copy selector을 클릭해주면 복사가 된다.

그리고 파이썬 코드에서 title=soup.select_one(' <<<<<붙여넣기>>>>>>') 를 해보면 원하는대로 결과가 뜨지 않는 것을 볼 수 있다. 이러한 경우 title=soup.select_one('meta[property="og:title"]')를 입력해주면 해결된다.

 

아래와 같이 코드를 작성하면 제목, 이미지, 줄거리까지 원하는 데이터가 잘 크롤링된 것을 확인할 수 있다.

import requests
from bs4 import BeautifulSoup

url = 'https://movie.naver.com/movie/bi/mi/basic.nhn?code=171539'

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)

soup = BeautifulSoup(data.text, 'html.parser')

title = soup.select_one('meta[property="og:title"]')['content']
image = soup.select_one('meta[property="og:image"]')['content']
desc = soup.select_one('meta[property="og:description"]')['content']
print(title,image,desc)

 

2. POST 요청 실습

A. 요청 정보

- 요청 URL= /memo , 요청 방식 = POST
- 요청 데이터 : URL(url_give), 코멘트(comment_give)

B. 서버가 제공할 기능

- URL의 meta태그 정보를 바탕으로 제목, 설명, 이미지URL 스크래핑
- (제목, 설명, URL, 이미지URL, 코멘트) 정보를 모두 DB에 저장

C. 응답 데이터  

- API가 정상적으로 작동하는지 클라이언트에게 알려주기 위해서 성공 메시지 보내기
- (JSON 형식) 'result'= 'success'

1) 클라이언트 코드 - index.html

function postArticle() {
	let url = $('#post-url').val()
	let comment = $('#post-comment').val()

	$.ajax({
		type: "POST",
		url: "/memo",
		data: {url_give:url, comment_give:comment},
		success: function (response) { // 성공하면
			alert(response["msg"]);
			window.location.reload()
		}
	})
}

2) 서버 코드 - app.py

@app.route('/memo', methods=['POST'])
def saving():
    url_receive = request.form['url_give']
    comment_receive = request.form['comment_give']

    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_receive,headers=headers)

    soup = BeautifulSoup(data.text, 'html.parser')

    title = soup.select_one('meta[property="og:title"]')['content']
    image = soup.select_one('meta[property="og:image"]')['content']
    desc = soup.select_one('meta[property="og:description"]')['content']
    doc = {
        'title': title,
        'image':image,
        'desc':desc,
        'url':url_receive,
        'comment':comment_receive
    }
    db.articles.insert_one(doc)

    return jsonify({'msg':'저장이 완료되었습니다!'})

 

3. GET 요청 실습

A. 요청 정보

- 요청 URL= /memo , 요청 방식 = GET
- 요청 데이터 : 없음

B. 서버가 제공할 기능

- DB에 저장돼있는 모든 (제목, 설명, URL, 이미지URL, 코멘트) 정보를 가져오기

C. 응답 데이터

- 아티클(기사)들의 정보(제목, 설명, URL, 이미지URL, 코멘트) → 카드 만들어서 붙이기
- (JSON 형식) 'articles': 아티클 정보

 

1) 서버 코드 - app.py

@app.route('/memo', methods=['GET'])
def listing():
    articles = list(db.articles.find({}, {'_id':False}))
    return jsonify({'all_articles':articles})

 

2) 클라이언트 코드 - index.html

function showArticles() {
      $.ajax({
        type: "GET",
        url: "/memo",
        data: {},
        success: function (response) {
          let articles = response['all_articles']
          for (let i = 0; i < articles.length; i++) {
            let title = articles[i]['title']
            let image = articles[i]['image']
            let url = articles[i]['url']
            let desc = articles[i]['desc']
            let comment = articles[i]['comment']

            let temp_html = `<div class="card">
                               <img class="card-img-top"
                                 src="${image}"
                                 alt="Card image cap">
                                 <div class="card-body">
                                   <a target="_blank" href="${url}" class="card-title">${title}</a>
                                   <p class="card-text">${desc}</p>
                                   <p class="card-text comment">${comment}</p>
                                 </div>
                             </div>`
            $('#cards-box').append(temp_html)
          }
        }
      })
    }

 

 

참고: https://spartacodingclub.kr/

 

728x90
반응형