티스토리 뷰

반응형
웹 수집 파이선 매크로를 설명하기 전에 웹 스크래핑과 웹 크롤링 차이부터 잠깐 말하고 시작하겠습니다

웹 스크래핑과 웹 크롤링은 둘 다 웹 데이터를 가져오는 과정이지만, 그 목적과 방식에 있어서 차이가 있습니다.

웹 스크래핑(Web Scraping):


웹 스크래핑은 웹 페이지에서 필요한 정보를 추출하는 과정을 말합니다. 주로 정적인 웹 페이지에서 데이터를 수집하며, 특정 웹 페이지의 HTML을 분석하여 원하는 데이터를 추출합니다. 이를 통해 웹 사이트로부터 특정 정보를 수집하거나 가공하여 활용할 수 있습니다. 웹 스크래핑은 주로 데이터 마이닝, 가격 비교, 리뷰 수집 등과 같은 목적으로 사용됩니다.

웹 스크래핑의 장점은 다음과 같습니다:

특정 웹 페이지에서 필요한 데이터만 추출할 수 있음.
정적인 페이지에서 작동하므로 비교적 간단하게 구현 가능.
그러나 웹 스크래핑에는 몇 가지 주의할 점이 있습니다:

웹 페이지의 소스코드 변경 시 스크래핑 코드도 수정해야 함.
웹 페이지 소유자의 동의 없이 데이터를 수집하는 경우 법적 문제 발생 가능.


웹 크롤링(Web Crawling):


웹 크롤링은 인터넷을 횡단하여 웹 페이지를 자동으로 탐색하고 인덱싱하는 프로세스입니다. 크롤러 또는 스파이더라고 불리는 프로그램이 시작점에서 출발하여 하이퍼링크를 따라 이동하면서 웹 페이지를 수집합니다. 이를 통해 대량의 데이터를 수집하거나 웹 사이트의 구조를 분석할 수 있습니다.

웹 크롤링의 장점은 다음과 같습니다:

대규모 데이터를 자동으로 수집할 수 있음.
동적인 페이지나 로그인이 필요한 페이지도 크롤링 가능.
하지만 웹 크롤링에도 몇 가지 주의할 점이 있습니다:

서버에 과도한 부하를 줄 수 있음.
로봇 배제 표준(Robots Exclusion Standard)을 준수하지 않으면 웹 사이트 운영자의 반발을 일으킬 수 있음.
요약하자면, 웹 스크래핑은 웹 페이지에서 데이터를 추출하는 것에 중점을 두고 있으며, 웹 크롤링은 인터넷을 횡단하여 대량의 데이터를 수집하고 인덱싱하는 프로세스를 의미합니다.

보통 커뮤니티 유머글을 수집하는 것을 많이 볼 수 있죠

글을 가져와서 보여주는 거에서는 대체로 문제가 되지 않지만 

1. 글 내용자체가 문제가 될 수 있는 경우(명예훼손, 개인정보, 허위사실, 불법적 홍보글  등의 법적인 문제)

2. 프로그램이 과도하게 접속하여 대상 사이트에 부하를 일으키는 등의 행위. 

 

 

우선은 여러 커뮤니티 사이트 들에서 유저들이 새로운 소식을 올리긴 하죠

코드로 설명하기 전에 기본적으로 판단해야할 항목들은

1. 어떤 게시물을 가져올지 2. 어떤 게시물을 통과할건지 3. 어느 분류로 가져올 건지 4. 이미지처리 5. 수집시간 등의 조건이 있겠죠

큰 흐름을 

메인 프로그램이 구동되면 각종 사이트에서 이슈를 수집한 후에 각 데이터 처리 후  이미지와 데이타를 모아주어서

일정한 시간간격으로 사이트에 업로드를 하는 방식으로 제작할 수 있습니다.

ChatGpt에 코드를 만들라고 하면 이런 뼈대를 제공해주는데

import requests
from bs4 import BeautifulSoup
import os

# A사이트 URL
url_A = 'A사이트의_URL'
# B사이트 URL
url_B = 'B사이트의_URL'
# main 사이트 업로드 URL
upload_url = 'main_사이트의_업로드_URL'

# A사이트 제목, 내용, 이미지 다운로드 함수
def scrape_A():
    response = requests.get(url_A)
    soup = BeautifulSoup(response.text, 'html.parser')
    # 제목
    title = soup.find('title').text
    # 내용
    content = soup.find('div', class_='content').text
    # 이미지 URL
    img_url = soup.find('div', class_='content').find('img')['src']
    # 이미지 다운로드
    img_response = requests.get(img_url)
    with open('A_image.jpg', 'wb') as f:
        f.write(img_response.content)
    return title, content, 'A_image.jpg'

# B사이트 제목, 내용, 이미지 다운로드 함수
def scrape_B():
    response = requests.get(url_B)
    soup = BeautifulSoup(response.text, 'html.parser')
    # 제목
    title = soup.find('h1').text
    # 내용
    content = soup.find('div', class_='article-content').text
    # 이미지 URL
    img_url = soup.find('div', class_='article-content').find('img')['src']
    # 이미지 다운로드
    img_response = requests.get(img_url)
    with open('B_image.jpg', 'wb') as f:
        f.write(img_response.content)
    return title, content, 'B_image.jpg'

# main 사이트에 업로드하는 함수
def upload_to_main(title, content, image_path):
    # 파일 업로드
    files = {'image': open(image_path, 'rb')}
    data = {'title': title, 'content': content}
    response = requests.post(upload_url, files=files, data=data)
    if response.status_code == 200:
        print("업로드 성공!")
    else:
        print("업로드 실패!")

if __name__ == "__main__":
    # A사이트 데이터 수집
    title_A, content_A, image_path_A = scrape_A()
    # B사이트 데이터 수집
    title_B, content_B, image_path_B = scrape_B()
    
    # main 사이트에 업로드
    upload_to_main(title_A, content_A, image_path_A)
    upload_to_main(title_B, content_B, image_path_B)

 

 

여기서 필요한 부분은 데이터 처리 및 수집 방식을 selenium으로 할지 request로 할지이며

이미지를 한장으로 길게 주르륵 할지

그리고 수집과 업로드를 쓰레드로 분리해서 각각 나눠서 작동되게끔 하는거

그리고 sqlite에서는 동시에 1개만 접속만 허용되기 때문에 수집중에 업로드를 하는게 문제 생길수있으니

(물론 거의 충돌이 일어나지는 않겠지만)

쓰레드 자체를 락을 걸어서 각각 작동을 분리해줄수도있다.

아래는 셀레니움을 이용해서 실제로 인스타그램에 로그인하는 코드 예제이다

import os
from datetime import datetime
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class Instagram:
    def __init__(self, new_item: list):        
        self.instagram_url: str = 'https://www.instagram.com/'
        # Chrome 드라이버 경로 설정
        chrome_driver_path = "./chromedriver"
        # Chrome 드라이버 옵션 설정
        options = webdriver.ChromeOptions()
        # 사용자 데이터 디렉토리 설정
        options.add_argument("user-data-dir=./chrome_cache/instagram")
        # 드라이버 생성
        self.driver = webdriver.Chrome(executable_path=chrome_driver_path, options=options)
        self.wait = WebDriverWait(self.driver, 10)
        self.new_item = new_item
    
    def login(self):
        print('▶ 인스타그램 로그인', end='...', flush=True)
        self.driver.get(self.instagram_url)
        try:
            # 로그인 페이지가 로드될 때까지 대기
            username_input = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='username']")))
            password_input = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='password']")))
            login_button = self.wait.until(EC.element_to_be_clickable((By.XPATH, "//button[@type='submit']")))
            # 아이디와 비밀번호 입력
            username_input.send_keys(self.id)
            password_input.send_keys(self.pw)
            # 로그인 버튼 클릭
            login_button.click()
            # 로그인 후 대기 시간 (예시: 60초)
            time.sleep(60)
        except Exception as e:
            print(f"로그인 실패: {e}")

# 사용 예시
# 아이디와 비밀번호 설정
id = 'your_username'
pw = 'your_password'
instagram = Instagram(new_item)
instagram.login()

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
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
글 보관함