본문 바로가기
프로그램 (PHP,Python)

HTML 코드에서 데이터 추출하여 JSON 형식 변환

by 날으는물고기 2023. 9. 23.

HTML 코드에서 데이터 추출하여 JSON 형식 변환

HTML 코드에서 데이터를 추출하여 JSON 형식으로 변환하는 작업을 수행합니다. 이를 간소화하려면 정규 표현식을 사용하는 대신 더 구조화된 방법을 사용하는 것이 좋습니다.

다음은 Python을 사용하여 같은 작업을 수행하는 방법입니다. Python은 정규 표현식 대신 BeautifulSoup과 같은 라이브러리를 사용하여 HTML 파싱을 더 쉽게 할 수 있습니다.

from bs4 import BeautifulSoup
import re
import json

html = """
여기에 HTML 코드를 입력하세요
"""

soup = BeautifulSoup(html, 'html.parser')

data = []
for row in soup.find_all('tr'):  # 'tr' 태그를 포함하는 모든 행을 찾습니다.
    columns = row.find_all('td')  # 'td' 태그를 포함하는 모든 열을 찾습니다.

    if len(columns) == 9:
        item = {
            "name": columns[0].get_text(),
            "close": columns[1].get_text(),
            "diff": columns[2].get_text(),
            "rate": columns[3].get_text(),
            "open": columns[4].get_text(),
            "hight": columns[5].get_text(),
            "low": columns[6].get_text(),
            "date": columns[7].get_text()
        }
        data.append(item)

json_data = json.dumps(data, ensure_ascii=False, indent=2)
print(json_data)

위 코드는 BeautifulSoup를 사용하여 HTML을 파싱하고, 각 행에서 필요한 데이터를 추출하여 JSON 형식으로 변환합니다. 이 방법은 코드가 더 읽기 쉽고 유지 보수하기 쉽다는 장점이 있습니다. HTML 구조가 변경되어도 더 쉽게 수정할 수 있습니다.

 

위 Python 코드를 Bash 스크립트로 다시 구현할 수 있습니다. Bash 스크립트로 HTML 파싱을 직접 수행하려면 awk와 sed와 같은 텍스트 처리 도구를 사용해야 합니다. 하지만 Python과 BeautifulSoup과 같은 라이브러리를 사용하는 것보다 번거로울 수 있습니다.

 

아래는 Bash 스크립트로 작업을 수행하는 방법입니다. 입력 HTML은 data.html 파일로 가정하고, 출력 JSON은 output.json 파일로 저장됩니다.

#!/bin/bash

# HTML 파일을 읽어옵니다.
html=$(<data.html)

# 데이터를 저장할 JSON 배열을 선언합니다.
data=()

# 각 데이터 행을 추출하고 배열에 저장합니다.
while read -r line; do
  if [[ $line =~ "<tr>"(.+)"<\/tr>" ]]; then
    row=${BASH_REMATCH[1]}

    if [[ $row =~ "<td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td><td>"([^<]+)"<\/td> ]]; then
      name=${BASH_REMATCH[1]}
      close=${BASH_REMATCH[2]}
      diff=${BASH_REMATCH[3]}
      rate=${BASH_REMATCH[4]}
      open=${BASH_REMATCH[5]}
      high=${BASH_REMATCH[6]}
      low=${BASH_REMATCH[7]}
      date=${BASH_REMATCH[8]}

      item="{\"name\":\"$name\",\"close\":\"$close\",\"diff\":\"$diff\",\"rate\":\"$rate\",\"open\":\"$open\",\"high\":\"$high\",\"low\":\"$low\",\"date\":\"$date\"}"
      data+=("$item")
    fi
  fi
done <<< "$html"

# JSON 배열을 출력 파일에 저장합니다.
json_data="["
json_data+=$(IFS=,; echo "${data[*]}")
json_data+="]"

echo "$json_data" > output.json

위 스크립트는 data.html 파일을 읽어와 각 데이터 행을 추출하고 JSON 형식으로 변환하여 output.json 파일에 저장합니다. 이 스크립트는 정규 표현식을 사용하여 HTML을 파싱하고 데이터를 추출합니다.

 

sedjq를 사용하여 Bash 스크립트를 더 간소화하고 최적화할 수 있습니다. 다음은 sedjq를 사용한 스크립트입니다.

#!/bin/bash

# HTML 파일을 읽어옵니다.
html=$(<data.html)

# 데이터 추출 및 JSON 변환을 위한 sed 명령어를 작성합니다.
sed_expr='s/<tr><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><\/tr>/"{\2":{"name":"\1","close":"\2","diff":"\3","rate":"\4","open":"\5","high":"\6","low":"\7","date":"\8"}},/g'
sed_script="/<tr>/!d; $sed_expr"
json_data=$(echo "$html" | sed -r "$sed_script")

# 마지막 JSON 객체의 쉼표를 제거합니다.
json_data="${json_data%,}"

# JSON 배열 형식으로 출력합니다.
echo "[$json_data]" | jq .

이 스크립트는 sed를 사용하여 HTML에서 데이터를 추출하고 그 결과를 jq를 사용하여 JSON으로 파싱합니다. sed 명령어를 사용하여 HTML에서 데이터를 추출하는 방법이 복잡하지만 JSON 변환은 jq를 사용하여 간단하게 수행합니다. JSON 배열 형식으로 출력됩니다.

 

/<tr>/!dsed 명령어의 패턴과 제어 명령을 사용하는 부분입니다. 이 부분은 <tr> 태그를 포함하지 않는 행을 삭제하는 역할을 합니다. 설명을 자세히 하면 다음과 같습니다.

  • /.../ 패턴 매칭을 나타냅니다.
  • <tr>은 찾을 패턴으로, <tr> 문자열을 의미합니다.
  • !는 부정을 나타내며, 즉 패턴을 찾는 것이 아니라 패턴이 없는 행을 선택합니다.
  • d는 선택한 행을 삭제하는 sed 명령어입니다.

따라서 /<tr>/!d<tr> 태그를 포함하지 않는 행을 모두 삭제하는 명령어입니다. 이렇게 하면 HTML에서 데이터 행만 남게 됩니다.

 

더 간결한 방법으로 Bash 스크립트를 최적화할 수 있습니다. 아래는 sedjq를 사용하여 스크립트를 더 간소화한 예제입니다.

#!/bin/bash

# HTML 파일을 읽어옵니다.
html=$(<data.html)

# 데이터 추출 및 JSON 변환을 위한 sed 명령어를 작성합니다.
sed_expr='s/<tr><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><\/tr>/{\2:{"name":"\1","close":"\2","diff":"\3","rate":"\4","open":"\5","high":"\6","low":"\7","date":"\8"}},/g'
json_data=$(echo "$html" | sed -r -e "1s/^/{/" -e "$s/$/}/" -e "$sed_expr" | jq -s .)

echo "$json_data"

이 스크립트는 먼저 HTML 파일을 읽어오고, sed를 사용하여 데이터를 추출하고 JSON 변환합니다. jq -s .는 결과 JSON 객체를 배열로 래핑합니다.

기존 스크립트보다 좀 더 간결하게 작성되었으며, 여전히 필요한 작업을 수행합니다. 각 부분을 자세히 설명하겠습니다.

 

아래 스크립트는 sedjq를 사용하여 HTML 데이터를 파싱하고 JSON 형식으로 변환하는 작업을 수행합니다.

#!/bin/bash

# HTML 파일을 읽어옵니다.
html=$(<data.html)

먼저 data.html 파일의 내용을 html 변수에 저장합니다.

# 데이터 추출 및 JSON 변환을 위한 sed 명령어를 작성합니다.
sed_expr='s/<tr><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><td>\([^<]\+\)<\/td><\/tr>/{\2:{"name":"\1","close":"\2","diff":"\3","rate":"\4","open":"\5","high":"\6","low":"\7","date":"\8"}},/g'

위 코드 블록은 sed 명령어를 위한 표현식을 정의합니다. 이 표현식은 <tr> 태그를 포함하는 각 데이터 행을 찾아 그 내용을 JSON 형식으로 변환합니다. sed_expr 변수에 저장된 이 표현식은 다음과 같은 역할을 합니다.

  • <tr> 태그로 시작하고 </tr> 태그로 끝나는 각 데이터 행을 찾습니다.
  • 각 행에서 9개의 <td> 태그를 추출하고 그 안의 내용을 정규 표현식을 사용하여 각각의 필드로 추출합니다. 필드 이름과 값을 사용하여 JSON 형식으로 변환합니다.
  • 각 데이터 행을 JSON 객체로 감싸고 쉼표로 구분하여 배열 형태로 만듭니다.
json_data=$(echo "$html" | sed -r -e "1s/^/{/" -e "$s/$/}/" -e "$sed_expr" | jq -s .)

위 코드 블록은 다음과 같은 작업을 수행합니다.

  • sed -r -e "1s/^/{/"은 HTML의 첫 번째 행을 {로 변경하여 JSON 배열을 시작합니다.
  • $s/$/}/"은 마지막 행을 }로 변경하여 JSON 배열을 종료합니다.
  • $sed_expr은 앞에서 정의한 sed_expr 변수의 내용을 적용하여 데이터 행을 JSON으로 변환합니다.
  • jq -s .는 결과 JSON 객체를 배열로 래핑합니다. 이렇게 하면 여러 JSON 객체가 포함된 JSON 배열이 생성됩니다.

마지막으로 json_data 변수에 최종 JSON 데이터가 저장되며, 스크립트는 이 데이터를 출력합니다. 이렇게 하면 HTML 데이터가 파싱되어 JSON 형식으로 변환되어 출력됩니다.

주어진 HTML에서 데이터를 추출하여 JSON 형식으로 만들기 위해 다음과 같은 Bash 스크립트를 사용할 수 있습니다. 이 스크립트는 주어진 HTML에서 각 항목을 추출하고 JSON 배열로 구성합니다.

#!/bin/bash

# HTML 데이터
html=$(cat <<EOF
<a href="#" title="CD91일물">CD91일물</a>
<span class="txt-en">CD91</span>
<span class="txt-num">3.76</span>
<span class="txt-num stock-point hold">0.00</span>
<span class="txt-num hold">0.00%</span>
<span class="txt-num">3.76</span>
<span class="txt-num">3.76</span>
<span class="txt-num">3.76</span>
<span class="txt-date">2023.09.15</span>
<a href="#" title="CP91일물">CP91일물</a>
<span class="txt-en">CP91</span>
<span class="txt-num">4.01</span>
<span class="txt-num stock-point hold">0.00</span>
<span class="txt-num hold">0.00%</span>
<span class="txt-num">4.01</span>
<span class="txt-num">4.01</span>
<span class="txt-num">4.01</span>
<span class="txt-date">2023.09.15</span>
EOF
)

# 데이터 추출 및 JSON 배열 만들기
json_data="["
while [[ "$html" =~ "<a href=\"(.+?)\" title=\"(.+?)\">"(.+?)<\/a>" ]]; do
    link="${BASH_REMATCH[1]}"
    title="${BASH_REMATCH[2]}"
    name="${BASH_REMATCH[3]}"

    html="${html#*<\/a>}"  # 현재 항목 이후의 HTML 부분을 가져옵니다.

    if [[ "$html" =~ "<span class=\"txt-num\">(.+?)<\/span>" ]]; then
        num1="${BASH_REMATCH[1]}"
        html="${html#*<\/span>}"
    fi

    if [[ "$html" =~ "<span class=\"txt-num\">(.+?)<\/span>" ]]; then
        num2="${BASH_REMATCH[1]}"
        html="${html#*<\/span>}"
    fi

    if [[ "$html" =~ "<span class=\"txt-num\">(.+?)<\/span>" ]]; then
        num3="${BASH_REMATCH[1]}"
        html="${html#*<\/span>}"
    fi

    if [[ "$html" =~ "<span class=\"txt-date\">(.+?)<\/span>" ]]; then
        date="${BASH_REMATCH[1]}"
    fi

    item="{\"link\":\"$link\",\"title\":\"$title\",\"name\":\"$name\",\"num1\":\"$num1\",\"num2\":\"$num2\",\"num3\":\"$num3\",\"date\":\"$date\"}"

    if [[ "$json_data" == "[" ]]; then
        json_data="$json_data$item"
    else
        json_data="$json_data,$item"
    fi
done

json_data="$json_data]"

# 결과 출력
echo "$json_data"

이 스크립트는 주어진 HTML에서 각 항목을 추출하고 JSON 배열로 만듭니다. JSON 배열에는 각 항목에 대한 정보가 포함되며, 필요에 따라 더 많은 항목을 추가하거나 수정할 수 있습니다. 이 예제는 주어진 HTML의 구조에 기반하여 작성되었습니다. HTML의 구조가 변경되면 스크립트를 수정해야 할 수 있습니다.

 

BASH_REMATCH는 Bash 스크립트에서 사용할 수 있는 특별한 변수로, 정규 표현식을 사용하여 문자열에서 패턴을 추출한 결과를 저장하는 데 사용됩니다. BASH_REMATCH 배열은 =~ 연산자를 사용하여 문자열과 정규 표현식 패턴을 비교할 때 생성되며, 배열의 첫 번째 요소(BASH_REMATCH[0])에는 패턴과 일치하는 전체 문자열이 포함되고, 이후의 요소(BASH_REMATCH[1], BASH_REMATCH[2], ...)에는 패턴의 그룹에 해당하는 부분 문자열이 저장됩니다.

 

예를 들어, 다음과 같은 문자열에서 숫자를 추출하고자 할 때 BASH_REMATCH를 사용할 수 있습니다.

string="Hello, my phone number is 123-456-7890."

if [[ $string =~ ([0-9]+)-([0-9]+)-([0-9]+) ]]; then
    echo "Full match: ${BASH_REMATCH[0]}"
    echo "First group: ${BASH_REMATCH[1]}"
    echo "Second group: ${BASH_REMATCH[2]}"
    echo "Third group: ${BASH_REMATCH[3]}"
fi

위 예제에서, 정규 표현식 ([0-9]+)-([0-9]+)-([0-9]+)는 숫자 그룹을 추출하기 위한 패턴입니다. =~ 연산자를 사용하여 문자열과 패턴을 비교하면, BASH_REMATCH 배열이 채워지고 각 그룹에 해당하는 값이 배열 요소에 저장됩니다.

BASH_REMATCH는 문자열에서 패턴을 추출하거나 특정 부분 문자열을 가져와야 할 때 유용합니다.

728x90

댓글