인프런 커뮤니티 질문&답변

cherrykim90님의 프로필 이미지
cherrykim90

작성한 질문수

[2024 개정판] 이것이 진짜 크롤링이다 - 실전편 (인공지능 수익화)

서버 요청 거절 시 해결하는 방법 (헤더 추가하기)

크롤링 에러 관련 문의

작성

·

317

0

안녕하세요.

아래 코드를 사용해서 '식품 로봇'이라는 검색어로 크롤링을 시도했는데요. URL에 지정한 기간에 존재하는 모든 기사를 수집하고자 하는데, 총 몇 페이지나 있는지 알 수가 없어서..
페이지수를 2,000으로 넣어서 실행 해보았습니다.

그런데, 크롤링이 잘 진행되다가 에러가 발생해서요. 혹시 이건 어떻게 수정할 수 있을지요?

에러 문구:

=======링크======= 
 https://n.news.naver.com/mnews/article/025/0003239249?sid=101
Traceback (most recent call last):
  File "/Users/유저이름/startcoding/Chapter04/11.마지막페이지확인하기.py", line 64, in <module>
    print("=======제목======= \n", title.text.strip())
                                 ^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'text'

실행 코드:

import requests
from bs4 import BeautifulSoup
import time
import pyautogui
from openpyxl import Workbook
from openpyxl.styles import Alignment

# 사용자입력
keyword = pyautogui.prompt("검색어를 입력하세요")
lastpage = int(pyautogui.prompt("몇 페이지까지 크롤링 할까요?"))

# 엑셀 생성하기
wb = Workbook()

# 엑셀 시트 생성하기
ws = wb.create_sheet(keyword)

# 열 너비 조절
ws.column_dimensions['A'].width = 60
ws.column_dimensions['B'].width = 60
ws.column_dimensions['C'].width = 120

# 행 번호
row = 1

# 페이지 번호
page_num = 1
for i in range(1, lastpage * 10, 10):
    print(f"{page_num}페이지 크롤링 중 입니다.==========================")
    response = requests.get(f"https://search.naver.com/search.naver?sm=tab_hty.top&where=news&query={keyword}&start={i}")
    html = response.text # html은 response의 text 안에 위치함
    soup = BeautifulSoup(html, 'html.parser')
    articles = soup.select("div.info_group") #뉴스 기사 div 10개  추출
    # 기사가 10개니까 for문을 써서 하나하나 추출 필요
    for article in articles:
        links = article.select("a.info") # a 태그, info class인 아이들을 가져옴. = 리스트
        if len(links) >= 2: # 링크가 2개 이상이면
            url = links[1].attrs['href'] # 두번째 링크의 href를 추출
            # 다시 request 날려주기
            response = requests.get(url, headers={'User-agent': 'Mozila/5.0'})
            html = response.text
            soup_sub = BeautifulSoup(html, 'html.parser')
            print(url)
            
            # 연예 뉴스 체크
            if "entertain" in response.url: 
                title = soup_sub.select_one(".end_tit")
                content = soup_sub.select_one("#articeBody")
            elif "sports" in response.url:
                title = soup_sub.select_one("h4.title")
                content = soup_sub.select_one("#newsEndContents")    
                # 본문 내용 안에 불필요한 div, p 삭제  
                divs = content.select("div")
                for div in divs:
                    div.decompose()
                paragraphs = content.select("p")
                for p in paragraphs:
                    p.decompose()
            else: 
                title = soup_sub.select_one(".media_end_head_headline")
                content = soup_sub.select_one("#newsct_article")

            print("=======링크======= \n", url)
            print("=======제목======= \n", title.text.strip())
            print("=======본문======= \n", content.text.strip())
            ws[f'A{row}'] = url # A열에는 URL 기입
            ws[f'B{row}'] = title.text.strip()
            ws[f'C{row}'] = content.text.strip()
            # 자동 줄바꿈
            ws[f'C{row}'].alignment = Alignment(wrap_text=True)
            row = row + 1
            time.sleep(0.3)
    
    # 마지막 페이지 여부 확인하기
    isLastPage = soup.select_one("a.btn_next").attrs['aria-disabled']
    if isLastPage == 'true':
        print("마지막 페이지 입니다.")
        break
    page_num = page_num + 1

wb.save(f'{keyword}_result.xlsx')

답변 2

0

스타트코딩님의 프로필 이미지
스타트코딩
지식공유자

같은 키워드 페이지 수로 테스트 해봤는데
저는 47페이지 까지 크롤링이 잘 돼고 오류가 발생하네요

조금 빠르게 크롤링을 해서 생기는 문제가 아닐까 싶습니다.

time.sleep을 1초로 주고 다시 테스트해보니 220페이지까지 크롤링했네요

 

문제의 원인은

response를 제대로 받아오지 못해서 생기는 현상이었습니다. (500은 서버에 문제가 있을 때 발생하는 에러)

image

  • 제대로 받아올 때까지 retry 할수도 있고

 

if response.status_code == 500:

    continue

과 같이 500에러가 발생한다면 넘어가도록 하는 방법이 있습니다.

 

 


0

안녕하세요, 인프런 AI 인턴이에요. 크롤링 에러에 대해 도움을 드릴게요.

에러 메시지를 보면, ‘NoneType’ 객체에는 ‘text’ 속성이 없다고 나와있네요. 이는 크롤링한 결과가 None인 경우에 발생하는 오류입니다.

에러가 발생하는 줄을 보면, ‘title’ 변수가 None인 상태에서 ‘text’ 속성에 접근하려고 하기 때문에 발생하고 있습니다.

에러가 발생하는 이유는 아마도 크롤링한 페이지에는 제목 태그가 존재하지 않는 경우일 것입니다.

따라서, ‘title’ 변수가 None인 경우에는 제목이 없는 것으로 간주하고 그냥 넘어가도록 수정해보세요. 예를 들어, 다음과 같이 if문 안에 조건을 추가할 수 있습니다.

if title is not None:
    print("=======제목======= \n", title.text.strip())

이렇게 수정해주시면, 제목이 없는 경우에는 해당 줄을 건너뛰고 다음 줄로 넘어가게 되어 에러가 발생하지 않을 것입니다.

추가로, 크롤링할 페이지의 수가 많은 경우에는 네이버에서 IP 차단을 할 수 있으므로 너무 많은 페이지를 크롤링하려고 하지 말아주세요. 웹사이트의 이용 정책을 준수하는 것이 중요해요.

더 필요한 내용이 있으시면 언제든지 물어보세요. 좋은 결과 있기를 바랄게요!

cherrykim90님의 프로필 이미지
cherrykim90

작성한 질문수

질문하기