Post

네이버 종목토론방 크롤링 1

대학 자연어처리 과제 준비중!
데이터 준비중

코드

version 1

selenium 으로 크롤링을 하기 위해 처음에는 Class name으로 요소를 가저오려 했으나 날짜, 추천, 비추천등 다른 필요 없는 요소까지 같은 이름으로 되어있어 다른 방법을 찾아보다 CSS selector를 이용해서 요소를 추출하기로 했다.

코드 version 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import selenium
from selenium import webdriver
import time
import datetime
import pandas as pd
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

start = time.time()

def max_page():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless') #코드 완벽할 시 활성화
    #mobile_emulation = {"deviceName": "iPhone 12 Pro"}
    #chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)#모바일 모드 용도
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("https://finance.naver.com/item/board.naver?code=005930")
    driver.find_element(By.CLASS_NAME, 'pgRR').click()
    max_not_clean = driver.find_element(By.CSS_SELECTOR, '#content > div.section.inner_sub > table:nth-child(3) > tbody > tr > td:nth-child(2) > table > tbody > tr > td.on > a').text
    driver.quit()
    max = max_not_clean.replace(",","")
    print("최대값 : ",max)
    return max

page = 2#int(max_page())#최대 99168


all_comment_url = []

date_text = []
title_text = []
body_text = []

for t in range (1, page + 1):
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless')
    driver = webdriver.Chrome(options=chrome_options)
    print("크롤링 페이지 : ",t)
    url = f"https://finance.naver.com/item/board.naver?code=005930&page={t}"
    driver.get(url = url)
    driver.implicitly_wait(10)

    selector = "#content > div.section.inner_sub > table > tbody > tr > td.title > a"
    links = driver.find_elements(By.CSS_SELECTOR, selector)
    for link in links:
        url = link.get_attribute("href")
        all_comment_url.append(url)
    
    time_page_start = time.time()
    for url in all_comment_url:
        print(url)
        driver.get(url=url) 
        driver.implicitly_wait(10)
        date = driver.find_element(By.CLASS_NAME, 'gray03.p9.tah').text
        title_not_clean = driver.find_element(By.CLASS_NAME, 'c.p15').text
        body_not_clean = driver.find_element(By.ID, 'body').text

        body = body_not_clean.replace("\n","")
        title = title_not_clean.replace("#","")
        date_text.append(date)
        title_text.append(title)
        body_text.append(body)
    time_end_page = time.time()
    sec = (time_end_page - time_page_start)
    result = str(datetime.timedelta(seconds=sec)).split(".")
    print(f"페이지{t} : ",result[0])

driver.quit()

df = pd.DataFrame()
df['date'] = date_text
df['title'] = title_text
df['body'] =  body_text

df.to_csv("data/test.txt", index = False, sep='\t')
df.to_excel("data/test.xlsx")
end = time.time()
sec = (end - start)
result = str(datetime.timedelta(seconds=sec)).split(".")
print("전체 페이지 : ",result[0])


version 2

네이버 주식토론방 크롤링을 하다보면 관리자가 삭제한 글이라는 알람이 뜨며 프로그램을 강제종료 시키기에 exception을 걸어 무시하고 지나갈 수 있게 하였다. 코드에 대한 설명은 추후에 천천히 하나씩 채워나가기로 하겠다.

코드 version 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import selenium
from selenium import webdriver
import time
import datetime
from selenium.common.exceptions import UnexpectedAlertPresentException
import pandas as pd
from selenium.webdriver.common.by import By

start = time.time()

def max_page():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless') #코드 완벽할 시 활성화
    #mobile_emulation = {"deviceName": "iPhone 12 Pro"}
    #chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)#모바일 모드 용도
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("https://finance.naver.com/item/board.naver?code=005930")
    driver.find_element(By.CLASS_NAME, 'pgRR').click()
    max_not_clean = driver.find_element(By.CSS_SELECTOR, '#content > div.section.inner_sub > table:nth-child(3) > tbody > tr > td:nth-child(2) > table > tbody > tr > td.on > a').text
    driver.quit()
    max = max_not_clean.replace(",","")
    print("최대값 : ",max)
    return max

page = 10#int(max_page())#최대 99168


all_comment_url = []

date_text = []
title_text = []
body_text = []

for t in range (1, page + 1):
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless')
    driver = webdriver.Chrome(options=chrome_options)
    print("크롤링 페이지 : ",t)
    url = f"https://finance.naver.com/item/board.naver?code=005930&page={t}"
    driver.get(url = url)
    driver.implicitly_wait(10)

    selector = "#content > div.section.inner_sub > table > tbody > tr > td.title > a"
    links = driver.find_elements(By.CSS_SELECTOR, selector)
    for link in links:
        url = link.get_attribute("href")
        all_comment_url.append(url)
    
    time_page_start = time.time()
    for url in all_comment_url:
        print(url)
        try:
            driver.get(url=url) 
            driver.implicitly_wait(10)
            date = driver.find_element(By.CLASS_NAME, 'gray03.p9.tah').text
            title_not_clean = driver.find_element(By.CLASS_NAME, 'c.p15').text
            body_not_clean = driver.find_element(By.ID, 'body').text
            body = body_not_clean.replace("\n","")
            title = title_not_clean.replace("#","")
            date_text.append(date)
            title_text.append(title)
            body_text.append(body)           

        except UnexpectedAlertPresentException:#무조건 필요 관리자가 삭제한 글을 불러오지 못할 때에 문제가 아주 크게크게 생김 프로그램이 멈춰버려!
            print("\n관리자가 삭제한 글 임\n")

    time_end_page = time.time()
    sec = (time_end_page - time_page_start)
    result = str(datetime.timedelta(seconds=sec)).split(".")
    print(f"페이지{t} : ",result[0])#시간 표시

driver.quit()

#데이터 프레임 만들어서 저장
df = pd.DataFrame()
df['date'] = date_text
df['title'] = title_text
df['body'] =  body_text

df.to_csv("data/1-100.txt", index = False, sep='\t')
df.to_excel("data/1-100.xlsx")
end = time.time()
sec = (end - start)
result = str(datetime.timedelta(seconds=sec)).split(".")
print("전체 페이지 : ",result[0])

version 3

컴퓨터로 코드를 돌려보던 중 점점 한 페이지를 크롤링 하는데 걸리는 시간이 늘어나기에 이상함을 느끼고 코드를 다시 보니 전에 크롤링 한 url이 사라지지 않고 다시 긁어오는 문제를 발견하여 크롤링 한 후 url을 초기화시켜주었다. 지금은 페이지당 7초로 고정되었음.

크롤링 로그를 저장하기 위해 log.txt라는 파일에 저장하였음.

혹시모를 코드의 또다른 오류로 그동안 크롤링 한 것이 증발하지 않게 10, 100 페이지 마다 저장할 수 있도록 변경 하였음.

설명은 추후 최종 결정하고 기록 예정. (2023-11-18 23:19) </br>-> (최종 버전에 #로 기록)

역시 직접 실행해 보고 문제점을 꼭 찾아야 한다는 것을 배웠다… 이걸 모르고 사용했다면.. 으..

코드 version 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import selenium
from selenium import webdriver
import time
import datetime
from selenium.common.exceptions import UnexpectedAlertPresentException
import pandas as pd
from selenium.webdriver.common.by import By
import os.path

#페이지 최대값 자동 불러오기, 굳이 필요 없음
def max_page():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless') #코드 완벽할 시 활성화
    #mobile_emulation = {"deviceName": "iPhone 12 Pro"}
    #chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)#모바일 모드 용도
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("https://finance.naver.com/item/board.naver?code=005930")
    driver.find_element(By.CLASS_NAME, 'pgRR').click()
    max_not_clean = driver.find_element(By.CSS_SELECTOR, '#content > div.section.inner_sub > table:nth-child(3) > tbody > tr > td:nth-child(2) > table > tbody > tr > td.on > a').text
    driver.quit()
    max = max_not_clean.replace(",","")
    print("최대값 : ",max)
    return max

#------------------------------------------------------------------------

file = 'log.txt'
if os.path.isfile(file):
    print("log 파일 존재")
else:
    f = open("log.txt", 'w')
    f.close()


page = 99000#int(max_page())#최대 99168

file = open("log.txt", "a", encoding="UTF-8")
file.write(f"크롤링 페이지 수 : {page}\n\n")
file.close()

start = time.time()
start_middle = time.time()

#중간 저장 리스트 목록
all_comment_url = []
url_100 = []
url_10 = []

date_text_for_100 = []
title_text_for_100 = []
body_text_for_100 = []

date_text_for_10 = []
title_text_for_10 = []
body_text_for_10 = []

date_text = []
title_text = []
body_text = []

#에러(관리자 삭제)수 체크 필수임
error_count = 0

#시간 리셋
tic_10 = 0
tic_100 = 0

#크롤링 시작
for t in range (1, page + 1):
    #크롬 옵션 설정
    chrome_options = webdriver.ChromeOptions()#옵션 드라이버 설정
    chrome_options.add_argument('headless')#웹 드라이버 안띄우고 실행
    chrome_options.add_argument('--no-sandbox')#이걸로 오류를 잡았는데 무엇인지 이해 불가 	Disables the sandbox for all process types that are normally sandboxed. Meant to be used as a browser-level switch for testing purposes only
    driver = webdriver.Chrome(options=chrome_options)#옵션 적용

    print("크롤링 페이지 : ",t)
    url = f"https://finance.naver.com/item/board.naver?code=005930&page={t}"#comment 크롤링용 링크
    driver.get(url = url)#링크 접속
    driver.implicitly_wait(10)#열릴 때 까지 대기

    selector = "#content > div.section.inner_sub > table > tbody > tr > td.title > a"#크롤링 할 url의 CSS selector위치
    links = driver.find_elements(By.CSS_SELECTOR, selector)#요소(link) 찾아서 links에 전부 보관
    
    #href값 즉 실질적으로 우리가 필요한 url text를 추출
    for link in links:
        url = link.get_attribute("href")
        all_comment_url.append(url)
    
    time_page_start = time.time()

    for url in all_comment_url:
        #print(url)
        try:
            driver.get(url=url) 
            driver.implicitly_wait(10)
            date = driver.find_element(By.CLASS_NAME, 'gray03.p9.tah').text
            title_not_clean = driver.find_element(By.CLASS_NAME, 'c.p15').text
            body_not_clean = driver.find_element(By.ID, 'body').text
            body = body_not_clean.replace("\n","")
            title = title_not_clean.replace("#","")
            #append
            date_text_for_100.append(date)
            date_text_for_10.append(date)
            date_text.append(date)
            title_text_for_100.append(title)
            title_text_for_10.append(title)
            title_text.append(title)
            body_text_for_100.append(body)
            body_text_for_10.append(body)
            body_text.append(body)         
            url_100.append(url)
            url_10.append(url)  
        
        except UnexpectedAlertPresentException:#무조건 필요 관리자가 삭제한 글을 불러오지 못할 때에 문제가 아주 크게크게 생김 프로그램이 멈춰버려!
            #print("\n관리자가 삭제한 글 임\n")
            error_count = error_count + 1
    all_comment_url = []#리셋 해줘야함 미친미친

    #10페이지 마다 저장(혹시 모를 오류 발생으로 인한 데이터 소실 해소)
    if(t%10 == 0):
        tic_10 = tic_10 + 10
        toc_10 = tic_10 - 10
        df_for_10 = pd.DataFrame()
        df_for_10['date'] = date_text_for_10
        df_for_10['title'] = title_text_for_10
        df_for_10['body'] = body_text_for_10
        df_for_10['url'] = url_10

        date_text_for_10.clear()
        title_text_for_10.clear()
        body_text_for_10.clear()
        url_10.clear()

        df_for_10.to_csv(f"data/for10/{toc_10}_{tic_10}.txt", index = False, sep='\t')
        df_for_10.to_excel(f"data/for10/{toc_10}_{tic_10}.xlsx")

    if(t%100 == 0):
        tic_100 = tic_100 + 100
        toc_100 = tic_100 - 100
        df_for_100 = pd.DataFrame()
        df_for_100['date'] = date_text_for_100
        df_for_100['title'] = title_text_for_100
        df_for_100['body'] = body_text_for_100
        df_for_100['url'] = url_100
        
        date_text_for_100.clear()
        title_text_for_100.clear()
        body_text_for_100.clear()
        url_100.clear()

        df_for_10.to_csv(f"data/for10/{toc_100}_{tic_100}.txt", index = False, sep='\t')
        df_for_10.to_excel(f"data/for10/{toc_100}_{tic_100}.xlsx")


    end_middle = time.time()
    time_end_page = time.time()
    sec = (time_end_page - time_page_start)
    sec_middle = (end_middle - start_middle)
    result_middle = str(datetime.timedelta(seconds=sec_middle)).split(".")
    result = str(datetime.timedelta(seconds=sec)).split(".")
    print(f"페이지{t}시간 : ",result[0])#시간 표시
    print(f"현재까지 시간 : ", result_middle[0])#지금까지 시간 표시
    print(f"관리자 삭제 글 수 : {error_count}")#관리자 삭제 글 수 
    today = time
    file = open("log.txt", "a", encoding="UTF-8")
    text = f"시간 : {today.strftime('%Y-%m-%d %H:%M:%S')}\n페이지{t}의 걸린시간 : {result[0]}\n현재까지 걸린 시간 : {result_middle[0]}\n관리자가 삭제한(error)수 : {error_count}\n\n"
    file.write(text)
    file.close()
driver.quit()

#전체 데이터 프레임 만들어서 저장
df = pd.DataFrame()
df['date'] = date_text
df['title'] = title_text
df['body'] =  body_text

df.to_csv(f"data/0_{page}_result.txt", index = False, sep='\t')
df.to_excel(f"data/0_{page}_result.xlsx")
end = time.time()
sec = (end - start)
result = str(datetime.timedelta(seconds=sec)).split(".")
print("전체 페이지 : ",result[0])

file = open("log.txt", "a", encoding="UTF-8")
file.write("--------------------------------------------------------\n\n\n")
file.close()
#2023-11-18 미친미친 어쩐지 자꾸 중첩되더라, url이 자꾸 점점 늘어서 그럼, 20페이지 40분에서 4분으로 감소, 35페이지 7분, 한 페이지당 7초


log.txt
크롤링 페이지 수 : 3

시간 : 2023-11-18 23:11:22
페이지1의 걸린시간 : 0:00:08
현재까지 걸린 시간 : 0:00:11
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:11:35
페이지2의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:24
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:11:48
페이지3의 걸린시간 : 0:00:08
현재까지 걸린 시간 : 0:00:37
관리자가 삭제한(error)수 : 0

--------------------------------------------------------


크롤링 페이지 수 : 3

시간 : 2023-11-18 23:13:03
페이지1의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:11
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:13:14
페이지2의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:23
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:13:27
페이지3의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:36
관리자가 삭제한(error)수 : 0

--------------------------------------------------------


크롤링 페이지 수 : 99000

시간 : 2023-11-18 23:15:32
페이지1의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:10
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:15:45
페이지2의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:23
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:15:58
페이지3의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:36
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:16:11
페이지4의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:00:49
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:16:23
페이지5의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:01:01
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:16:36
페이지6의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:01:14
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:16:49
페이지7의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:01:26
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:17:01
페이지8의 걸린시간 : 0:00:07
현재까지 걸린 시간 : 0:01:39
관리자가 삭제한(error)수 : 0

시간 : 2023-11-18 23:17:14
페이지9의 걸린시간 : 0:00:06
현재까지 걸린 시간 : 0:01:51
관리자가 삭제한(error)수 : 0

그리고 다시한번 오류 발생, 이번에는 저번과 다르게 전체 url을 가져오는 과정에서 문제가 생긴 듯 하다. 바로 내일 ver4가 만들어지겠군…

그리고 또다른 오류...
Traceback (most recent call last):
  File "d:\AFTER 2021-11-21\programing\NLP_TERM_PROJECT\crawler.py", line 82, in <module>
    links = driver.find_elements(By.CSS_SELECTOR, selector)#요소(link) 찾아서 links에 전부 보관  
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\AFTER 2021-11-21\programing\NLP_TERM_PROJECT\NLP_TP\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 771, in find_elements
    return self.execute(Command.FIND_ELEMENTS, {"using": by, "value": value})["value"] or []     
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\AFTER 2021-11-21\programing\NLP_TERM_PROJECT\NLP_TP\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 347, in execute
    self.error_handler.check_response(response)
  File "D:\AFTER 2021-11-21\programing\NLP_TERM_PROJECT\NLP_TP\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 228, in check_response
    raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
selenium.common.exceptions.UnexpectedAlertPresentException: Alert Text: 잘못된 접근입니다.
Message: unexpected alert open: {Alert text : 잘못된 접근입니다.}

이 문제는 추후에 알게되었지만 그냥 url으로서는 접근이 불가능 하고 referer를 참조해야지 접근할 수 있는 url에 접근해서 뜬 오류 문구이다.

version 4

이번에 찾은 문제점은 저번 것에 이어서 추가적으로

1
openpyxl.utils.exceptions.IllegalCharacterError#excel 특수문자 오류

이라는 오류를 만나게 되었고 이를 해결하기 위해

1
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE

을 이용해 특수문자를 제거하는 작업을 추가해 주었다.

ver4

변경사항 : 크롤링용 url을 로딩하던 도중 오류 발생, 특수문자 exel파일로 옮기기 불가, 파일 로그 오류 url추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import selenium
from selenium import webdriver
import time
import datetime
from selenium.common.exceptions import UnexpectedAlertPresentException
import pandas as pd
from selenium.webdriver.common.by import By
import os.path
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE

#페이지 최대값 자동 불러오기, 굳이 필요 없음
def max_page():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless') #코드 완벽할 시 활성화
    #mobile_emulation = {"deviceName": "iPhone 12 Pro"}
    #chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)#모바일 모드 용도
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("https://finance.naver.com/item/board.naver?code=005930")
    driver.find_element(By.CLASS_NAME, 'pgRR').click()
    max_not_clean = driver.find_element(By.CSS_SELECTOR, '#content > div.section.inner_sub > table:nth-child(3) > tbody > tr > td:nth-child(2) > table > tbody > tr > td.on > a').text
    driver.quit()
    max = max_not_clean.replace(",","")
    print("최대값 : ",max)
    return max

#------------------------------------------------------------------------

file = 'log.txt'
if os.path.isfile(file):
    print("log 파일 존재")
else:
    f = open("log.txt", 'w')
    f.close()

start_page = 1#0페이지 존재 안함 0넣으면 문제가 좀 많이많이 커져용
page = 99000#int(max_page())#최대 99168

file = open("log.txt", "a", encoding="UTF-8")
file.write(f"\n-------------------------------\n크롤링 시작 페이지 수: {start_page}\n크롤링 총 페이지 수 : {page}\n\n")
file.close()

start = time.time()
start_middle = time.time()

#중간 저장 리스트 목록
all_comment_url = []
url_100 = []
url_10 = []

date_text_for_100 = []
title_text_for_100 = []
body_text_for_100 = []

date_text_for_10 = []
title_text_for_10 = []
body_text_for_10 = []

date_text = []
title_text = []
body_text = []

#에러(관리자 삭제)수 체크 필수임
error_count = 0

#시간 리셋
tic_10 = 0
tic_100 = 0

#크롤링 시작
for t in range (start_page, page + 1):
    try:
        #크롬 옵션 설정
        chrome_options = webdriver.ChromeOptions()#옵션 드라이버 설정
        chrome_options.add_argument('headless')#웹 드라이버 안띄우고 실행
        chrome_options.add_argument('--no-sandbox')#이걸로 오류를 잡았는데 무엇인지 이해 불가 	Disables the sandbox for all process types that are normally sandboxed. Meant to be used as a browser-level switch for testing purposes only
        chrome_options.add_argument('disable-gpu')#gpu사용 안함
        driver = webdriver.Chrome(options=chrome_options)#옵션 적용

        print("크롤링 페이지 : ",t)
        url = f"https://finance.naver.com/item/board.naver?code=005930&page={t}"#comment 크롤링용 링크
        driver.get(url = url)#링크 접속
        driver.implicitly_wait(10)#열릴 때 까지 대기

        selector = "#content > div.section.inner_sub > table > tbody > tr > td.title > a"#크롤링 할 url의 CSS selector위치
        links = driver.find_elements(By.CSS_SELECTOR, selector)#요소(link) 찾아서 links에 전부 보관
        
        #href값 즉 실질적으로 우리가 필요한 url text를 추출
        for link in links:
            url = link.get_attribute("href")
            all_comment_url.append(url)
        
        time_page_start = time.time()

        for url in all_comment_url:
            #print(url)
            try:
                driver.get(url=url) 
                driver.implicitly_wait(10)
                date = driver.find_element(By.CLASS_NAME, 'gray03.p9.tah').text
                title_not_clean = driver.find_element(By.CLASS_NAME, 'c.p15').text
                body_not_clean = driver.find_element(By.ID, 'body').text
                body = body_not_clean.replace("\n","")
                title = title_not_clean.replace("#","")
                #append
                date_text_for_100.append(date)
                date_text_for_10.append(date)
                date_text.append(date)
                title_text_for_100.append(title)
                title_text_for_10.append(title)
                title_text.append(title)
                body_text_for_100.append(body)
                body_text_for_10.append(body)
                body_text.append(body)         
                url_100.append(url)
                url_10.append(url)  
            
            except UnexpectedAlertPresentException:#무조건 필요 관리자가 삭제한 글을 불러오지 못할 때에 문제가 아주 크게크게 생김 프로그램이 멈춰버려!
                #print("\n관리자가 삭제한 글 임\n")
                error_count = error_count + 1
        all_comment_url = []#리셋 해줘야함 미친미친

        #10페이지 마다 저장(혹시 모를 오류 발생으로 인한 데이터 소실 해소)
        if(t%10 == 0):
            tic_10 = tic_10 + 10
            toc_10 = tic_10 - 10
            df_for_10 = pd.DataFrame()
            df_for_10['date'] = date_text_for_10
            df_for_10['title'] = title_text_for_10
            df_for_10['body'] = body_text_for_10
            df_for_10['url'] = url_10

            date_text_for_10.clear()
            title_text_for_10.clear()
            body_text_for_10.clear()
            url_10.clear()

            df_for_10.to_csv(f"data/for10/{toc_10}_{tic_10}.txt", index = False, sep='\t')
            df_for_10.to_excel(f"data/for10/{toc_10}_{tic_10}.xlsx")
            file = open("log.txt", "a", encoding="UTF-8")
            txt_text = f"{t}파일 생성 : {toc_10}_{tic_10}.txt"
            file.write(txt_text)
            file.close()


        if(t%100 == 0):
            tic_100 = tic_100 + 100
            toc_100 = tic_100 - 100
            df_for_100 = pd.DataFrame()
            df_for_100['date'] = date_text_for_100
            df_for_100['title'] = title_text_for_100
            df_for_100['body'] = body_text_for_100
            df_for_100['url'] = url_100
            
            date_text_for_100.clear()
            title_text_for_100.clear()
            body_text_for_100.clear()
            url_100.clear()

            df_for_10.to_csv(f"data/for10/{toc_100}_{tic_100}.txt", index = False, sep='\t')
            df_for_10.to_excel(f"data/for10/{toc_100}_{tic_100}.xlsx")
            file = open("log.txt", "a", encoding="UTF-8")
            txt_text = f"{t}파일 생성 : {toc_100}_{tic_100}.txt"
            file.write(txt_text)
            file.close()


        end_middle = time.time()
        time_end_page = time.time()
        sec = (time_end_page - time_page_start)
        sec_middle = (end_middle - start_middle)
        result_middle = str(datetime.timedelta(seconds=sec_middle)).split(".")
        result = str(datetime.timedelta(seconds=sec)).split(".")
        print(f"페이지{t}시간 : ",result[0])#시간 표시
        print(f"현재까지 시간 : ", result_middle[0])#지금까지 시간 표시
        print(f"관리자 삭제 글 수 : {error_count}")#관리자 삭제 글 수 
        today = time
        file = open("log.txt", "a", encoding="UTF-8")
        text = f"시간 : {today.strftime('%Y-%m-%d %H:%M:%S')}\n페이지{t}의 걸린시간 : {result[0]}\n현재까지 걸린 시간 : {result_middle[0]}\n관리자가 삭제한(error)수 : {error_count}\n\n"
        file.write(text)
        file.close()
    except UnexpectedAlertPresentException:
        print(url)
        print("크롤링용 url 오류 발생지")
        file = open("log.txt", "a", encoding="UTF-8")
        error_text = f"크롤링용 url 오류 발생 {url}"
        file.write(error_text)
        file.close()

driver.quit()

#전체 데이터 프레임 만들어서 저장
df = pd.DataFrame()
df['date'] = date_text
df['title'] = title_text
df['body'] =  body_text

df.to_csv(f"data/0_{page}_result.txt", index = False, sep='\t')
page = ILLEGAL_CHARACTERS_RE.sub(r'', text)#엑셀파일 불가한 특수문자 제거 -> 7초에서 11초 정도로 시간 증가
df.to_excel(f"data/0_{page}_result.xlsx")
end = time.time()
sec = (end - start)
result = str(datetime.timedelta(seconds=sec)).split(".")
print("전체 페이지 : ",result[0])

file = open("log.txt", "a", encoding="UTF-8")
file.write("--------------------------------------------------------\n\n\n")
file.close()
#2023-11-18 미친미친 어쩐지 자꾸 중첩되더라, url이 자꾸 점점 늘어서 그럼, 20페이지 40분에서 4분으로 감소, 35페이지 7분, 한 페이지당 7초
#2023-11-21 였는데 특수문자 처리 하는 속도가 늘어나서 페이지당 10초로 증가


에서 결국 바로 또 다른 오류 발생

오류
DevTools listening on ws://127.0.0.1:2469/devtools/browser/0428c71e-8a66-41c2-abcd-fa36b4ebde1a
크롤링 페이지 :  20
Traceback (most recent call last):
  File "d:\CODE\NLP_TERM_PROJECT\crawler.py", line 138, in <module>
    df_for_10.to_excel(f"data/for10/{toc_10}_{tic_10}.xlsx") 
  File "D:\CODE\NLP_TERM_PROJECT\NLP_TERM_PROJECT_VENV\Lib\site-packages\pandas\core\generic.py", line 2345, in to_excel  
    formatter.write(
  File "D:\CODE\NLP_TERM_PROJECT\NLP_TERM_PROJECT_VENV\Lib\site-packages\pandas\io\formats\excel.py", line 955, in write  
    writer._write_cells(
  File "D:\CODE\NLP_TERM_PROJECT\NLP_TERM_PROJECT_VENV\Lib\site-packages\pandas\io\excel\_openpyxl.py", line 490, in _write_cells
    xcell.value, fmt = self._value_with_fmt(cell.val)
    ^^^^^^^^^^^
  File "D:\CODE\NLP_TERM_PROJECT\NLP_TERM_PROJECT_VENV\Lib\site-packages\openpyxl\cell\cell.py", line 218, in value       
    self._bind_value(value)
  File "D:\CODE\NLP_TERM_PROJECT\NLP_TERM_PROJECT_VENV\Lib\site-packages\openpyxl\cell\cell.py", line 197, in _bind_value 
    value = self.check_string(value)
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\CODE\NLP_TERM_PROJECT\NLP_TERM_PROJECT_VENV\Lib\site-packages\openpyxl\cell\cell.py", line 165, in check_string
    raise IllegalCharacterError(f"{value} cannot be used in worksheets.")
openpyxl.utils.exceptions.IllegalCharacterError: => 윤대통령, 영국.프랑스 방문 타이밍이 기가 막히게 좋구나==> 사우디 ,이탈리아 ,한국 부산 3파전 1차투표로 2개국 선정 그리고 결승은 2차 투표로1차투표 예상 2개국으로 한국 ,사우디로 , 한국은 이탈리아 투표한 국가들 적극 포섭 전략오는 2030년 세계박람회(엑스포)  개최 도시를 정하는 국제박람회기구(BIE) 총회가 어느덧 1주일여 앞으로 다가왔다. BIE는 오는 28일(현지시간) 프랑스 파리에서 총회를 열고 부산과 사우디아라비아 리야드,이탈인과 국가가 실력을 겨루는 자리라면 엑스포는 한 국가의 산업,과학기술,문화 수준을 과시하는 경제문화올림픽이라 할 수 있다. 엑스포는 전시 기간과 규모 등에 따라 등록박람회와인정박람회로 나뉘는데, 한국은 1993년 대전과2012년 전남 여수에서 인정박람회를 개최한 바 있다.부산이 도전장을 낸 것은 등록박람회로, 한국이 유치에  성공한다면 올림픽, 월드컵등 3대 글로벌 이벤트를 모두개최하는 7번째 국가가 된다.유치위에 따르면 부산엑스포가 열리면 관람객만 3천500만명에 이르고 60조원 이상의생산유발, 50만명의 고용창출 효과를 낳을 것으로 추산된다. 비단 경제적 효과뿐만 아니라 IT와 미디어 등 '스마트 혁신' 강국으로 서의국가 위상을 높이고 한류 등 소 프트파워를 확산시킬 수 있는 계기가 될 것으로 기대된다. cannot be used in worksheets.

읽어보니 아무래도 excel worksheets에 들어갈 수 있는 최대 글 길이를 넘어선 듯 하다. 좀 더 생각해 보아햐 할 듯한 문제다…(지금보니 특수문자 오류였다.)

version 5

그렇다면 문제를 해결하기 위해 아예 excel이 아닌 csv형식을 사용하는 것은 어떤가? 훨씬 빠르고 제약이 없는 csv를 이용해서 문제 해결 -> excel써도 특수문자 제외하면 사용 가능

ver5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import selenium
from selenium import webdriver
import time
import datetime
from selenium.common.exceptions import UnexpectedAlertPresentException
import pandas as pd
from selenium.webdriver.common.by import By
import os.path
#from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE

#페이지 최대값 자동 불러오기, 굳이 필요 없음
def max_page():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless') #코드 완벽할 시 활성화
    #mobile_emulation = {"deviceName": "iPhone 12 Pro"}
    #chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)#모바일 모드 용도
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("https://finance.naver.com/item/board.naver?code=005930")
    driver.find_element(By.CLASS_NAME, 'pgRR').click()
    max_not_clean = driver.find_element(By.CSS_SELECTOR, '#content > div.section.inner_sub > table:nth-child(3) > tbody > tr > td:nth-child(2) > table > tbody > tr > td.on > a').text
    driver.quit()
    max = max_not_clean.replace(",","")
    print("최대값 : ",max)
    return max

#------------------------------------------------------------------------

file = 'log.txt'
if os.path.isfile(file):
    print("log 파일 존재")
else:
    f = open("log.txt", 'w')
    f.close()

start_page = 1#0페이지 존재 안함 0넣으면 문제가 좀 많이많이 커져용
page = 99000#int(max_page())#최대 99168

file = open("log.txt", "a", encoding="UTF-8")
file.write(f"\n-------------------------------\n크롤링 시작 페이지 수: {start_page}\n크롤링 총 페이지 수 : {page}\n\n")
file.close()

start = time.time()
start_middle = time.time()

#중간 저장 리스트 목록
all_comment_url = []
url_100 = []
url_10 = []

date_text_for_100 = []
title_text_for_100 = []
body_text_for_100 = []

date_text_for_10 = []
title_text_for_10 = []
body_text_for_10 = []

date_text = []
title_text = []
body_text = []

#에러(관리자 삭제)수 체크 필수임
error_count = 0

#시간 리셋
tic_10 = 0
tic_100 = 0

#크롤링 시작
for t in range (start_page, page + 1):
    try:
        #크롬 옵션 설정
        chrome_options = webdriver.ChromeOptions()#옵션 드라이버 설정
        chrome_options.add_argument('headless')#웹 드라이버 안띄우고 실행
        chrome_options.add_argument('--no-sandbox')#이걸로 오류를 잡았는데 무엇인지 이해 불가 	Disables the sandbox for all process types that are normally sandboxed. Meant to be used as a browser-level switch for testing purposes only
        chrome_options.add_argument('disable-gpu')#gpu사용 안함
        driver = webdriver.Chrome(options=chrome_options)#옵션 적용

        print("크롤링 페이지 : ",t)
        url = f"https://finance.naver.com/item/board.naver?code=005930&page={t}"#comment 크롤링용 링크
        driver.get(url = url)#링크 접속
        driver.implicitly_wait(10)#열릴 때 까지 대기

        selector = "#content > div.section.inner_sub > table > tbody > tr > td.title > a"#크롤링 할 url의 CSS selector위치
        links = driver.find_elements(By.CSS_SELECTOR, selector)#요소(link) 찾아서 links에 전부 보관
        
        #href값 즉 실질적으로 우리가 필요한 url text를 추출
        for link in links:
            url = link.get_attribute("href")
            all_comment_url.append(url)
        
        time_page_start = time.time()

        for url in all_comment_url:
            #print(url)
            try:
                driver.get(url=url) 
                driver.implicitly_wait(10)
                date = driver.find_element(By.CLASS_NAME, 'gray03.p9.tah').text
                title_not_clean = driver.find_element(By.CLASS_NAME, 'c.p15').text
                body_not_clean = driver.find_element(By.ID, 'body').text
                body = body_not_clean.replace("\n","")
                title = title_not_clean.replace("#","")
                #append
                date_text_for_100.append(date)
                date_text_for_10.append(date)
                date_text.append(date)
                title_text_for_100.append(title)
                title_text_for_10.append(title)
                title_text.append(title)
                body_text_for_100.append(body)
                body_text_for_10.append(body)
                body_text.append(body)         
                url_100.append(url)
                url_10.append(url)  
            
            except UnexpectedAlertPresentException:#무조건 필요 관리자가 삭제한 글을 불러오지 못할 때에 문제가 아주 크게크게 생김 프로그램이 멈춰버려!
                #print("\n관리자가 삭제한 글 임\n")
                error_count = error_count + 1
        all_comment_url = []#리셋 해줘야함 미친미친

        #10페이지 마다 저장(혹시 모를 오류 발생으로 인한 데이터 소실 해소)
        if(t%10 == 0):
            tic_10 = tic_10 + 10
            toc_10 = tic_10 - 10
            df_for_10 = pd.DataFrame()
            df_for_10['date'] = date_text_for_10
            df_for_10['title'] = title_text_for_10
            df_for_10['body'] = body_text_for_10
            df_for_10['url'] = url_10

            date_text_for_10.clear()
            title_text_for_10.clear()
            body_text_for_10.clear()
            url_10.clear()

            df_for_10.to_csv(f"data/for10/{toc_10}_{tic_10}.txt", index = False, sep='\t')
            df_for_10.to_csv(f"data/for10/{toc_10}_{tic_10}.csv", index=False, sep='\t')
            file = open("log.txt", "a", encoding="UTF-8")
            txt_text = f"{t}파일 생성 : {toc_10}_{tic_10}.txt"
            file.write(txt_text)
            file.close()


        if(t%100 == 0):
            tic_100 = tic_100 + 100
            toc_100 = tic_100 - 100
            df_for_100 = pd.DataFrame()
            df_for_100['date'] = date_text_for_100
            df_for_100['title'] = title_text_for_100
            df_for_100['body'] = body_text_for_100
            df_for_100['url'] = url_100
            
            date_text_for_100.clear()
            title_text_for_100.clear()
            body_text_for_100.clear()
            url_100.clear()

            df_for_10.to_csv(f"data/for10/{toc_100}_{tic_100}.txt", index = False, sep='\t')
            df_for_10.to_csv(f"data/for10/{toc_100}_{tic_100}.csv", index=False, sep='\t')
            file = open("log.txt", "a", encoding="UTF-8")
            txt_text = f"{t}파일 생성 : {toc_100}_{tic_100}.txt"
            file.write(txt_text)
            file.close()


        end_middle = time.time()
        time_end_page = time.time()
        sec = (time_end_page - time_page_start)
        sec_middle = (end_middle - start_middle)
        result_middle = str(datetime.timedelta(seconds=sec_middle)).split(".")
        result = str(datetime.timedelta(seconds=sec)).split(".")
        print(f"페이지{t}시간 : ",result[0])#시간 표시
        print(f"현재까지 시간 : ", result_middle[0])#지금까지 시간 표시
        print(f"관리자 삭제 글 수 : {error_count}")#관리자 삭제 글 수 
        today = time
        file = open("log.txt", "a", encoding="UTF-8")
        text = f"시간 : {today.strftime('%Y-%m-%d %H:%M:%S')}\n페이지{t}의 걸린시간 : {result[0]}\n현재까지 걸린 시간 : {result_middle[0]}\n관리자가 삭제한(error)수 : {error_count}\n\n"
        file.write(text)
        file.close()
    except UnexpectedAlertPresentException:
        print(url)
        print("크롤링용 url 오류 발생지")
        file = open("log.txt", "a", encoding="UTF-8")
        error_text = f"크롤링용 url 오류 발생 {url}"
        file.write(error_text)
        file.close()

driver.quit()

#전체 데이터 프레임 만들어서 저장
df = pd.DataFrame()
df['date'] = date_text
df['title'] = title_text
df['body'] =  body_text

df.to_csv(f"data/0_{page}_result.txt", index = False, sep='\t')
#page = ILLEGAL_CHARACTERS_RE.sub(r'', text)#엑셀파일 불가한 특수문자 제거 -> 7초에서 11초 정도로 시간 증가
df.to_csv(f"data/0_{page}_result.csv", index=False, sep='\t')#엑셀로 포함 불가능한 길이의 문장들이 존재
end = time.time()
sec = (end - start)
result = str(datetime.timedelta(seconds=sec)).split(".")
print("전체 페이지 : ",result[0])

file = open("log.txt", "a", encoding="UTF-8")
file.write("--------------------------------------------------------\n\n\n")
file.close()
#2023-11-18 미친미친 어쩐지 자꾸 중첩되더라, url이 자꾸 점점 늘어서 그럼, 20페이지 40분에서 4분으로 감소, 35페이지 7분, 한 페이지당 7초
#2023-11-21 excel 파일로 만들기에는 문장이 길어서 넣지 못하는 경우가 생겨 csv로 생성

음… 여전히 100페이지를 넘어가는 순간 멈춰버린다.. 이유를 더 찾아보기로 하자.

version6

찾았다 아무래도 내가 user-agent를 설정해 주지 않아 네이버 서버에서 봇으로 판단하고 차단했다는 생각이 든다. 고로 user-agent를 추가해 주었다.

version7

위 방법을 써봤으나 이상하게도 주식토론방 100페이지는 링크로 접속 할 수 있으나 주식토론방 101페이지잘못된 접근이라는 문구가 뜨며 접근을 차단해 버린다. wrong_connect헌데 주식토론방 100페이지에서 직접 101페이지를 클릭해서 들어가면 접근이 가능하다. 난 이런일이 처음이다보니 여기저기 찾아보았고 request모듈을 사용할 때 reference라는 것을 보았다. 이것은 봇을 잡기 위한 최소한의 보안으로 이 링크를 가지고 있더라도 정해진 위치에서 오지 않는다면 접근할 수 없게 만들어 놓은 것이다. (아마도)

이것을 해결하기 위해 selenium에서 reference 값을 조정할 수 있나 찾아보았지만 proxy를 쓰는 방법 외에는 공식적인 방법이 없다고들 하였다. 고로 내가 생각한 방법은 글을 불러오기 위한 url을 아예 request에 header값을 넣어 가져오기로 한 것이다. 그리고 성공했다!!! 하루하루 발전해가니 기분이 좋다!

코드 ver7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import selenium
from selenium import webdriver
import time
import datetime
from selenium.common.exceptions import UnexpectedAlertPresentException
import pandas as pd
from selenium.webdriver.common.by import By
import os.path
from url_parser import url_parser as up

#------------------------------------------------------------------------

file = 'log.txt'
if os.path.isfile(file):
    print("log 파일 존재")
else:
    f = open("log.txt", 'w')
    f.close()

start_page = 1#0페이지 존재 안함 0넣으면 문제가 좀 많이많이 커져용
end_page = 10#int(max_page())#최대 99168

file = open("log.txt", "a", encoding="UTF-8")
file.write(f"\n-------------------------------\n크롤링 시작 페이지 수: {start_page}\n크롤링 총 페이지 수 : {end_page}\n\n")
file.close()

start = time.time()
start_middle = time.time()

#중간 저장 리스트 목록
all_comment_url = []
url_100 = []
url_10 = []

date_text_for_100 = []
title_text_for_100 = []
body_text_for_100 = []

date_text_for_10 = []
title_text_for_10 = []
body_text_for_10 = []

date_text = []
title_text = []
body_text = []

#에러(관리자 삭제)수 체크 필수임
error_count = 0

#시간 리셋
tic_10 = 0
tic_100 = 0

#크롤링 시작


for t in range (start_page, end_page+1):
    all_comment_url = up(t, t)    
    time_page_start = time.time()
    chrome_options = webdriver.ChromeOptions()#옵션 드라이버 설정
    chrome_options.add_argument('headless')#웹 드라이버 안띄우고 실행
    chrome_options.add_argument('--no-sandbox')#이걸로 오류를 잡았는데 무엇인지 이해 불가 	Disables the sandbox for all process types that are normally sandboxed. Meant to be used as a browser-level switch for testing purposes only
    chrome_options.add_argument('disable-gpu')#gpu사용 안함
    user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
    chrome_options.add_argument('user-agent=' + user_agent)
    driver = webdriver.Chrome(options=chrome_options)#옵션 적용
    for url in all_comment_url:
        #print(url)
        try:
            url_time_start = time.time()
            url = "https://finance.naver.com"+url
            driver.get(url=url) 
            driver.implicitly_wait(10)
            date = driver.find_element(By.CLASS_NAME, 'gray03.p9.tah').text
            title_not_clean = driver.find_element(By.CLASS_NAME, 'c.p15').text
            body_not_clean = driver.find_element(By.ID, 'body').text
            body = body_not_clean.replace("\n","")
            title = title_not_clean.replace("#","")
            #append
            date_text_for_100.append(date)
            date_text_for_10.append(date)
            date_text.append(date)
            title_text_for_100.append(title)
            title_text_for_10.append(title)
            title_text.append(title)
            body_text_for_100.append(body)
            body_text_for_10.append(body)
            body_text.append(body)         
            url_100.append(url)
            url_10.append(url)  
            url_time_end = time.time()
            print(url_time_end - url_time_start, ":", "중간시간")
        
        except UnexpectedAlertPresentException:#무조건 필요 관리자가 삭제한 글을 불러오지 못할 때에 문제가 아주 크게크게 생김 프로그램이 멈춰버려!
            #print("\n관리자가 삭제한 글 임\n")
            error_count = error_count + 1

    #10페이지 마다 저장(혹시 모를 오류 발생으로 인한 데이터 소실 해소)
    if(t%10 == 0):
        tic_10 = tic_10 + 10
        toc_10 = tic_10 - 10
        df_for_10 = pd.DataFrame()
        df_for_10['date'] = date_text_for_10
        df_for_10['title'] = title_text_for_10
        df_for_10['body'] = body_text_for_10
        df_for_10['url'] = url_10

        date_text_for_10.clear()
        title_text_for_10.clear()
        body_text_for_10.clear()
        url_10.clear()

        df_for_10.to_csv(f"data/for10/{toc_10}_{tic_10}.txt", index = False, sep='\t')
        df_for_10.to_csv(f"data/for10/{toc_10}_{tic_10}.csv", index=False, sep='\t')
        file = open("log.txt", "a", encoding="UTF-8")
        txt_text = f"{t}파일 생성 : {toc_10}_{tic_10}.txt"
        file.write(txt_text)
        file.close()


    if(t%100 == 0):
        tic_100 = tic_100 + 100
        toc_100 = tic_100 - 100
        df_for_100 = pd.DataFrame()
        df_for_100['date'] = date_text_for_100
        df_for_100['title'] = title_text_for_100
        df_for_100['body'] = body_text_for_100
        df_for_100['url'] = url_100
        
        date_text_for_100.clear()
        title_text_for_100.clear()
        body_text_for_100.clear()
        url_100.clear()

        df_for_10.to_csv(f"data/for10/{toc_100}_{tic_100}.txt", index = False, sep='\t')
        df_for_10.to_csv(f"data/for10/{toc_100}_{tic_100}.csv", index=False, sep='\t')
        file = open("log.txt", "a", encoding="UTF-8")
        txt_text = f"{t}파일 생성 : {toc_100}_{tic_100}.txt"
        file.write(txt_text)
        file.close()
    
    all_comment_url = []
    end_middle = time.time()
    time_end_page = time.time()
    sec = (time_end_page - time_page_start)
    sec_middle = (end_middle - start_middle)
    result_middle = str(datetime.timedelta(seconds=sec_middle)).split(".")
    result = str(datetime.timedelta(seconds=sec)).split(".")
    print(f"페이지{t}시간 : ",result[0])#시간 표시
    print(f"현재까지 시간 : ", result_middle[0])#지금까지 시간 표시
    print(f"관리자 삭제 글 수 : {error_count}")#관리자 삭제 글 수 
    today = time
    file = open("log.txt", "a", encoding="UTF-8")
    text = f"시간 : {today.strftime('%Y-%m-%d %H:%M:%S')}\n페이지{t}의 걸린시간 : {result[0]}\n현재까지 걸린 시간 : {result_middle[0]}\n관리자가 삭제한(error)수 : {error_count}\n\n"
    file.write(text)
    file.close()
driver.quit()

#전체 데이터 프레임 만들어서 저장
df = pd.DataFrame()
df['date'] = date_text
df['title'] = title_text
df['body'] =  body_text

df.to_csv(f"data/0_{end_page}_result.txt", index = False, sep='\t')
#page = ILLEGAL_CHARACTERS_RE.sub(r'', text)#엑셀파일 불가한 특수문자 제거 -> 7초에서 11초 정도로 시간 증가
df.to_csv(f"data/0_{end_page}_result.csv", index=False, sep='\t')#엑셀로 포함 불가능한 길이의 문장들이 존재
end = time.time()
sec = (end - start)
result = str(datetime.timedelta(seconds=sec)).split(".")
print("전체 페이지 : ",result[0])

file = open("log.txt", "a", encoding="UTF-8")
file.write("--------------------------------------------------------\n\n\n")
file.close()
#2023-11-18 어쩐지 자꾸 중첩되더라, url이 자꾸 점점 늘어서 그럼, 20페이지 40분에서 4분으로 감소, 35페이지 7분, 한 페이지당 7초
#2023-11-21 excel 파일로 만들기에는 문장이 길어서 넣지 못하는 경우가 생겨 csv로 생성


추가적으로 링크를 request로 크롤링 하기 위한 모듈을 만들었다.

url_parser
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import  os
import  requests
from bs4 import BeautifulSoup as bs
from selenium.webdriver.common.by import By
 
def url_parser(min, max):
    for t in range(int(min), int(max + 1)):
        url = f'https://finance.naver.com/item/board.naver?code=005930&page={t}'
        
        headers = {
            'Referer': 'https://finance.naver.com/item/board.naver?code=005930',
            'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
            }
        
        response = requests.get(url = url, headers = headers)
        #print(response) # 접속 확인 (200 = 성공)
        html_text = response.text
        html = bs(html_text, 'html.parser')
        url_per_page = html.select('.title')
        
        url_per_page_url = []

        for n in url_per_page:
            url_per_page_url.append(n.a["href"])

    return url_per_page_url

def max_page(webdriver):
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('headless')
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("https://finance.naver.com/item/board.naver?code=005930")
    driver.find_element(By.CLASS_NAME, 'pgRR').click()
    max_not_clean = driver.find_element(By.CSS_SELECTOR, '#content > div.section.inner_sub > table:nth-child(3) > tbody > tr > td:nth-child(2) > table > tbody > tr > td.on > a').text
    driver.quit()
    max = max_not_clean.replace(",","")
    print("최대값 : ",max)
    return max

version 8 (Beautiful soap)

Beautiful soap과 request를 이용해서 header를 조작하여 접근 및 크롤링 하는것이 더 효율적이고 쉽겠다는 생각이 들어 만들어 보았다.

추가사항 : pyinstaller로 exe파일 생성시 오류 발생 fake_useragent의 문제 (2023-11-22 해결 못함)

Crawler_BS4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import os
import requests
from bs4 import BeautifulSoup as bs
import url_parser as UP
import time
import pandas as pd
import datetime
from tqdm import tqdm
from fake_useragent import UserAgent

#정적 크롤러
print("시작 페이지를 입력하시오(최소 1) : ")
input_start = input()
print("끝 페이지를 입력하시오(최대 99522) : ")
input_end = input()
print("다운로드 형식 : 1. excel(긴글 존재시 불가)     2. csv  3. txt ")
input_type = int(input())

start_page = int(input_start)
end_page = int(input_end)

log_file_name = 'log.txt'
if os.path.isfile(log_file_name):
    print("log 파일 존재")
else:
    f = open("log.txt", 'w')
    f.close()
    print("로그파일 생성")


file = open("log.txt", "a", encoding="UTF-8")
file.write(f"\n---------------------------------\n 정적 크롤링 시작\n 시작 페이지: {start_page}, 마지막 페이지: {end_page}")
file.close()

start_time = time.time()
print("크롤링 url 시작")
crawling_url_list = UP.url_parser(start_page, end_page)
print("크롤링 url 생성")

date_list = []
title_list = []
comment_list = []
goodcnt_list = []
badcnt_list = []
url_list = []

print("데이터 수집 시작")
for url_p in tqdm(crawling_url_list):
    user_agent = UserAgent()
    headers = {
            'Referer': 'https://finance.naver.com/item/board.naver?code=005930',
            'User-Agent': user_agent.random
        }
    url = "https://finance.naver.com" + url_p
    response_url_html = requests.get(url=url, headers=headers)
    url_html_text = response_url_html.text
    html = bs(url_html_text, 'html.parser')

    date = html.select_one('.gray03.p9.tah').text
    comment_not_cleaned = html.select_one('.view_se').text
    comment = comment_not_cleaned.replace("\n", "")
    title_not_cleaned = html.select_one('.c.p15').text
    title = title_not_cleaned.replace("#", "").replace("", "").replace("[", "").replace("]", "")
    goodcnt = html.select_one('.tah.p11.red01._goodCnt').text
    badcnt = html.select_one('.tah.p11.blue01._badCnt').text


    date_list.append(date)
    comment_list.append(comment)
    title_list.append(title)
    goodcnt_list.append(goodcnt)
    badcnt_list.append(badcnt)
    url_list.append(url)

df = pd.DataFrame()
df['date'] = date_list
df['title'] = title_list
df['comment'] = comment_list
df['good'] = goodcnt_list
df['bad'] = badcnt_list
df['url'] = url_list

if(input_type == 1):
    df.to_excel(f"data/{start_page}_to_{end_page}_bs.xlsx", index = False)
elif(input_type == 2):    
    df.to_csv(f"data/{start_page}_to_{end_page}_bs.csv", index = False, sep='\t')
elif(input_type == 3):
    df.to_csv(f"data/{start_page}_to_{end_page}_bs.txt", index = False, sep='\t')
else:
    print("전부생성")
    df.to_csv(f"data/{start_page}_to_{end_page}_bs.txt", index = False, sep='\t')
    df.to_csv(f"data/{start_page}_to_{end_page}_bs.csv", index = False, sep='\t')
    df.to_excel(f"data/{start_page}_to_{end_page}_bs.xlsx", index = False)
end_time = time.time()
sec = (end_time - start_time)
result_t = str(datetime.timedelta(seconds=sec)).split(".")
print(f"시간 : {result_t[0]}")
file = open("log.txt", "a", encoding="UTF-8")
file.write(f"걸린 시간 : {result_t[0]}")
file.close()

time.sleep(1000)
Url_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import  requests
from bs4 import BeautifulSoup as bs
from tqdm import tqdm
from fake_useragent import UserAgent
 
def url_parser(min, max):
    url_per_page_url = []
    for t in tqdm(range(int(min), int(max + 1))):
        url = f'https://finance.naver.com/item/board.naver?code=005930&page={t}'
        user_agent = UserAgent()
        if(t == 1):
            headers = {
                'User-Agent': user_agent.random
            }
        else:
            headers = {
                'Referer': f'https://finance.naver.com/item/board.naver?code=005930&page={t-1}',
                'User-Agent' : user_agent.random
                }
        
        response = requests.get(url = url, headers = headers)
        #print(response) # 접속 확인 (200 = 성공)
        html_text = response.text
        html = bs(html_text, 'html.parser')
        url_per_page = html.select('.title')
        

        for n in url_per_page:
            url_per_page_url.append(n.a["href"])

    return url_per_page_url

version 8-1 (Beautiful soap)

하나의 파일로 묶어서 사용할 수 있게 함수처리 하였다.

crawler_bs4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import os
import requests
from bs4 import BeautifulSoup as bs
import url_parser as UP
import time
import pandas as pd
import datetime
from tqdm import tqdm
import fake_useragent

#정적 크롤러
def CWBS(input_start, input_end, input_type):
    start_page = int(input_start)
    end_page = int(input_end)
    save_type = int(input_type)

    log_file_name = 'log.txt'
    if os.path.isfile(log_file_name):
        print("log 파일 존재")
    else:
        f = open("log.txt", 'w')
        f.close()
        print("로그파일 생성")


    file = open("log.txt", "a", encoding="UTF-8")
    file.write(f"\n---------------------------------\n 정적 크롤링 시작\n 시작 페이지: {start_page}, 마지막 페이지: {end_page}")
    file.close()

    start_time = time.time()
    print("크롤링 url 시작")
    crawling_url_list = UP.url_parser(start_page, end_page)
    print("크롤링 url 생성")

    date_list = []
    title_list = []
    comment_list = []
    goodcnt_list = []
    badcnt_list = []
    url_list = []

    print("데이터 수집 시작")
    for url_p in tqdm(crawling_url_list):
        user_agent = fake_useragent.UserAgent()
        headers = {
                'Referer': 'https://finance.naver.com/item/board.naver?code=005930',
                'User-Agent': user_agent.random
            }
        url = "https://finance.naver.com" + url_p
        response_url_html = requests.get(url=url, headers=headers)
        url_html_text = response_url_html.text
        html = bs(url_html_text, 'html.parser')

        date = html.select_one('.gray03.p9.tah').text
        comment_not_cleaned = html.select_one('.view_se').text
        comment = comment_not_cleaned.replace("\n", "")
        title_not_cleaned = html.select_one('.c.p15').text
        title = title_not_cleaned.replace("#", "").replace("", "").replace("[", "").replace("]", "")
        goodcnt = html.select_one('.tah.p11.red01._goodCnt').text
        badcnt = html.select_one('.tah.p11.blue01._badCnt').text


        date_list.append(date)
        comment_list.append(comment)
        title_list.append(title)
        goodcnt_list.append(goodcnt)
        badcnt_list.append(badcnt)
        url_list.append(url)

    df = pd.DataFrame()
    df['date'] = date_list
    df['title'] = title_list
    df['comment'] = comment_list
    df['good'] = goodcnt_list
    df['bad'] = badcnt_list
    df['url'] = url_list

    if(save_type == 1):
        df.to_excel(f"data/{start_page}_to_{end_page}_bs.xlsx", index = False)
    elif(save_type == 2):    
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.csv", index = False, sep='\t')
    elif(save_type == 3):
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.txt", index = False, sep='\t')
    else:
        print("전부생성")
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.txt", index = False, sep='\t')
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.csv", index = False, sep='\t')
        df.to_excel(f"data/{start_page}_to_{end_page}_bs.xlsx", index = False)
    end_time = time.time()
    sec = (end_time - start_time)
    result_t = str(datetime.timedelta(seconds=sec)).split(".")
    print(f"시간 : {result_t[0]}")
    file = open("log.txt", "a", encoding="UTF-8")
    file.write(f"걸린 시간 : {result_t[0]}")
    file.close()
url_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import  requests
from bs4 import BeautifulSoup as bs
from tqdm import tqdm
from fake_useragent import UserAgent
 
def url_parser(min, max):
    url_per_page_url = []
    for t in tqdm(range(int(min), int(max + 1))):
        url = f'https://finance.naver.com/item/board.naver?code=005930&page={t}'
        user_agent = UserAgent()
        if(t == 1):
            headers = {
                'User-Agent': user_agent.random
            }
        else:
            headers = {
                'Referer': f'https://finance.naver.com/item/board.naver?code=005930&page={t-1}',
                'User-Agent' : user_agent.random
                }
        
        response = requests.get(url = url, headers = headers)
        #print(response) # 접속 확인 (200 = 성공)
        html_text = response.text
        html = bs(html_text, 'html.parser')
        url_per_page = html.select('.title')
        

        for n in url_per_page:
            url_per_page_url.append(n.a["href"])

    return url_per_page_url
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import crawler_bs4


print("시작, 끝, 타입(excel, csv, txt), 스텝")
start = int(input())
end = int(input())
type = int(input())
step = int(input())


total = end + 1 - start
sep = int(total/step)

time_list = []

for i in range(start, end+1, step):
    time_list.append(i)

print(time_list)
print(len(time_list))
time_list_len = len(time_list)

for i in range(0, time_list_len-1):
    start_time = time_list[i]
    end_time = time_list[i+1]
    crawler_bs4.CWBS(start_time, end_time, type)

version 8-2 (try except 예외처리)

크롤링을 시작하자마자, 아래와 같이 NoneType 에러를 마주하였고 selenium을 이용할 때 문제가 생긴 것을 해결했듯 try except문을 이용하여 예외처리하였다.

또한 우리에게는 year, month, day만 필요하고 뒤에 나오는 시, 분, 초는 필요가 없기에 [:10]으로 뒤에 부분을 잘랐다.

2023-11-22
엑셀 파일을 만들 때 특수문자로 인한 오류가 발생하기에 아래 구문을 이용하여 오류를 방지하였다.

1
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE

그리고 문제 봉착

main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import crawler_bs4


print("시작, 끝, 타입(excel, csv, txt), 스텝")
start = int(input()) #시작페이지
end = int(input()) #끝 페이지
type = int(input()) #타입 설정 엑셀, csv, 텍스트
step = int(input()) #몇 페이지당 저장할 것인지 end와 start 값의 차이보다 작을것

time_list = [] #몇 페이지에서 멈출지 리스트 선언

#step 페이지마다 저장
time_list.append(start)
for i in range(start, end+1):
    if(i%step == 0):
        time_list.append(i)


print(time_list) #디버깅
#print(len(time_list)) #디버깅

time_list_len = len(time_list) #리스트 길이 측정

#리스트에 있는 요소값 만큼 페이지 크롤링, 타입 전해주기
for i in range(0, time_list_len-1):
    start_time = time_list[i]
    end_time = time_list[i+1]
    crawler_bs4.CWBS(start_time, end_time, type) #crawler_bs4파일의 CWBS함수에 전달
crawler_bs4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import os
import requests
from bs4 import BeautifulSoup as bs
import url_parser as UP
import time
import pandas as pd
import datetime
from tqdm import tqdm
import fake_useragent #pyinstaller 사용 불가 우씨...
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE

#정적 크롤러
def CWBS(input_start, input_end, input_type):
    error_count = 0 #관리자 삭제 링크 수 세기
    start_page = int(input_start) #첫 페이지
    end_page = int(input_end) #끝 페이지
    save_type = int(input_type) #저장 타입

    #로그 파일 존재 확인
    log_file_name = 'log.txt'
    if os.path.isfile(log_file_name):
        print("log 파일 존재")
    else:
        f = open("log.txt", 'w')
        f.close()
        print("로그파일 생성")

    #크롤링 시작 log에 출력
    file = open("log.txt", "a", encoding="UTF-8")
    file.write(f"\n---------------------------------\n 정적 크롤링 시작\n 시작 페이지: {start_page}, 마지막 페이지: {end_page}\n")
    file.close()

    start_time = time.time()
    print("크롤링 url 시작")
    crawling_url_list = UP.url_parser(start_page, end_page)
    print("크롤링 url 생성")

    #필요 리스트
    date_list = [] #날짜
    title_list = [] #제목
    comment_list = [] #본몬
    goodcnt_list = [] #추천
    badcnt_list = [] #비추천
    url_list = [] #크롤링된 url

    #크롤링 시작
    print("데이터 수집 시작")
    for url_p in tqdm(crawling_url_list):
        try: #관리자 삭제 링크 생기면 except 실행 후 다음 링크 크롤링
            user_agent = fake_useragent.UserAgent()
            headers = {
                    'Referer': 'https://finance.naver.com/item/board.naver?code=005930',
                    'User-Agent': user_agent.random
                }
            url = "https://finance.naver.com" + url_p #링크에 item 뒷부분만 포함되어있기에 앞부분 추가
            response_url_html = requests.get(url=url, headers=headers) #링크 요청
            url_html_text = response_url_html.text #받은 json파일에서 text값만 추출
            html = bs(url_html_text, 'html.parser') #html 파싱

            #요소 접근
            date = html.select_one('.gray03.p9.tah').text #날짜
            comment_not_cleaned = html.select_one('.view_se').text #본문
            comment = comment_not_cleaned.replace("\n", "") #본문에서 \n제거
            comment = ILLEGAL_CHARACTERS_RE.sub(r'', comment)
            title_not_cleaned = html.select_one('.c.p15').text #제목
            title = title_not_cleaned.replace("#", "").replace("", "").replace("[", "").replace("]", "") #제목에서 특수문자 제거
            goodcnt = html.select_one('.tah.p11.red01._goodCnt').text #추천
            badcnt = html.select_one('.tah.p11.blue01._badCnt').text #비추천

            #크롤링한 요소 리스트에 담기
            date_list.append(date[:10]) #year, month, day만 크롤링
            comment_list.append(comment)
            title_list.append(title)
            goodcnt_list.append(goodcnt)
            badcnt_list.append(badcnt)
            url_list.append(url) #디버깅용 url
        except:
            error_count =+ 1

    #dataframe 생성 후 크롤링 한 것들 전부 담기
    df = pd.DataFrame()
    df['date'] = date_list
    df['title'] = title_list
    df['comment'] = comment_list
    df['good'] = goodcnt_list
    df['bad'] = badcnt_list
    df['url'] = url_list

    #데이터프레임 저장
    if(save_type == 1):
        df.to_excel(f"data/{start_page}_to_{end_page}_bs.xlsx", index = False)
    elif(save_type == 2):    
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.csv", index = False, sep='\t')
    elif(save_type == 3):
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.txt", index = False, sep='\t')
    else:
        print("전부생성")
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.txt", index = False, sep='\t')
        df.to_csv(f"data/{start_page}_to_{end_page}_bs.csv", index = False, sep='\t')
        df.to_excel(f"data/{start_page}_to_{end_page}_bs.xlsx", index = False)
    
    #디버깅용 시간 체크
    end_time = time.time()
    sec = (end_time - start_time)
    result_t = str(datetime.timedelta(seconds=sec)).split(".") #소수점 이후로 자르기
    print(f"시간 : {result_t[0]}") #잘린 소수점은 [1]
    file = open("log.txt", "a", encoding="UTF-8") #마무리 로그
    file.write(f"걸린 시간 : {result_t[0]}, error_count : {error_count}")
    file.close()
url_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import  requests
from bs4 import BeautifulSoup as bs
from tqdm import tqdm #현제 크롤링 상황 체크
from fake_useragent import UserAgent
 
def url_parser(min, max):

    url_per_page_url = [] #페이지에서 필요한 url추출하여 저장할 리스트

    #크롤러
    for t in tqdm(range(int(min), int(max))):
        url = f'https://finance.naver.com/item/board.naver?code=005930&page={t}'#접속 링크
        user_agent = UserAgent()#fake_useragent함수, useragent 렌덤값 설정하기 위해 UserAgent()불러옴
        if(t == 1): #1페이지는 참조할 필요 없음, 오히려 참조하면 접속 불가
            headers = {
                'User-Agent': user_agent.random #랜덤 agent 설정
            }
        else: #1페이지 이후 참조
            headers = {
                'Referer': f'https://finance.naver.com/item/board.naver?code=005930&page={t-1}', #Referer를 이용해서 다음 링크로 들어가기 전에 참조, 원래 100페이지 이후부터 참조 필요한데 굳이?
                'User-Agent' : user_agent.random #랜덤 agent 설정
                }
        
        response = requests.get(url = url, headers = headers) #url접속
        #print(response) # 접속 확인 (200 = 성공)
        html_text = response.text #response에서 html값 텍스트만 가져오기
        html = bs(html_text, 'html.parser') #beautifulsoup로 HTML 문서를 파싱
        url_per_page = html.select('.title') #파싱된 문서에서 .title 클래스 전부 찾기
        
        #.title 클래스에서 a.href 속성값만 추출
        for n in url_per_page:
            url_per_page_url.append(n.a["href"])

    return url_per_page_url #추출한 링크 리스트 리턴

페이지 찾기

크롤링을 할 때에 너무 방대한 크기를 가지고 있다보니 원하는 날짜부터 크롤링 하기가 쉽지 않았다. 그래서 날짜를 크롤링해서 원하는 페이지를 찾을 수 있게 만들었다.

main.py
1
2
3
4
5
import DF

print("찾고자 하는 날짜를 입력하시오 ex) 2022.11.30")
date = input()
print(DF.date_fider(date))
DF.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import  requests
from bs4 import BeautifulSoup as bs
from tqdm import tqdm #현제 크롤링 상황 체크
from fake_useragent import UserAgent
 
def date_fider(date):
    find_it = False
    #크롤러
    for t in tqdm(range(1, 99983)):
        url = f'https://finance.naver.com/item/board.naver?code=005930&page={t}'#접속 링크
        user_agent = UserAgent()#fake_useragent함수, useragent 렌덤값 설정하기 위해 UserAgent()불러옴
        if(t <= 99): #99페이지 전까지는 참조할 필요 없음, 오히려 참조하면 접속 불가
            headers = {
                'User-Agent': user_agent.random #랜덤 agent 설정
            }
        else: #1페이지 이후 참조
            headers = {
                'Referer': f'https://finance.naver.com/item/board.naver?code=005930&page={t-1}', #Referer를 이용해서 다음 링크로 들어가기 전에 참조, 원래 100페이지 이후부터 참조 필요한데 굳이?
                'User-Agent' : user_agent.random #랜덤 agent 설정
                }
        
        response = requests.get(url = url, headers = headers) #url접속
        #print(response) # 접속 확인 (200 = 성공)
        html_text = response.text #response에서 html값 텍스트만 가져오기
        html = bs(html_text, 'html.parser') #beautifulsoup로 HTML 문서를 파싱
        date_crawling = html.select('.tah.p10.gray03') #파싱된 문서에서 .tah p10 gray03 클래스 전부 찾기 , 추천 비추천 포함이기는 하나 날짜로 찾을 것이기에 문제 없음
        
        #.title 클래스에서 a.href 속성값만 추출
        for n in date_crawling:
            check = n.text
            if date in check:
                find_date_in_page = t
                find_it = True
                break
        if find_it == True:
            break
    
    return find_date_in_page #날짜에 맞는 페이지 리턴

추가 사항들

버전이 추가되었다. (2023-11-22)

  • 셀레니움버전
  • beautiful soap 버전

    페이지 찾기가 추가되었다. (2023-12-06)

    원하는 날짜를 입력하면 페이지를 찾아준다.

    날짜 기반 크롤러를 만들었다. (2023-12-11)

    링크

최종

처음으로 목적을 가지고 프론트엔드에 대해 1도 못하던 내가 0부터 차근차근 쌓아가면서 이렇게 만들어낼 줄은 생각도 못했다. 이제 코드를 깨끗하게 정리해서 최종 코드를 올리고 마무리 하도록 하겠다.(2023-11-22)
-> multiprocessing을 이용해서 크롤링 하는 코드를 더 만들어 봐야 겠다. 1000페이지를 크롤링 하는데 1시간 20분이기에 최대한 노력해봐야 겠다.


참조

This post is licensed under CC BY 4.0 by the author.