반응형

 

Flask란?

 

플라스크는 Python의 마이크로 웹 프레임워크이다. 다양한 웹 엔진과 붙여서 쓸 수 있고 또 가볍기도 해서 Django와 같이 쓰는 경우도 있다. 코드도 비교적 단순하고, 특히 API 서버를 만들기에 매우 편리하다. 관련된 확장 기능들이 많기 때문이다.

출처: 나무위키

 

웹 서버 만들기

 

from flask import Flask

app = Flask("JobScrapper")

@app.route("/")
def home():
  return 'Hello Flask!'

app.run("0.0.0.0")

 

웹 서버 만드는 방법은 간단하다.

몇 줄의 코드 작성으로 홈페이지에 접속한 유저에게 'Hello Flask!'를 보여주는 웹 서버가 생성된다.

replit.com에서 코드를 작성해서 실행하므로  "0.0.0.0"을 넣어주었다.

 

무엇을 보여줄까?

 

저번 게시물에서 작성한 JobScrapper를 사용한다.

 

 

원하는 키워드를 검색하면 weworkremotely 사이트에서 키워드를 검색하고 스크래핑해서 유저에게 보여준다.

그리고 목록을 다운로드 받을 수 있는 기능도 추가한다.

 

List를 csv 파일로 만들기

 

def  save_to_file(file_name, jobs):
  file = open(f"{file_name}.csv", "w")
  
  file.write("Position,Company,Location,URL\n")
  
  for job in jobs:
    file.write(f"{job['position']},{job['company']},{job['location']},{job['link']}\n")
  
  file.close()

 

file.py를 생성하고 저번 게시물에서 스크랩한 정보(List)를 파일로 생성한다.

 

HTML 작성하기

 

HTML 파일은 Main.py와 같은 레벨의 폴더에 'templates'라는 폴더를 생성하고 그 안에 생성한다.

그 이유는 Flask가 templates 폴더 안의 HTML 파일을 검색할 수 있도록 하기 위함이다.

 

home.html

 

<!DOCTYPE html>
<html lang="en">
<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">
  <title>Job Scrapper</title>
  # Pico.css
  <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
</head>
<body>
  <main class="container">
    <h1>Job Scrapper</h1>
  <h4>What job do you want?</h4>
  <form action="/search">
    <input type="text" name="keyword" placeholder="Write Keyword" />
    <button>Search</button>
  </form>
  </main>
</body>
</html>

 

유저가 홈페이지에 접속했을 때, 직무를 검색할 수 있는 Input과 버튼을 만든다.

버튼을 클릭하면 /search 페이지로 이동한다.

 

search.html

 

<!DOCTYPE html>
<html lang="en">
<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">
  <title>Job Scrapper</title>
  # Pico.css
  <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
</head>
<body>
  <main class="container">
    <hgroup>
      <h1>Search Results for "{{keyword}}":</h1>
    <a target="_blank" href="/export?keyword={{keyword}}">Export to file</a>
    </hgroup>
    <figure><table role="grid">
      <thead>
        <tr>
          <th>Position</th>
          <th>Company</th>
          <th>Location</th>
          <th>Link</th>
        </tr>
      </thead>
      <tbody>
      {% for job in jobs %}
        <tr>
          <td>{{job.position}}</td>
          <td>{{job.company}}</td>
          <td>{{job.location}}</td>
          <td><a href="{{job.link}}" target="_blank">Apply now &rarr;</a></td>
        </tr>
      {% endfor %}
      </tbody>
    </table></figure>
  </main>
</body>
</html>

 

스크랩해온 데이터를 Loop하면서 보여준다.

데이터는 테이블로 표시된다.

CSV 파일로 만든 데이터를 다운로드 받을 수 있도록 버튼을 추가하고 다운로드 페이지로 이동하도록 만든다.

 

{{ }} : 변수를 사용할 수 있다.

 

{% %} : for 구문 등 로직을 사용할 수 있다.

 

Pico.css

 

https://picocss.com/

 

Pico.css • Minimal CSS Framework for semantic HTML

Elegant styles for all natives HTML elements without .classes and dark mode automatically enabled. 7.9 kB minified and gzipped!

picocss.com

Pico.css는 우리가 작성한 못생긴 HTML 사이트를 간단한 로직을 사용해서 미려하게 만들 수 있는 툴이다.

다양한 방법으로 사용할 수 있는데, 나는 HTML <head>에 로직을 추가하는 방법을 사용했다.

 

<main class="container"> : 콘텐츠를 중앙에 배치한다.

 

<table role="grid"> : 한 줄마다 색이 다르게 된다. (SAP ALV Layout의 zebra 옵션과 비슷하다..)

 

<figure> : 페이지를 가로로 스크롤 할 수 있게 된다. 모바일로 접속해도 가로로 스크롤 할 수 있다. 반응형으로 설계 가능.

 

Main.py

 

from flask import Flask, render_template, request, redirect, send_file
from extractors.wwr import extract_wwr_jobs
from file import save_to_file

app = Flask("JobScrapper")
db = {} # 데이터베이스

@app.route("/")
def home():
  return render_template("home.html")

@app.route("/search")
def search():
  keyword = request.args.get("keyword")
  if keyword == None: # 키워드 미입력 시
    return redirect("/")
  if keyword in db: # 키워드가 데이터베이스에 있으면
    jobs = db[keyword]
  else: # 키워드가 데이터베이스에 없으면
    wwr = extract_wwr_jobs(keyword)
    jobs = wwr
    db[keyword] = jobs # 스크랩 해온 데이터 -> 데이터베이스
  return render_template("search.html", keyword = keyword, jobs=jobs)

@app.route("/export") # 데이터 다운로드
def export():
  keyword = request.args.get("keyword")
  if keyword == None:
    return redirect("/")
  if keyword not in db:
    return redirect(f"/search?keyword={keyword}")
  save_to_file(keyword, db[keyword])
  return send_file(f"{keyword}.csv", as_attachment=True)

app.run("0.0.0.0")

 

유저에게 키워드를 받고(request), 데이터를 보내주고(render_template), 리다이렉트하고(redirect), 파일을 전송하기(send_file)위해서 import 한다.

db를 사용한 이유는, 유저가 검색한 키워드를 계속 스크랩 할 수 있지만 매번 수행하면 좋지 않기 때문에 속도 향상을 위해 사용했다. (실제 데이터베이스는 아니다..)

 

request.args.get("keyword") : 유저가 입력한 키워드를 받는다.

 

render_template( ) : 사용자에게 html과 함께 파라미터도 보내줄 수 있다.

 

redirect( ) : 유저가 키워드를 입력하지 않았으면 홈페이지로 보내고, 데이터베이스에 없는 데이터를 검색하면 키워드를 스크랩해올 수 있도록 한다.

 

send_file( ) : 유저가 웹페이지에서 Export to File 버튼을 선택하면 /export 페이지로 이동하게 되고, file.py의 save_to_file()로 만들어진 csv 파일을 다운로드하게 된다.(as_attachement=True)

 

결과

 

홈 페이지

 

처음 접속한 홈페이지. 검색하고 싶은 키워드를 넣고 Search 버튼을 클릭할 수 있다. (Pico.css를 사용해서 확실히 이쁘다..)

 

검색 페이지

 

Java를 검색한 결과이다. 데이터가 잘 표시되고 링크로 잘 이동하며 Export to file을 클릭하면 데이터를 csv 파일로 다운로드 받을 수 있다.

 

느낀 점

 

Flask는 Python으로만 작성하면 심심한 코드를 웹 서버와 HTML, CSS를 사용해서 유저에게 보여줄 수 있는 웹사이트를 아주 간단하게 제작할 수 있는 장점이 있는 것 같다.

마이크로 프레임워크라고 하지만, 강력한 기능을 많이 제공하고 단순한 로직으로 쉽게 사용이 가능하다.

 

앞으로 간단하게 웹사이트를 제작해보고 싶으면 사용할 것 같다.

 

반응형
사서