파이썬 코딩했는데 너무 for문 남발한 건가요?

lhm7877의 이미지

어떤 사이트에 검색 결과 내용을 beautifulsoup를 이용해 파싱해오는 소스인데

소스 설명을 간단히 해드리자면

1. keyword_matrix라는 리스트에 00부터 99까지의 숫자를 넣고

2. 그 숫자들을
http://newnovel.aks.ac.kr/Search?keyword="+j+"&page=1"
ㄴ 이곳에 j에다 넣어서 각각의 페이지 수를 구하고(j는 검색어 , '00'을 검색하였을 때)

3. j 검색 시 페이지 수를 구할때마다 검색 페이지에 1페이지부터 for문으로 각각의 html을 가져오는데

4. 그 안에서 for문으로 테이블을 파싱한다.

이런 방식인데 for문을 남발해서 속도가 느린것 같습니다.
혹은 파싱하려는 사이트가 원할하지 않아 느릴수도 있고요.

제 코딩 방식이 비효율적인 소스인가요?

#-*- coding: utf-8 -*-
 
#if 명령어 수정
#2차 keyword검색
import csv # csv 파일로 저장하기 위한 모듈
import urllib # http 연결용 모듈
import requests # http 연결용 모듈
from bs4 import BeautifulSoup # HTML 문서 파싱라이브러리
 
keyword_matrix = []
for r in range(100):
    keyword_matrix.append('%02i' % r)
 
def get_pages(url):
    src = requests.get(url).text # url에 해당하는 웹페이지를 읽어서 소스코드를 문자열에 저장
    if src.find(">>")!=-1:
        num = src[src.find("=",src.find(">>")-10)+1:src.find(">>")-2]
    else:
        num = 0;
 
    # .find() 는 문자열 내에 특정한 문자, 문자열이 있는지를 찾습니다. 
    # .find("=", 10) 은 11번째 글자부터 "="가 있는지를 찾고, "="의 인덱스를 리턴합니다.
    # 없으면 -1이 리턴됩니다. 
    # 위 코드는 
    # ">>" 가 있는 곳의 앞 9글자 위치부터 "="를 찾아서, "="의 바로 다음 글자부터,
    # ">>" 가 있는 곳의 바로 앞 2글자전까지 잘라냅니다. 
    # 엄청복잡하네요 ㅎㅎ 이런 부분은 정규식으로 하면 좀 편합니다.
 
    # 그 문자열이 숫자인가 보군요. 정수형으로 변환해서 리턴합니다. 
    return int(num)
 
 
 
# with open() as f: 이 구문은
# f = open( ... )
# ....
# f.close() 
# 
# 를 좀 더 예쁘고 안전하게 쓰는 코드입니다. 
# 궁금하시면 context manager 라고 검색해보시면 됩니다.
 
with open('listing_second.csv', 'wb') as f:
    # csv 포맷으로 각 라인을 저장해주는 모듈을 파일 핸들러를 이용해서 초기화합니다.
    writer = csv.writer(f)
 
    # 1 ... 위에서 구한 숫자값 범위를 반복합니다. 
    for j in keyword_matrix:
        #print j.encode('utf-8')
        pages = get_pages("http://newnovel.aks.ac.kr/Search?keyword="+j+"&page=1")
        print pages
        for i in range(1,pages+1):
 
            # url을 합성하고, 
            url = "http://newnovel.aks.ac.kr/Search?keyword="+j+"&page="+str(i)
            print url
            # 그 url의 데이터를 받아와서, html 이라는 이름을 붙입니다.
            u = urllib.urlopen(url)
            try:
                html = u.read()
            finally:
                u.close()
 
            # 받아온 데이터를 BeautifulSoup를 이용해서 파싱합니다. 
            # 이때 파서 모듈은 "lxml"을 씁니다. 
            soup=BeautifulSoup(html, "lxml")
            # BeautifulSoup의 자세한 내용은 라이브러리 문서를 확인하세요.
            # 아마 한글로 제공할겁니다.
 
            # html 중 특정 클래스가 있는 TABLE 요소를 찾습니다.
            table=soup.find("table", {"class":"table table-striped table-hover oldkorean"})
 
            # 테이블의 세번째 TR 요소부터, 
            for tr in table.find_all('tr')[2:]:
 
                # 각 줄의 TD 요소를 얻고, 다시 
                tds = tr.find_all('td')
 
                # 각 TD의 내부 텍스트(text node)를 이어서 리스트로 만듭니다.
                row = [elem.text.encode('utf-8') for elem in tds]
 
                # 4번째 열의 문자열이 "_"를 포함하고 있으면, 
                # 이를 _ 중심으로 쪼개서 4번째 열은 그 왼쪽 것을
                # 오른쪽 나머지는 맨 마지막으로 붙입니다.
                # 그리고 이 행을 csv 파일에 씁니다.
 
                if "_" in row[3]:#문자열 내에 특정 글자가 있는지 검사
                    left, right = row[3].split("_", 1)
                    row[3] = left
                    row.append(right)
 
                    writer.writerow(row)
chanik의 이미지

스크립트는 시간 잡아먹을만한 부분도 눈에 띄지 않고 for 문도 많지 않네요.
키워드별, 페이지수별, TR갯수별, TD갯수별 룹이 들어간 셈이니 적당히 구성된 셈이죠.

원인은 그냥 웹사이트의 응답시간 자체가 느린 것입니다.
간단히 살펴보니 00 ~ 99 까지의 키워드중에서
어떤 키워드는 페이지수가 6667이고 어떤 키워드는 몇십 페이지인데,
페이지수가 많은 키워드일수록 한 페이지 뜨는 시간이 길어지네요.

페이지수 6667인 키워드 00은 한 페이지 뜨는 데 14초 정도 걸리고
페이지수가 90인 키워드 09는 1초 정도 걸리는군요.

키워드 00만 처리하려고 해도, 14초 * 6667페이지 = 93338초 = 약 26시간 걸릴테니
모든 키워드 다 처리하려면 쉬지않고 돌려도 며칠 걸릴 것입니다.

결론은, 해당 웹사이트의 내부 DB처리를 개선하지 않으면 해결되지 않는 문제입니다.

아니면 한 페이지에 출력되는 기본형 갯수를 지금처럼 15개로 고정시키지 말고
임의의 갯수로 지정할 수 있게만 해줘도 뭉텅뭉텅 처리해서 시간을 크게 줄일 수 있겠네요.

lhm7877의 이미지

답변 감사합니다
기본형 갯수는 사이트에서 15개씩 출력해주고 거기서 파싱해오는 방법이라서 일단은 15개씩 하는쪽으로 해야할꺼같아요 ㅎㅎ

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.