Python 을 활용해서 indeed 와 wwr 웹 사이트의 구인정보들을 스크랩 하고
스크랩한 구인정보들을 Flask 로 구축한 웹 사이트로 구현해 보았다.
제작했던 전체 파일
extractors 폴더에 indeed.py 와 wwr.py ( indeed 와 wwr 웹 사이트의 구인정보를 스크랩 하는 파일 )
templates 폴더에 home.html 과 search.html ( Flask 웹 사이트 구축을 위한 template )
chromedriver.exe 는 indeed 웹 사이트를 스크랩 하기 위해 필요한 프로그램 → 관련 게시물
( webdriver 는 Python에서 브라우저를 시작할 수 있게 해준다. )
file.py 는 파일을 어떤 방식으로 저장하고 어떤 데이터를 가져와서 저장하는지 → 관련 게시물
main.py 는 각 파일들로 부터 필요한 함수들을 import 하고 Flask 로 함수를 만들어 웹 사이트와 연결.
< indeed.py >
from requests import get
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def get_page_count(keyword):
options = Options()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
browser = webdriver.Chrome(options=options)
base_url = 'https://kr.indeed.com/jobs?q='
browser.get(f'{base_url}{keyword}')
soup = BeautifulSoup(browser.page_source,'html.parser')
search_count = soup.find('div',class_='jobsearch-JobCountAndSortPane-jobCount')
if search_count == None:
print('검색 결과 없음')
else:
search_count2 = search_count.find('span')
print(search_count2.string)
pagination = soup.find('nav',{'aria-label':'pagination'})
pages = pagination.select('div a')
count = len(pages)+1
for page in pages:
if page['aria-label'] == "Previous Page":
count = count - 1
if page['aria-label'] == "Next Page":
count = count - 1
if count >= 5:
return 5
else:
return count
def extract_indeed_jobs(keyword):
options = Options()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
browser = webdriver.Chrome(options=options)
pages = get_page_count(keyword)
print("Found", pages, "pages")
results = []
for page in range(pages):
base_url = 'https://kr.indeed.com/jobs'
final_url = f'{base_url}?q={keyword}&start={page*10}'
print('Requesting', final_url)
browser.get(final_url)
soup = BeautifulSoup(browser.page_source,'html.parser')
job_list = soup.find('ul', class_='jobsearch-ResultsList')
jobs = job_list.find_all('li', recursive=False)
for job in jobs:
zone = job.find('div', class_='mosaic-zone')
if zone == None:
anchor = job.select_one('h2 a')
title = anchor['aria-label']
link = anchor['href']
company = job.find('span',class_='companyName')
location = job.find('div',class_='companyLocation')
job_data = {
'link':f'https://kr.indeed.com{link}',
'company': company.string.replace(","," "),
'location': location.string.replace(","," "),
'position': title.replace(","," ")
}
results.append(job_data)
return results
< wwr.py >
from requests import get
from bs4 import BeautifulSoup
def extract_wwr_jobs(keyword):
base_url = "https://weworkremotely.com/remote-jobs/search?utf8=%E2%9C%93&term="
response = get(f'{base_url}{keyword}')
if response.status_code != 200:
print("Can't request website")
else:
results =[]
soup = BeautifulSoup(response.text,'html.parser')
jobs = soup.find_all('section', class_="jobs")
for job_section in jobs:
job_posts = job_section.find_all('li')
job_posts.pop(-1)
for post in job_posts:
anchors = post.find_all('a')
anchor = anchors[1]
link = anchor['href']
company, kind, region = anchor.find_all('span',class_='company')
title = anchor.find('span', class_='title')
job_data = {
'link': f"https://weworkremotely.com/{link}" ,
'company': company.string.replace(","," "),
'location': region.string.replace(","," "),
'position': title.string.replace(","," ")
}
results.append(job_data)
return results
< 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>
<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" method="get">
<input type="text" name="keyword" placeholder="Write keyword please" />
<button>Search</button>
</form>
</main>
</body>
</html>
< 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>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
</head>
<body>
<main class="container">
<h1>Search Results for "{{keyword}}":</h1>
<hgroup>
<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 →</a></td>
</tr>
{% endfor %}
</tbody>
</table></figure>
</main>
</body>
</html>
< file.py >
def save_to_file(file_name, jobs):
file = open(f'{file_name}.csv','w',encoding='utf-8-sig')
file.write('Postition,Company,Location,URL\n')
for job in jobs:
file.write(f"{job['position']},{job['company']},{job['location']},{job['link']}\n")
file.close()
< main.py >
from flask import Flask, render_template, request, redirect, send_file
from extractors.indeed import extract_indeed_jobs
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", name="james", age=20)
@app.route("/search")
def search():
keyword = request.args.get("keyword")
if keyword == None:
return redirect("/")
if keyword == "":
return redirect("/")
if keyword in db:
jobs = db[keyword]
else:
indeed = extract_indeed_jobs(keyword)
wwr = extract_wwr_jobs(keyword)
jobs = indeed + 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 == "":
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("127.0.0.1")
main.py 코드 실행 시 콘솔창
크롬 ( 브라우저 ) 열고 url 에 127.0.0.1:5000 입력하여 Job Scrapper 웹사이트 접속
python 검색
python 검색 결과 ( indeed 와 wwr 웹 사이트에서 구인정보들 스크랩 해서 Flask 웹 사이트로 구현 )
Apply now 클릭 시 새 창이 열리면서 해당 구인공고로 이동
Export to file 클릭 시 "python" 검색어로 검색했던 indeed 와 wwr 웹 사이트 구인정보를 스크랩 하여 csv 파일로 저장.
저장된 python.csv 파일을 엑셀로 열면 Position, Company, Location, URL 이 정리되어 있다.
python 참고 강의
'Programming > Python 웹 스크래퍼 만들기' 카테고리의 다른 글
Python Flask 웹 사이트 다운로드 버튼 만들기 (0) | 2023.01.10 |
---|---|
Python Flask 가짜 DB 만들어서 웹사이트 속도 향상 시키기 (0) | 2023.01.09 |
Flask 웹 사이트 Pico CSS 사용해서 꾸미기 (0) | 2023.01.06 |
Python Flask 로 HTML 에서 For 문 사용 (0) | 2023.01.05 |
Python Flask Arguments (0) | 2023.01.02 |