2016-12-15 4 views
2

BeautifulSoup & HTML 초보자를 사용하여 HTML이 아닌 웹 페이지에서 데이터를 가져 오려고합니다. 이전에이 유형의 페이지를 본 적이 없습니다. 위스콘신 주 데인 카운티 (Dane County)에서 2008 년 대선 경주에서 데이터를 가져 오려고합니다.어떻게 파싱 하시겠습니까? BeautifulSoup 및 Python

링크 : 대선에 대한 https://www.countyofdane.com/clerk/elect2008d.html

데이터는 하드 코딩 테이블로 보이는에? 그것은 HTML 태그 사이에 저장되지 않았거나 이전에 발견 된 것입니다.

어떻게 든 < !-- #-->을 반복하여 데이터를 가져올 수 있습니까? 페이지를 HTML 파일로 저장하고 태그 주위에 본문 태그를 추가하여 구문 분석하기 쉬워야합니까?

+0

이 시점에서 텍스트를 구문 분석하고 있습니다. BeautifulSoup는 도움이되지 않습니다. 실제 데이터를 파싱하는 것은 비교적 간단하지만 대각선 헤딩은 어려울 것입니다. – kindall

+0

'

' and '
'태그 사이에 텍스트가 있으면 정규 표현식을 사용하여 구문 분석하는 것이 좋습니다. –

+0

@kindall 기술적으로 헤더를 파싱하는 것은 그리 복잡하지 않습니다. 먼저 그들이 얼마나 많은 선을 차지하고 있는지 측정해야합니다. 그런 다음 각 행의 오른쪽에 얼마나 많은 공간을 추가해야 하는지를 측정 할 수 있습니다. 그런 다음 열을 시작하는 각 문자는 이름이고 열 끝의 각 문자는 다른 이름입니다. 열은'----'기호입니다. 복잡한 것은 아니며 불가능한 것도 아닙니다. –

답변

3

이 문제는 실제로 테이블이 pre 요소 내부 일반 텍스트에 있기 때문에을 분석 텍스트로 제공됩니다.

다음은 사용자가 시작할 수있는 것입니다. 생각은 테이블 다음에 ----- 헤더와 빈 줄을 사용하여 테이블의 시작과 끝을 감지하는 것입니다. 이 라인을 따라 뭔가 :이 목록의 목록을 인쇄 할

import re 

from bs4 import BeautifulSoup 
import requests 
from ppprint import pprint 

url = "https://www.countyofdane.com/clerk/elect2008d.html" 
response = requests.get(url) 

soup = BeautifulSoup(response.content, "html.parser") 

is_table_row = False 

tables = [] 
for line in soup.pre.get_text().splitlines(): 
    # beginning of the table 
    if not is_table_row and "-----" in line: 
     is_table_row = True 
     table = [] 
     continue 

    # end of the table 
    if is_table_row and not line.strip(): 
     is_table_row = False 
     tables.append(table) 
     continue 

    if is_table_row: 
     table.append(re.split("\s{2,}", line)) # splitting by 2 or more spaces 

pprint(tables) 

- 모든 테이블의 데이터 행 하위 목록 :

[ 
    [ 
     ['0001 T ALBION WDS 1-2', '753', '315', '2', '4', '1', '0', '5', '2', '0', '1'], 
     ['0002 T BERRY WDS 1-2', '478', '276', '0', '0', '0', '0', '2', '0', '0', '1'], 
     ... 
     ['', 'CANDIDATE TOTALS', '205984', '73065', '435', '983', '103', '20', '1491', '316', '31', '511'], 
     ['', 'CANDIDATE PERCENT', '72.80', '25.82', '.15', '.34', '.03', '.52', '.11', '.01', '.18']], 
    [ 
     ['0001 T ALBION WDS 1-2', '726', '323', '0'], 
     ['0002 T BERRY WDS 1-2', '457', '290', '1'], 
     ['0003 T BLACK EARTH', '180', '107', '0'], 
     ... 
    ], 
    ... 
] 

이, 물론, 테이블 이름과 대각선 헤더를 포함하지 않는다 그것을 얻기는 어려울 수 있지만 불가능하지는 않습니다. 또한 테이블의 다른 데이터 행과 전체 행을 구분해야 할 수 있습니다. 어쨌든, 나는 이것이 당신을위한 좋은 출발점이 될 수 있다고 생각합니다.

+0

죄송합니다. 두 가지 멍청한 질문 : 1) ".pre"는 "for soup.pre.get_text(). splitlines() :"에서 무엇을합니까? 더 이상 ppprint하는 데 어려움을 겪고 있습니다. 선적 서류 비치? 내가 당신과 똑같은 것을보고 있는지 확인하고 싶습니다. – kfish15

+0

@ kfish15, 문제 없습니다. 1)'soup.pre'는'soup.find ("pre")'와 같습니다. 2)'pprint()'는 예쁜 인쇄용으로, 코드 샘플에서 사용하기위한 기능적인 목적이 없습니다. 감사. – alecxe