이번에는 제가 원하는 정적으로 동작하는 웹 사이트에서 제품명, 제품유형, 제조사, 인증일, 인증만료일 등 데이터를 추출하는 프로그램을 파이썬으로 구현해보았습니다.

항상 크롤링에서 중요한 것은, 파싱하고자 하는 웹 사이트의 HTML에서 원하는 경로를 바로 파악하는 능력이 필요하다고 생각합니다.

(내가 원하는 데이터가 어떤 div 태그영역에 있는지 확인하고, div 태그 내에서 class 값 또는 id 값 등을 이용해 해당 데이터를 추출할 수 있는지가 필요)

아래는 제가 원하는 사이트에서 html 내 태그값을 이용하여 제품명, 분류, 제조사, 인증일, 인증만료일, 상태값을 추출하는 코드입니다.

import requests, openpyxl
from bs4 import BeautifulSoup

wb = openpyxl.Workbook()
sheet = wb.active

sheet.append(["제품명", "분류", "제조사", "인증일", "인증만료일", "상태값"])

#크롤링할 사이트 직접입력하였으며, URL 변수로 별도 선언 후 input() 을 통해 크롤링할 URL을 입력받도록 만들어도 됨.
for i in range(1, 10+1, 1):
    raw = requests.get(
       "https://www.bsi.bund.de/SiteGlobals/Forms/IT-Sicherheitskennzeichen/EN/IT-Sicherheitskennzeichen_Formular.html?gtp=980004_list%253D{}".format(
          (i)))
    html = BeautifulSoup(raw.text, 'html.parser')

    #크롤링 할 영역을 container로 저장
    container = html.select(".c-search-results > ul > li")

    for c in container:
       #제품명 추출
       product_name = c.select_one(".c-search-result-teaser__headline").text.strip()

       #본문(카테고리, 제조사, 인증일, 인증만료일)의 데이터를 추출하여 line별로 list에 저장
       product_data = c.select_one(".c-search-result-teaser__content").text.strip()
       product_data_list = product_data.splitlines()

       #리스트로부터 제품의 카테고리, 제조사, 인증일, 인증만료일 데이터를 추출
       category = product_data_list[0].replace("Category: ", "")
       manufacturer = product_data_list[1].replace("Manufacturer: ", "")
       Date_of_issue = product_data_list[2].replace("Date of issue: ", "")
       end_of_term = product_data_list[3].replace("End of term: ", "")

       #제품의 상태값은 해당 제품들의 링크로 들어가서 추출해야하므로, 링크값(a태그) 추출 후, 한번 더 BeautifulSoup를 이용해 Status 값을 추출 
       product_status_link = c.find('a')['href']

       raw_status = requests.get('https://www.bsi.bund.de/' + product_status_link)
       html_status = BeautifulSoup(raw_status.text, 'html.parser')

       product_status = html_status.select_one('.c-product-stage__security-status').text.strip()
       
       #엑셀 시트에 저장
       sheet.append([product_name, category, manufacturer, Date_of_issue, end_of_term, product_status])
       
wb.save("C:/Users/user/Documents/bsi_product_search.xlsx")

 

결과

 

위 코드에서 포인트는 A웹사이트에서, A->A' 사이트(A'는 각 제품의 상세페이지)로 한번 더 들어가서 제품의 현재 상태값(status)을 추출해주는 부분입니다.

각 제품들의 링크로 들어가서 한번 더 beautifulsoup를 이용해 파싱하고, 상태값을 불러오는 부분에서 상당한 딜레이가 발생하는 것을 확인하였습니다.

어떻게 성능을 개선할지가 다음 과제인것 같습니다.

좋은 의견 있으실 경우 남겨주시면 언제든 환영입니다.


WRITTEN BY
SiriusJ

,

최근에 파이썬으로 프로그램을 만들어보고 있는데, pycharm으로 개발하면서 실행파일로 누구나 사용할 수 있도록 하기 위해 배포하려고 해서 관련 포스팅을 남깁니다.

 

가장 일반적인 실행파일 생성 방법은 PyInstaller 또는 **cx_Freeze**와 같은 패키지를 사용하는 것입니다. 여기서는 가장 많이 사용되는 **PyInstaller**를 활용하여 파이썬 스크립트를 실행 파일로 만드는 방법을 다루겠습니다.

1. PyInstaller 설치

PyInstaller는 파이썬 스크립트를 단일 실행 파일로 변환해주는 도구입니다. 터미널이나 명령 프롬프트에서 다음 명령어로 설치할 수 있습니다.

(windows : cmd 창)

> pip install pyinstaller

 * 혹시라도 pip가 설치되어있지 않다고 할 경우에는, python을 제어판에서 삭제했다가 다시 설치하고, 설치할 때 환경변수 등 관련 체크박스가 해제되어있는 부분을 확인하고 체크해주신 후에 설치하면 pip가 자동으로 설치되게 됩니다. 이후에는 pip를 이용한 install 등 가능하게 됩니다.

 

2. PyInstaller 사용 방법

설치 후, 파이썬 스크립트를 실행 파일로 변환하려면 터미널 또는 명령 프롬프트에서 다음 명령을 입력합니다:

> pyinstaller --onefile 'test.py'

여기서 'test.py'는 실행 파일로 만들고자 하는 본인의 파이썬 파일 이름입니다.

주요 옵션:

  • --onefile: 하나의 실행 파일로 만듭니다. 기본적으로 PyInstaller는 여러 파일을 생성하는데, 이 옵션을 사용하면 단일 파일로 묶어줍니다.
  • --noconsole: 프로그램을 콘솔 창 없이 GUI 형태로 실행하고 싶을 때 사용합니다. (GUI 프로그램인 경우에만 유용)

 

3. 실행 파일 생성 과정

PyInstaller가 실행되면, 다음과 같은 작업을 수행합니다:

  • dist/ 폴더에 실행 파일이 생성됩니다.
  • build/ 폴더에 빌드와 관련된 파일이 생성됩니다.
  • .spec 파일이 생성되며, 이는 빌드 구성을 저장하는 파일입니다.

 

4. 실행 파일 배포

dist/ 폴더에 생성된 .exe 파일을 다른 사용자에게 배포할 수 있습니다. 배포할 때는 해당 파일만 전달하면 됩니다.

 

5. 참고 사항

  • 윈도우에서 만든 실행 파일은 윈도우에서만 실행 가능하고, macOS 또는 리눅스에서 만들면 그 운영체제에서만 실행 가능합니다. 각 운영체제에서 해당 OS에 맞게 빌드해야 합니다.
  • 실행 파일 크기가 커질 수 있으므로 불필요한 패키지는 제외하는 것이 좋습니다. 이를 위해 .spec 파일을 편집할 수 있습니다.

 

6. 실행 파일로 만들 때 발생할 수 있는 문제 해결

  • 외부 모듈이 포함되지 않는 문제: 일부 외부 모듈이 자동으로 포함되지 않을 수 있습니다. 이 경우, hidden-import 옵션을 사용하여 추가합니다.

> pyinstaller --onefile --hidden-import <module_name> 'test.py'

 

7. PyInstaller 외 다른 도구

  • cx_Freeze: PyInstaller와 유사하게 파이썬 스크립트를 실행 파일로 만들 수 있는 도구입니다. GUI 애플리케이션을 제작할 때 주로 사용됩니다.

> pip install cx_Freeze

> cxfreeze your_script.py --target-dir dist


WRITTEN BY
SiriusJ

,

파이썬 Merge Sort로 오름차순으로 정렬하는 방식입니다.


시간복잡도 : O(nlogn)


(CASE 1)

def mergeSort(A):

    left = []

    right = []

    

    if len(A) > 1:

        mid = len(A) / 2


        for l in range(0, mid, 1):

            left.append(A[l])

        for r in range(mid, len(A), 1):

            right.append(A[r])


        mergeSort(left)

        mergeSort(right)

        

        i=j=k=0

        

        while i < len(left) and j < len(right):

            if left[i] < right[j]:

                A[k]=left[i]

                i += 1

            else:

                A[k]=right[j]

                j += 1

            k += 1


        while i < len(left):

            A[k]=left[i]

            i += 1

            k += 1


        while j < len(right):

            A[k]=right[j]

            j += 1

            k += 1


if __name__ == '__main__':

    A= [1, 8, 6, 10, 4, 5, 3, 22]

    mergeSort(A)

    print A



(CASE 2)

def merge_sort(A, first, last):

    mid = 0

    if first < last:

        mid = (first + last) / 2

        merge_sort(A, first, mid)

        merge_sort(A, mid+1, last)

        merge(A, first, last)


def merge(A, first, last):

    temp = []

    mid = (first + last) / 2

    i = first

    j = mid + 1

    k = 0


    while i <= mid and j <= last:

        if A[i] <= A[j]:

            temp.append(A[i])

            i += 1

        else:

            temp.append(A[j])

            j += 1


    if i > mid:

        for t in range(j, last+1):

            temp.append(A[t])


    else:

        for t in range(i, mid+1):

            temp.append(A[t])

    

    for t in range(first, last+1, 1):

        A[t] = temp[k]

        k += 1

    

if __name__ == '__main__':

    A= [1, 8, 6, 10, 4, 5, 3, 22]

    merge_sort(A, 0, len(A)-1)


    print A


WRITTEN BY
SiriusJ

,

파이썬 Heap Sort로 내림차순으로 정렬하는 방식입니다.


시간복잡도 : O(nlogn)


def heapify(A, n, k):

    while 2*k+1 < n:

        L = 2*k+1

        R = 2*k+2


        if A[k] > A[L]:

            m = L

        else:

            m = k

        if R < n and A[m] > A[R]:

            m = R

        if k != m:

            A[k], A[m] = A[m], A[k]

            k = m

        else:

            break


def make_heap(A):

    for k in range(len(A)/2, -1, -1):

        heapify(A, len(A), k)


def heapSort(A):

    make_heap(A)

    n = len(A)

    for k in range(len(A)-1):

        A[0], A[n-1] = A[n-1], A[0]

        n = n-1

        heapify(A, n, 0)


if __name__ == '__main__':

    A = [3, 10, 7, 9, 8, 5, 12, 21, 4, 15]

    heapSort(A)

    print A



WRITTEN BY
SiriusJ

,

파이썬 Heap Sort로 오름차순으로 정렬하는 방식입니다.

시간복잡도 : O(nlogn)


def heapify(A, n, k):

    while 2*k+1 < n:

        L = 2*k+1

        R = 2*k+2


        if A[k] < A[L]:

            m = L

        else:

            m = k

        if R < n and A[m] < A[R]:

            m = R

            

        if k != m:

            A[k], A[m] = A[m], A[k]

            k = m

        else:

            break


def make_heap(A):

    for k in range(len(A)/2, -1, -1):

        heapify(A, len(A), k)


def heapSort(A):

    make_heap(A)

    n = len(A)

    

    for k in range(n-1):

        A[0], A[n-1] = A[n-1], A[0]

        n -= 1

        heapify(A, n, 0)


if __name__ == '__main__':

    A = [3, 10, 7, 9, 8, 5, 12, 21, 4, 15]

    heapSort(A)

    print A


WRITTEN BY
SiriusJ

,

파이썬 Selection Sort로 오름차순으로 정렬하는 방식입니다.


시간복잡도 : O(n^2)


def selectionSort(A):

    for i in range(len(A)):

        minValue = i

        for j in range(i+1, len(A)):

            if A[j] < A[minValue]:

                minValue = j


        A[minValue], A[i] = A[i], A[minValue]


if __name__ == '__main__':

    A = [4, 1, 5, 8, 6, 2, 3, 7, 10]

    selectionSort(A)

    print A




WRITTEN BY
SiriusJ

,

파이썬 Insertion Sort로 오름차순으로 정렬하는 방식입니다.


시간복잡도 : O(n^2)


def insertionSort(A):

    for i in range(1, len(A)):

        temp = A[i]

        j = i

        while j > 0 and A[j-1] > temp:

            A[j] = A[j-1]

            j -= 1

        A[j] = temp


if __name__ == '__main__':

    A = [4, 1, 5, 8, 6, 2, 3, 7, 10]

    insertionSort(A)

    print A


'Programming > Python' 카테고리의 다른 글

Sorting(5) Heap Sort(힙 정렬 - min Heap)  (0) 2016.10.27
Sorting(4) Selection Sort(선택 정렬)  (0) 2016.10.27
Sorting(2) Quick Sort(퀵 정렬)  (0) 2016.10.27
Sorting(1) Bubble Sort(버블 정렬)  (0) 2016.10.27
Python2 설치  (0) 2016.05.14

WRITTEN BY
SiriusJ

,

파이썬 Quick Sort로 오름차순으로 정렬하는 방식입니다.


시간복잡도 : O(n^2) - Worst Case 일 때 이지만,

일반적으로는 가장 빠른 정렬으로 시간복잡도를 O(nlogn) 으로 봅니다.


def quickSort(A, first, last):

    left = first + 1

    right = last


    if first >= last:

        return

    pivot = A[first]


    while left <= right:

        while left <= last and A[left] < pivot:

            left += 1

        while right > first and A[right] >= pivot:

            right -= 1

        if left <= right:

            A[left], A[right] = A[right], A[left]

            left += 1

            right -= 1


    A[right], A[first] = A[first], A[right]

    quickSort(A, first, right-1)

    quickSort(A, left, last)


if __name__ == '__main__':

    A = [4, 1, 5, 8, 6, 2, 3, 7, 10]

    quickSort(A, 0, len(A)-1)


    print A




WRITTEN BY
SiriusJ

,