Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

파이썬 - 웹 페이지 데이터 수집을 위한 scrapy Crawler 사용법 요약

윈도우 사용자라고 해도, 간단한 실습에 불과하니 쓸데없이 ^^ 디렉터리를 어지럽히지 말고 WSL에 맡기면 좋습니다. 게다가 파이썬 환경이니 virtualenv로 한 번 더 격리를 하면 좋겠지요. ^^

$ cd ~
~$ mkdir pyenv
~$ cd pyenv

~/pyenv$ virtualenv scraptest

~/pyenv$ source scraptest/bin/activate

(scraptest) testusr@TESTPC:~/pyenv$

scrapy를 설치하고,

(scraptest) testusr@TESTPC:~/pyenv$ pip install scrapy

(scraptest) testusr@TESTPC:~/pyenv$ python --version
Python 3.8.10


(scraptest) testusr@TESTPC:~/pyenv$ scrapy --version
Scrapy 2.5.0 - no active project

Usage:
  scrapy <command> [options] [args]

Available commands:
  bench         Run quick benchmark test
  commands
  fetch         Fetch a URL using the Scrapy downloader
  genspider     Generate new spider using pre-defined templates
  runspider     Run a self-contained spider (without creating a project)
  settings      Get settings values
  shell         Interactive scraping console
  startproject  Create new project
  version       Print Scrapy version
  view          Open URL in browser, as seen by Scrapy

  [ more ]      More commands available when run from project directory

Use "scrapy <command> -h" to see more info about a command

프로젝트를 하나 만듭니다.

(scraptest) testusr@TESTPC:~/pyenv$ cd scraptest/
(scraptest) testusr@TESTPC:~/pyenv/scraptest$

(scraptest) testusr@TESTPC:~/pyenv/scraptest$ scrapy startproject sample1
New Scrapy project 'sample1', using template directory '/home/testusr/pyenv/scraptest/lib/python3.8/site-packages/scrapy/templates/project', created in:
    /home/testusr/pyenv/scraptest/sample1

You can start your first spider with:
    cd sample1
    scrapy genspider example example.com

(scraptest) testusr@TESTPC:~/pyenv/scraptest$ cd sample1/
(scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$

스파이더를 생성하고,

(scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ scrapy genspider sysnet sysnet.pe.kr
Created spider 'sysnet' using template 'basic' in module:
  sample1.spiders.sysnet

(scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ tree
.
├── sample1
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   └── settings.cpython-38.pyc
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       ├── __pycache__
│       │   └── __init__.cpython-38.pyc
│       └── sysnet.py
└── scrapy.cfg

(scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ cat sample1/spiders/sysnet.py
import scrapy

class SysnetSpider(scrapy.Spider):
    name = 'sysnet'
    allowed_domains = ['sysnet.pe.kr']
    start_urls = ['http://sysnet.pe.kr/']

    def parse(self, response):
        pass

여기서, scrap 관련한 코드를 원하는 목적에 맞게 수정해야 합니다. 가령 제 경우에는 제 웹 사이트에 있는 글의 "제목"을 스크립하고 싶은데요, 다음과 같은 식으로 위의 코드를 변경해야 합니다.

# items.py의 기본 내용을 다음과 같이 변경
import scrapy

class Sample1Item(scrapy.Item):
    title = scrapy.Field()

# ./spiders/sysnet.py의 기본 내용을 다음과 같이 변경

import scrapy
from ..items import Sample1Item

class SysnetSpider(scrapy.Spider):
    name = 'sysnet'
    allowed_domains = ['www.sysnet.pe.kr']
    start_urls = ['https://www.sysnet.pe.kr/']

    def start_requests(self):
        maxPage = 5

        for i in range(0, maxPage):
            yield scrapy.Request(self.start_urls[0] + "Default.aspx?mode=2&sub=0&pageno={0}".format(i), self.parse)

    def parse(self, response):
        items = []

        # CSS 예제 (1)
        # for article in response.css('#contentPane > table.postlist > tr'):
        #     item = Sample1Item()
        #     item['title'] = article.css("td:nth-child(5) > a::text").extract()[0]
        #     items.append(item)

        # CSS 예제 (1)
        # for article in response.css('#contentPane > table.postlist > tr > td:nth-child(5) > a::text'):
        #     item = Sample1Item()
        #     item['title'] = article.extract()
        #     items.append(item)

        # XPath 예제 (1)
        # for article in response.xpath('//*[@id="contentPane"]/table[2]/tr'):
        #     item = Sample1Item()
        #     item['title'] = article.xpath("td[5]/a/node()").extract()[0]
        #     items.append(item)

        # XPath 예제 (2)
        for article in response.xpath('//*[@id="contentPane"]/table[2]/tr/td[5]/a/node()'):
            item = Sample1Item()
            item['title'] = article.extract()
            items.append(item)

            print(item['title'])

        return items

# pipelines.py의 기본 내용을 다음과 같이 변경

from itemadapter import ItemAdapter
from scrapy.exporters import JsonItemExporter
import codecs

class Sample1Pipeline:
    def process_item(self, item, spider):
        return item

class JsonPipeline:
    def __init__(self):
        self.file = open('result.json', 'wb')
        self.exporter = JsonItemExporter(self.file, encoding='utf-8', ensure_ascii=False)
        self.exporter.start_exporting()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

    def close_spider(self, spider):
        self.exporter.finish_exporting()
        self.file.close()

# settings.py에 ITEM_PIPELINES 설정을 새롭게 추가

# ...[생략]...

ITEM_PIPELINES = {
    'sample1.pipelines.JsonPipeline': 300,
}

# ...[생략]...

이렇게 하고, scrapy를 다음과 같이 실행하면,

(scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ scrapy crawl sysnet

오류 없이 실행되었으면 result.json 파일에 다음과 같이 5페이지에 해당하는 분량의 제목이 추출된 것을 볼 수 있습니다. ^^

[{"title": "기부/후원"},{"title": ".NET Framework: 1113. C# 10 - (13) 문자열 보간 성능 개선"},{"title": "개발 환경 구성: 603. GoLand - WSL 환경과 연동"},...[생략]...,{"title": ".NET Framework: 1080. xUnit 단위 테스트에 메서드/클래스 수준의 문맥 제공 - Fixture"},{"title": ".NET Framework: 1079. MSTestv2 단위 테스트에 메서드/클래스/어셈블리 수준의 문맥 제공"},{"title": ".NET Framework: 1078. C# 단위 테스트 - MSTestv2/NUnit의 Assert.Inconclusive 사용법(?)"}]





위에서, Spider의 parse 함수 내의 코드에서 결과물을 XPath 또는 CSS를 이용해 select하는 것이 어려울 때는 scrapy를 명령행에서 실행시켜 테스트하는 것이 더 편합니다.

일례로, 위의 경우 페이지 하나를 scrap 하는 다음의 명령을 실행하고,

$ scrapy shell 'https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0'
...[생략]...
021-09-04 16:56:06 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0> (referer: None)
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x7f063aad5100>
[s]   item       {}
[s]   request    <GET https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0>
[s]   response   <200 https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0>
[s]   settings   <scrapy.settings.Settings object at 0x7f063aad2d90>
[s]   spider     <SysnetSpider 'sysnet' at 0x7f063a7a4100>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
>>>

진입한 shell 모드에서 다음과 같은 식으로 테스트해 볼 수 있습니다.

>>> response.css('#contentPane > table.postlist > tbody').getall()
[]
>>> response.css('#contentPane > table.postlist > tr').getall()
[...[생략]...]




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 10/1/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 181  182  183  184  185  186  [187]  188  189  190  191  192  193  194  195  ...
NoWriterDateCnt.TitleFile(s)
312정성태8/5/200631303    답변글 디버깅 기술: 5.3. PDB 파일에 따른 Debug 정보 - .NET 2.0 Web Site Model 유형의 프로젝트
313정성태8/12/200630440    답변글 디버깅 기술: 5.4. VS.NET 2005 디버그 모드에서의 PDB 파일 사용 차이 (1)
317정성태8/12/200627793    답변글 디버깅 기술: 5.5. VS.NET 2005 디버그 모드에서의 PDB 파일 사용 차이 (2)
318정성태8/12/200634232    답변글 디버깅 기술: 5.6. VS.NET 2005를 이용한 미니덤프 파일 분석 (1)
319정성태8/12/200629410    답변글 디버깅 기술: 5.7. VS.NET 2005를 이용한 미니덤프 파일 분석 (2) [1]
320정성태8/12/200633449    답변글 디버깅 기술: 5.8. WinDBG를 이용한 미니덤프 파일 분석 [1]
321정성태8/13/200638113    답변글 디버깅 기술: 5.9. Microsoft의 PDB 파일 관리
323정성태8/15/200639458    답변글 디버깅 기술: 5.10. Symbol Server 생성 [4]
324정성태8/15/200635994    답변글 디버깅 기술: 5.11. PDB 파일과 소스 코드
325정성태9/8/200628763    답변글 디버깅 기술: 5.12. CCP를 이용한 Windows Source Code 수준의 디버깅
329정성태8/19/200627688    답변글 디버깅 기술: 5.13. 소스 서버 구성 [1]
332정성태8/20/200629195    답변글 디버깅 기술: 5.14. GAC 에 등록된 Assembly 디버그 [2]
341정성태9/16/200621570    답변글 디버깅 기술: 5.15. [내용 예약]
342정성태9/16/200639133    답변글 디버깅 기술: 5.16. ASP.NET 디버깅 환경 구성 [1]파일 다운로드1
306정성태2/13/200718614기타: 15. .NET 이 생산성이 높다는 증거(!)
304정성태7/21/200620664VS.NET IDE: 41. 하위 폴더의 모든 프로젝트의 출력물을 제거 (Clean)
305정성태7/21/200620367    답변글 VS.NET IDE: 41.1. 하위 폴더의 모든 프로젝트의 출력물을 제거 (Clean) [1]
303정성태7/20/200618309Team Foundation Server: 12. 사용자 계정 재생성에 따른 Version Control 영향
302정성태8/21/200620040Team Foundation Server: 11. TFS Team Build와 VC++ Project 설정
299정성태7/23/200620196개발 환경 구성: 5. VMWare - VM 생성 화면 캡쳐
300정성태7/15/200624765    답변글 개발 환경 구성: 5.1. VMWare 오류 유형 - The handle is invalid.
301정성태7/18/200619767    답변글 개발 환경 구성: 5.2. VMWare - 사용 후기.
298정성태7/14/200619997개발 환경 구성: 4. VMWare Server를 64bit 운영체제에 설치 시 주의 사항 [2]
296정성태7/10/200629333.NET Framework: 73. [ASP.NET] HTC(DHTML Control Behavior)를 WebResource.axd로 제공하는 방법 [3]
295정성태7/1/200622630VC++: 25. Microsoft National Language Support Downlevel APIs 1.0 사용 방법파일 다운로드1
294정성태6/30/200619165.NET Framework: 72. XSDObjectGen.EXE 기능 개선
... 181  182  183  184  185  186  [187]  188  189  190  191  192  193  194  195  ...