네이버뉴스 스크래핑!

저번시간에 배운 것들을 토대로 네이버의 종류별 뉴스부분을 스크래핑한다 

원래는 번개장터나 중고 물품거래사이트에서 lg그램을 검색하면 나오는 페이지들을 스크래핑하려했다

 

하지만 이렇게 거래 또는 보안을 엄격하게 걸어놓은 사이트들은 스크래핑이 되지 않는것같았다

 

배운대로 6단계에 걸쳐서 시행해 보았다

1. 먼저 requests와 BeautifulSoup의 패키지를 다운받고 네이버 URL을 가져왔다

import requests
from bs4 import BeautifulSoup

URL = 'https://www.naver.com/'

2. 마지막 페이지로 쓰일 것은 이번엔 페이지 번호가 아닌 분류명(리빙,푸드,스포츠,자동차 등등 28개의 종류들)

div태그 중 class명이 "rolling-container"인 것을 찾고 그중 li태그로 이루어진 모든것을 리스트화 시켰다

반복문을 통해 분류명이 텍스트형식으로 리스트에 들어가도록 했다 (그 이유는 get_text함수는 리스트 자체를 못 쓴다)

새로운 리스트에 텍스트를 담아주면 마지막 페이지 수는 리스트의 길이로 체크했다

def get_last_pages():
  result = requests.get(URL)
  s = BeautifulSoup(result.text, "html.parser")
  links = s.find("div",{"class":"rolling-container"}).find_all("li")
  page=[] 	#새로운 리스트
  for i in range(len(links)): #리스트 자체를 get_text하지못하기때문에 반복문을 사용
    page.append(links[i].get_text(strip="\n"))
  max_page = len(page)
  return max_page

 

3. 요소로는 제목과 링크를 가져오기로 했다

def extract_job(html):
  result = requests.get(URL)
  s = BeautifulSoup(result.text, "html.parser")
  title_r = s.find("span",{"class": "td_t"})
  title=title_r.get_text()
  link= s.find("li",{"class":"tl_default"}).find("a")["href"]
  return {
        "title": title,
        "link": link
  }

4. 모든 페이지를 찾고 요소들을 리스화 했다

def extract_jobs(last_page):
  jobs = []
  for page in range(last_page): 
    print(f"Scrapping Indeed: Page: {page}")
    result = requests.get(URL)
    s = BeautifulSoup(result.text, "html.parser")
    results = s.find_all("li", {"class": "tl_default"}) #사실 이 부분만 빼면 나머지는 거의 같다
        job = extract_job(result)
        jobs.append(job)
  return jobs

그리고 깔끔한 마무리~

def get_jobs():
  last_page=get_last_pages()
  jobs=extract_jobs(last_page)
  return jobs

5. CSV파일로 만들기와 6.스프레드시트에 불러오기는 https://jejehoon.tistory.com/15를 참고하면 된다

 

 

완성!!!!!!!!!

 

이것도 따라한거라고 생각하지만 막상 해보니 막히는 부분이 생기면서 시간이 엄청 지체되었다

React JS로 날씨앱 만들기는 따라만하고 직접 다시 만들어보지는 않았었다 

복습을 통해서 다시 떠올리고 또 새로운걸 알아가는 계기가 되었다 좋았다

 

 

다음은 Go언어! 

 

4. 요소들 리스트 화하기

이 단계에서는 전체 데이터를 jobs라는 리스트에 담는 것을 진행했었다

 

원래 title요소를 찾을 때 했었지만 20페이지 모두 매번 볼 수 없었기 때문에 니꼬쌤은 다른 함수로 옮겼다

 

def extract_jobs(last_page):  		#모든데이터 추출하는 함수
  jobs = []							#빈 리스트 jobs만들기
  for page in range(last_page): 	#마지막페이지까지 아래를 실행하는 반복문
    print(f"Scrapping Indeed: Page: {page}")	#되는지 안되는지 보기위한 출력문장
    result = requests.get(f"{URL}&start={page*Limit}")	
    s = BeautifulSoup(result.text, "html.parser")
    results = s.find_all("div", {"class": "jobsearch-SerpJobCard"})#모든 페이지 jobcard가져오기
    for result in results:
        job = extract_job(result)#제목,회사명,위치,링크추출하는 함수 실행
        jobs.append(job) #리스트에 넣기
  return jobs	#반환값

마지막으로 get_jobs함수를 만들어 나머지 세 개의 함수를 잘 정리했다

def get_jobs():
  last_page=get_last_pages()
  jobs=extract_jobs(last_page)
  return jobs

인디드는 끝!!

 

스택오버플로우는 이와 같이 반복 진행하므로 생략한다(물론 약간씩 다른 부분도 있어서 영상을 보는 것이 훌륭하다)

 

https://academy.nomadcoders.co/courses/

 

Academy

[풀스택] 인스타그램 클론 코딩 2.0 인스타그램 백엔드 + 프런트엔드 + 앱 + 서버 [중급] NodeJS, Prisma, GraphQL, Hooks, React Native % Complete

academy.nomadcoders.co

노마드 코더스 아카데미에서 파이썬으로 웹 스크래핑 영상이 있다

무료이다 (20년 3월 기준)

 

5.CSV로 파일 저장

CSV란? 콤마(Comma)로 데이터들을 구분한 파일이라는 뜻 엑셀이나 스프레드시트에 사용할 수 있다

 

인디드나 스택오버플로우와 마찬가지로 save.py를 만들어 코드를 작성한다

(main.py에는 오직 각 모듈에서 나오는 함수들만 있도록 깔끔하게)

 

먼저 save.py에서 파이썬에 내장된 CSV모듈을 import 해준다

(CSV모듈을 import 해주면 csv파일을 작성할 수 있다)

 

또한 각 파일로부터 반환된 jobs를 파이썬에 내장된 함수 open을 통해 생성해준다

 

이때 확장자는 csv , 모드는 w로 해준다

모드란? 파일을 열 때 어떤 형식으로 열지 정하는 것이다 w=write(쓰기), r=read(읽기), a=append(마지막에 추가하기)

 

CSV모듈 중 writer함수를 통해 제목, 회사명, 위치, 링크 순으로 각 위치에 리스트 형식으로 내용을 담아준다

 

우리가 반환한 인디드 값은 딕셔너리 형태이다

 

그렇게 된다면 스프레드시트에서 title: blablalba 이런 형태로 모든 것이 나오게 된다

 

이것을 없애기 위해 value함수를 통해 blablalba만 가져오자 

 

작성한 코드

 

import csv

def save_to_file(jobs):
  file = open("jobs.csv", mode="w")
  writer = csv.writer(file)
  writer.writerow(["title","company","location","link"])
  for job in jobs:
    writer.writerow(list(job.values()))
  return 

main.py에는 이런 식으로 인디드와 스택오버플로를 합쳐 저장했다

from indeed import get_last_pages
from so import get_jobs as get_so_jobs
from save import save_to_file

indeed_jobs = get_indeed_jobs()
so_jobs = get_so_jobs()
jobs = so_jobs + indeed_jobs

save_to_file(jobs)

 

이후 실행시켜보면

이런 형태로 jobs.csv에 저장이 된다 

6.스프레드시트에 불러오기

Repl.it에서 모든 파일을 압축 형식으로 다운로드하여 자신이 알 수 있는 공간에 풀어준다

풀었다면 구글의 온라인 스프레드시트에 들어가 job.csv를 import 해준다

밑의 그림처럼 나온다면 성공이다

감사합니다 니꼬쌤 김취 포테이토 냠냠

 3. 요소들 찾기

이전에 작성한 코드 

import requests
from bs4 import BeautifulSoup

 
result = requests.get(URL)
s = BeautifulSoup(result.text, "html.parser")

pagination = s.find("div", {"class": "pagination"})
links = pagination.find_all('a')

pages = []
for link in links[:-1]:
	pages.append(int(link.string))
    
max_page = pages[-1]

니꼬쌤은 import를 제외한 코드들을 함수로 쪼개는 편이 좋다고 한다 

그 이유는 깔끔하니까

main.py는 가장 먼저 실행되는 메인 파일이다 

니꼬쌤은 indeed.py를 만들어 코드를 작성했다 

커다란 장농에 칸마다 종류별 옷들을 정리하는 것 같았다

 

그래서 이것을 get_last_pages라는 함수를 만들어 그 안에 넣었다

def get_last_pages():
    result = requests.get(URL)
    s = BeautifulSoup(result.text, "html.parser")
    
    pagination = s.find("div", {"class": "pagination"})
    links = pagination.find_all('a')
  
    pages = []
    for link in links[:-1]:
        pages.append(int(link.string))
    
    max_page = pages[-1]
    return max_page

대부분의 함수는 전에 말했듯 반환해야 하는 값이 필요하다 

 

우리가 찾고자하는 값은 마지막 페이지이므로 max_page를 반환 값으로 지정했다

 

이와 마찬가지로 제목과 회사, 위치, 링크의 각각의 태그들을 찾아준다

def extract_job(html):
    title = html.find("div", {"class": "title"}).find("a")["title"]
    company = html.find("span", {"class": "company"})
    company_anchor = company.find("a")
    if company_anchor is not None:
        company = str(company_anchor.string)
    else:
        company = str(company.string)
    company = company.strip()
    location = html.find("div", {"class": "recJobLoc"})["data-rc-loc"]
    job_id = html["data-jk"]
    return {
        "title": title,
        "company": company,
        "location": location,
        "link": f"https://kr.indeed.com/%EC%B1%84%EC%9A%A9%EB%B3%B4%EA%B8%B0?&jk={job_id}"
    }

 

extract_job함수로 모은 요소들

 

title = html.find("div", {"class": "title"}).find("a")["title"]

제목을 찾을 때 a태그의 문자열을 가져왔더니 문자열로 저장되지 않은 부분이 있었다 

 

그래서 a태그 안에 있는 속성값 "title"로 구분을 해주었다 

속성 값을 찾을 때는 [ ]로 표시한다

 

company = html.find("span", {"class": "company"})
    company_anchor = company.find("a")
    if company_anchor is not None:
        company = str(company_anchor.string)
    else:
        company = str(company.string)
    company = company.strip()
    location = html.find("div", {"class": "recJobLoc"})["data-rc-loc"]

회사명을 찾을 때는 a태그의 문자열을 가져왔더니 링크가 저장되지 않은 부분이 있었다

print 해보면 None이 나왔다

 

또 여기는 a태그 안에 있는 속성 값에도 회사명이 없었다

 

그래서 if else 조건문으로 저장된 부분은 a태그의 문자열을 

저장되지 않은 부분은 span태그의 문자열을 가져오도록 했다

location = html.find("div", {"class": "recJobLoc"})["data-rc-loc"]

위치를 찾을 때도 제목처럼 속성값을 사용해 문자열을 찾았다

job_id = html["data-jk"]

링크는 클릭해서 들어가보면 페이지 URL맨 끝에 jk=어쩌고 저쩌고로 끝이 난다

 

어쩌고 저쩌고가 링크들을 구분할 수 있는 것이고 그것은 data-jk라는 속성에 있었다

 

return {
        "title": title,
        "company": company,
        "location": location,
        "link": f"https://kr.indeed.com/%EC%B1%84%EC%9A%A9%EB%B3%B4%EA%B8%B0?&jk={job_id}"
    }

 마지막으로 리스트 형식으로 반환해주고 extract_job함수에 넣어주었다

 

내 턴을 종료했다

 

작성한 코드

import requests
from bs4 import BeautifulSoup

Limit = 50
URL = f'https://kr.indeed.com/%EC%B7%A8%EC%97%85?as_and=Python&as_phr=&as_any=&as_not=&as_ttl=&as_cmp=&jt=all&st=&as_src=&radius=25&fromage=any&limit={Limit}&sort=&psf=advsrch&from=advancedsearch'

def get_last_pages():
    result = requests.get(URL)
    s = BeautifulSoup(result.text, "html.parser")
    pagination = s.find("div", {"class": "pagination"})
    links = pagination.find_all('a')
    print(links)
    pages = []
    for link in links[:-1]:
        pages.append(int(link.string))
    print(pages)
    max_page = pages[-1]
    return max_page

def extract_job(html):
    title = html.find("div", {"class": "title"}).find("a")["title"]
    company = html.find("span", {"class": "company"})
    company_anchor = company.find("a")
    if company_anchor is not None:
        company = str(company_anchor.string)
    else:
        company = str(company.string)
    company = company.strip()
    location = html.find("div", {"class": "recJobLoc"})["data-rc-loc"]
    job_id = html["data-jk"]
    return {
        "title": title,
        "company": company,
        "location": location,
        "link": f"https://kr.indeed.com/%EC%B1%84%EC%9A%A9%EB%B3%B4%EA%B8%B0?&jk={job_id}"
    }

 Limit= 50 은 URL의 jobcard개수를 50개로 제한한다는 의미이다 

25로 고치면 25개를 볼 수 있다

 

2. 페이지 인덱스를 수로 만들기

이전에 작성한 코드

import requests
from bs4 import BeautifulSoup


result = requests.get(URL)
soup = BeautifulSoup(result.text, "html.parser")

URL을 beautifulsoup를 통해 html형태로 파싱을 했다

그렇다면 특정 태그와 클래스명 등을 통해 데이터를 추출할수 있다

 

※html은 페이지의 코드라고 설명할 수 있는데 

<html></html>이런식의 태그형태로 대부분 이루어져있다 

 

요소들마다 가진 고유한 태그 또는 속성들을 찾아야만 데이터를 추출할 수 있다

 

우리가 찾고자하는 것은 페이지 인덱스!

 

페이지의 인덱스는 이렇게 생겼다

html태그들 중에 페이지 인덱스를 표현하는 태그를 찾으려면 

 

페이지에서 우클릭 후 검사를 클릭하면 html태그들이 쫙 나온다

 

거기에 마우스를 갖다대면 그태그가 가리키는 요소들을 이런식으로 표현해준다 

find함수를 통해 이 중 인덱스를 포함하는 태그를 찾아 준다

 

※find함수는 선택한 태그 하나를 찾아준다

find_all함수는 선택한 태그의 모든것(속성,클래스,아이디 등등)을 찾아주며 그것을 리스트의 형태로 나타낸다

pagination = soup.find("div", {"class": "pagination"})
indexs = pagination.find_all('a')

pages라는 변수에 빈리스트를 만들어 준다

 

indexs를 문자열 형태만 추출해 정수형으로 바꿔준 뒤 리스트에 넣어준다

왜냐하면 indexs안에는 태그의 모든 것이 들어있고 우리가 찾고자하는 것은 수이기 때문이다

pages = []
for index in indexs[:-1]:
    pages.append(int(link.string))

[:-1]는 리스트에 있는 문자열 중 처음부터 제일 마지막까지라는 의미이다

나는 10까지의 페이지 인덱스가 있었으므로 마지막 페이지는 10이다

max_page = pages[-1] #max_page = 10

 

작성한 코드

import requests
from bs4 import BeautifulSoup

 
result = requests.get(URL)
s = BeautifulSoup(result.text, "html.parser")

pagination = s.find("div", {"class": "pagination"})
links = pagination.find_all('a')

pages = []
for link in links[:-1]:
	pages.append(int(link.string))
    
max_page = pages[-1]

1. 웹 사이트가져오기

먼저 온라인 라이브러리를 사용한다

 

라이브러리란? 모듈과 동일하다 함수, 클래스 등등이 모여있는 집합체라고 이해할 수 있다

 

파이썬에 내장되어있는 모듈과 다르게 온라인 라이브러리는 강력하고 빠르게 데이터들을 추출할 수 있다

 

니꼬쌤은 requests2와 beautifulsoup4를 추천했다

 

requests2는 URL전체를 가져오는 용도이다

 

beautifulsoup4는 그것을 html태그로 읽어내는 용도이다

 

각각 Repl.it의 Packages에서 검색해서 다운로드할 수 있다

 

그리고 이런 식으로 불러온다

 

import requests
from bs4 import BeautifulSoup

이렇게 두가지 라이브러리를 불러왔다

 

우리가 찾고자하는 데이터는 채용공고의 제목,회사의 이름, 회사의 위치, 지원할 수 있는 링크이다

 

또 마지막페이지 번호가 필요한데 이것은 마지막 페이지까지의 정보를 다 스크래핑하기위해서 필요하다

 

requests 라이브러리를 통해 URL을 가져온다 그리고 result변수에 담아준다

result = requests.get(URL)

그리고 beautifulsoup 라이브러리를 통해 URL을 html형태로 파싱해서 데이터를 추출할 수 있다

마찬가지로 soup변수에 담아준다

파싱이란? 페이지 내 선택한 데이터를 순서나 패턴별로 추출하는 것이다

soup = BeautifulSoup(result.text, "html.parser")

 우리는 html패턴으로 추출했다

 

import requests
from bs4 import BeautifulSoup


result = requests.get(URL)
soup = BeautifulSoup(result.text, "html.parser")

작성한 코드

웹 스크래핑이란?

내가 아는 것은 필요한 정보들을 선택해서 가져올 수 있고

 

사용자가 설정을 통해 매시간마다 정보들이 업데이트되는 것인 줄 알았으나...

 

웹상의 데이터를 추출하는 것은 맞지만 정보들이 업데이트 되는 것은 아니었다

 

다운로드한 게임이 업데이트되려면 새로 무언가가 설치되어야 하는 것과 같은 느낌?

 

일단! 데이터추출 한다

 

니꼬쌤은 indeed와 stackoverflow의 사이트에서 파이썬과 관련된 직장을 스크래핑하려 한다

 

순서는 이렇다

 

1. 웹사이트 가져오기

 

2. 페이지 인덱스를 수로 만들기 

 

3. 찾을 요소들 찾기(제목,작성자,이름,등등 알고자하는 내용)

 

4. 요소들을 리스트화 하기

 

5. CSV파일로 저장 

 

6. 스프레드시트에서 불러오기

 

다음에 계속...

 

 

if else 조건문

형식

if 조건:    if는 조건이 참(True)일 때 내용이 실행됨

   내용

elif 조건:  elif는 if의 조건이 거짓(false)일때 elif의 조건이 참이면 내용이 실행됨 else if의 줄임말

   내용

else:        else는 모든 조건이 다 거짓일때 내용이 실행됨

   내용

 

조건에 쓰이는 연산자

1) 논리연산자

and(둘 다),  or(둘 중 하나),  not(~이 아닌 것, 차집합) 

 

2) 비교 연산자 

<(작다), <=(작같), >(크다), >=(크같), ==(같다),!=(같지 않다), is(그것이 이거니? 이거면 해~), is not(그것이 이게 아니니? 아니면 해~)

 

 

for loop 반복문

형식

for 입력될 시퀀스 in 표현할 시퀀스 :

    반복할 내용

예시

days =("M", "T", "W", "Th", "F")

for day in days:

    print(day)

=>M

    T

    W

    Th

    F

 

Modules 

함수들의 집합? 같은 느낌

 

맨 위에 import 모듈 이름을 해서 불러온다 

 

비유를 하자면 스타크래프트에 Show me the money를 치트키로 치면

핵이 덮어지는 느낌?

 

모든 핵을 불러오면 그 당시 컴퓨터로는 속도가 많이 느려지고 비효율적이었다

 

모듈도 마찬가지로 전체 파일을 불러오기보단 

 

from 모듈 이름 import 함수 이름 이런 식으로 함수 몇 개를 가져오는 것이 좋다

Code Challenge

니꼬쌤이 과제를 내주셨다 7가지 연산 만들고 활용해보기

 

Python Standard Liblary를 참고하여 만들었다

 

함수에 문자로 수를 넣는 사람들을 위해 int()를 이용해 정수로 바꿔주도록 했다

 

이렇게 올리니 니꼬쌤이 칭찬을 해주셨다

+ Recent posts