데이터분석 6기/본캠프

2025-05-24 정적 크롤링 과제

seyeon1130 2025. 5. 24. 16:08

과제 개요

  • AI타임즈(www.aitimes.com) 웹사이트에서 최신 AI 관련 뉴스 기사의 제목, 내용, 날짜 등을 수집
  • 여러 페이지의 뉴스 목록을 수집하고 각 기사의 상세 내용까지 추출
  • 수집한 데이터를 구조화하여 JSON 파일로 저장

구현 단계

  1. 뉴스 목록 페이지 분석 및 요청
    • 페이지 URL 구조 파악
    • HTTP 요청 함수 구현
  2. 뉴스 목록에서 기사 정보 추출
    • BeautifulSoup으로 기사 목록 파싱
    • 제목, 요약, URL, 날짜 등 추출
  3. 기사 상세 내용 수집
    • 각 기사 URL로 접속하여 본문 추출
    • 지연 시간 설정으로 서버 부담 최소화
  4. 데이터 저장 및 분석
    • 수집한 모든 데이터를 JSON 형식으로 저장
    • 날짜 범위 및 기사 개수 통계 작성

url 분석

홈페이지: 'https://www.aitimes.com'

본문 :' 'https://www.aitimes.com/news/articleView.html?idxno=170720'

 

즉 홈페이지 주소에 url 주소만 추가하면 본문으로 갈 수 있다. 그리고 그 url주소는 html 안에 들어있다.

 

 

본문 구하기

base_url = 'https://www.aitimes.com'

우선 홈페에지 url주소를 가져온다.

 

본문 기사 페이지를 보면

article id로 내용들이 다 묶여있다.

그래서 하위 탭을 모두 가져오는 함수를 사용해야한다.

 

p_tags = soup.select("article#article-view-content-div > p")

 

id는 #, class는 .으로 구분한다.

여기서 >p 하면 모든 하위 탭 p를 가져온다는 뜻이다.

 

#상세 페이지
def get_article_body(article_url: str) -> str:
    try:
        res = requests.get(article_url) #사이트 접속
        soup = BeautifulSoup(res.text, "html.parser")
        p_tags = soup.select("article#article-view-content-div > p")
        content = "\n".join([p.get_text(strip=True) for p in p_tags])
        return content
    except Exception as e:
        print(f"[본문 에러] {article_url} → {e}")
        return ""

 

제목, 날짜 등

 

다음은 제목 날짜 등을 가져와야한다.

우선 내가 가져와야하는 부분의 html을 확인한다. 

<div class="view-cont">
  <h4 class="titles">
    <a href="/news/articleView.html?idxno=170721">제목</a>
  </h4>
  <p class="lead line-6x2">
    <a href="/news/articleView.html?idxno=170721">요약</a>
  </p>
  <span class="byline">
    <em>기자 이름</em>
    <em>날짜</em>
  </span>
</div>

지금 구조가 이런식으로 돼있기 때문에 가져와야하는 건

전체 아티클인 "div.view-cont"

soup = BeautifulSoup(html, "html.parser")
    articles = soup.select("div.view-cont")
    data = []

제목 : h4.titles a

 # 제목
        title_tag = article.select_one("h4.titles a")
        title = title_tag.text.strip() if title_tag else ""

요약 : p.lead line a

# 요약
        summary_tag = article.select_one("p.lead a")
        summary = summary_tag.text.strip() if summary_tag else ""

기자 이름, 날짜 :span.byline em

# 기자 이름 + 날짜
        info_tags = article.select("span.byline em")
        reporter = info_tags[0].text.strip() if len(info_tags) > 0 else ""
        date = info_tags[1].text.strip() if len(info_tags) > 1 else ""

 

본문 총 코드

#본문
def parse_article_list(html):
    soup = BeautifulSoup(html, "html.parser")
    articles = soup.select("div.view-cont")
    data = []

    for article in articles:
        # 제목
        title_tag = article.select_one("h4.titles a")
        title = title_tag.text.strip() if title_tag else ""

        # URL
        relative_url = title_tag['href'] if title_tag else ""
        full_url = base_url + relative_url if relative_url else ""

        # 요약
        summary_tag = article.select_one("p.lead a")
        summary = summary_tag.text.strip() if summary_tag else ""

        # 기자 이름 + 날짜
        info_tags = article.select("span.byline em")
        reporter = info_tags[0].text.strip() if len(info_tags) > 0 else ""
        date = info_tags[1].text.strip() if len(info_tags) > 1 else ""

        # 본문 수집
        content = get_article_body(full_url) if full_url else ""

        # 데이터 저장
        data.append({
            "title": title,
            "summary": summary,
            "url": full_url,
            "reporter": reporter,
            "date": date,
            "content": content
        })

    return data

 

html = requests.get("https://www.aitimes.com/news/articleList.html?view_type=sm").text
result = parse_article_list(html)
result

 

이렇게 하면 완성!

 

#저장
# DataFrame 생성
df = pd.DataFrame(result)
 # JSON 파일로 저장 (DataFrame 활용)
json_path = f"article.json"
df.to_json(json_path, orient='records', force_ascii=False, indent=4)

이렇게 저장하면 끝!

'데이터분석 6기 > 본캠프' 카테고리의 다른 글

2025-05-27 스파크 특강 ot  (1) 2025.05.27
2025-05-26 spark  (1) 2025.05.26
2025-05-23 크롤링  (1) 2025.05.23
2025-05-22 API  (0) 2025.05.22
2025-05-21 태블로 메뉴 만들기  (0) 2025.05.21