본문 바로가기

크롤링

Crawling, English Linguistics 논문 초록 가져오기

728x90

학술제를 준비하며, Linguistics 관련 논문 Abstract 데이터가 필요했다. 좋은 사이트를 찾기 위해서 정말 많이 찾아보았지만, 아래의 사이트가 그나마 괜찮았다.


크롤링 사이트

lingbuzz - archive of linguistics articles


URL 구조 및 설명


카테고리 페이지

  • 논문을 담고있는 테이블은 html 중 2번째 테이블, table > tbody > tr 의 td 첫번째 자식

      tables = html.select('table')
      temp_table = tables[2]
      paper_table = temp_table.select_one('table')
  • td 안에 또 table이 존재하고, 그 안의 tr들이 각 논문을 담고 있다.

      rows = paper_table.select('tr')
  • tr 안에 td 중 마지막 요소가 논문 detail 페이지의 href를 가지고 있다.

      for row in rows:
            detail_url = row.select('td')[-1].select_one("a")['href']
            detail_page = requests.get(base + detail_url)
            detail_page_html = bs(detail_page.text, 'html.parser')

Detail Page

  • 논문 제목 : center > font > a 태그

    • bs4객체.제거할태그.extract() : 제거 + 해당 태그를 return

      title = detail_page_html.select_one("center").font.extract().text
  • 논문 저자 : center > a 태그

      author_list = detail_page_html.select("center a")
    
      # author 추출
      author = ''
      for person in author_list:
          author += person.text + ', '
      author = author.strip(', ')
  • 논문 내용 : body태그 내에 아무 태그 없이 존재 → 나머지 태그를 제거해야됨

    • bs4객체.제거할태그.decompose() : return 값 없이 태그 제거

      # abstract 만을 남겨놓기 위한 태그 삭제
      detail_page_html.center.decompose()
      detail_page_html.title.decompose()
      detail_page_html.table.decompose()
      detail_page_html.table.decompose()
      detail_page_html.p.decompose()
      
      abstract = detail_page_html.text

기타

논문 Abstract에 프랑스어와 같은 인코딩 없이 들어갈 수 없는 문자들이 있어서 utf-8-sig로 인코딩을 해주었다. 하지만 utf-8로도 인코딩이 불가한 특수문자들이 존재했다. 예를 들어 작은따옴표(’), 쌍따옴표(”)과 같은 것들이 일반적으로 쓰는 문자가 아닌 특수문자로 되어있어서 replace를 해주었고, 간혹 text에 JS 코드가 섞인게 있어서 그것 또한 replace를 해주었다.

https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa31122a9-b058-4d04-8e27-d3f512e06d44%2FUntitled.png?table=block&id=ec9f1884-9e62-468f-9374-e06b68592c14&width=3070&userId=5789effa-edf3-43f5-ad7c-8247a5264b62&cache=v2


전체 코드

import requests
from bs4 import BeautifulSoup as bs

def crawl(cate):
    total = []
    base = 'https://ling.auf.net/'
    'https://ling.auf.net/lingbuzz/_listing?community=Phonology&start=31'
    print(cate)
    print()
    start = 1
    while True:
        base_url = base + "lingbuzz/_listing?community=" + cate + "&start=" + str(start)
        res = requests.get(base_url)
        html = bs(res.text, 'html.parser')

        tables = html.select('table')
        temp_table = tables[2]
        paper_table = temp_table.select_one('table')
        if len(paper_table.text.strip()) == 0:
            break

        rows = paper_table.select('tr')

        for row in rows:
            paper = {'category' : cate}
            detail_url = row.select('td')[-1].select_one("a")['href']
            detail_page = requests.get(base + detail_url)
            detail_page_html = bs(detail_page.text, 'html.parser')

            # title 추출 및 제거
            title = detail_page_html.select_one("center").font.extract().text
            print(cate, len(total), title)
            paper['title'] = title
            author_list = detail_page_html.select("center a")

            # author 추출
            author = ''
            for person in author_list:
                author += person.text + ', '
            author = author.strip(', ')
            paper['author'] = author

                        # abstract 만을 남겨놓기 위한 태그 삭제
            detail_page_html.center.decompose()
            detail_page_html.title.decompose()
            detail_page_html.table.decompose()
            detail_page_html.table.decompose()
            detail_page_html.p.decompose()

            abstract = detail_page_html.text.replace('’',"'").replace('“','"').replace("혻혻","").replace("/*<![CDATA[*/function onLoad(){};/*]]>*/", "").replace('”', '"').replace("—","-").replace("‘","'").strip()
            paper['abstract'] = abstract
            paper['url'] = base + detail_url
            total.append(paper)
                # 시작페이지 수 증가
        if start == 1:
            start += 30
        else:
            start += 100
        # csv로 저장
    import pandas as pd
    data = pd.DataFrame(total)
    data.to_csv(cate + ".csv", encoding='utf-16')

# 4개 토픽 스레드로 처리
import threading

category = ['phonology', 'semantics', 'syntax', 'morphology']

thread_count = len(category)
threads = []

# 새로운 스레드 생성/실행 후 스레드 리스트에 추가
for i in range(thread_count):
    thread = threading.Thread(target=crawl, args=( (category[i], ) ))
    thread.start()
    threads.append(thread)

# 메인 스레드는 각 스레드의 작업이 모두 끝날 때까지 대기
for thread in threads:
    thread.join()
728x90

'크롤링' 카테고리의 다른 글

Selenium  (0) 2021.02.17