성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 ad='python' style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>파이썬 - 웹 페이지 데이터 수집을 위한 scrapy Crawler 사용법 요약</h1> <p> 윈도우 사용자라고 해도, 간단한 실습에 불과하니 쓸데없이 ^^ 디렉터리를 어지럽히지 말고 WSL에 맡기면 좋습니다. 게다가 파이썬 환경이니 virtualenv로 한 번 더 격리를 하면 좋겠지요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>cd ~</span> ~$ <span style='color: blue; font-weight: bold'>mkdir pyenv</span> ~$ <span style='color: blue; font-weight: bold'>cd pyenv</span> ~/pyenv$ <span style='color: blue; font-weight: bold'>virtualenv scraptest</span> ~/pyenv$ <span style='color: blue; font-weight: bold'>source scraptest/bin/activate</span> (scraptest) testusr@TESTPC:~/pyenv$ </pre> <br /> scrapy를 설치하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > (scraptest) testusr@TESTPC:~/pyenv$ <span style='color: blue; font-weight: bold'>pip install scrapy</span> (scraptest) testusr@TESTPC:~/pyenv$ <span style='color: blue; font-weight: bold'>python --version</span> Python 3.8.10 (scraptest) testusr@TESTPC:~/pyenv$ <span style='color: blue; font-weight: bold'>scrapy --version</span> 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 </pre> <br /> 프로젝트를 하나 만듭니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > (scraptest) testusr@TESTPC:~/pyenv$ <span style='color: blue; font-weight: bold'>cd scraptest/</span> (scraptest) testusr@TESTPC:~/pyenv/scraptest$ (scraptest) testusr@TESTPC:~/pyenv/scraptest$ <span style='color: blue; font-weight: bold'>scrapy startproject sample1</span> 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$ </pre> <br /> 스파이더를 생성하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > (scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ <span style='color: blue; font-weight: bold'>scrapy genspider sysnet sysnet.pe.kr</span> Created spider 'sysnet' using template 'basic' in module: sample1.spiders.sysnet (scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ <span style='color: blue; font-weight: bold'>tree</span> . ├── 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$ <span style='color: blue; font-weight: bold'>cat sample1/spiders/sysnet.py</span> import scrapy class SysnetSpider(scrapy.Spider): name = 'sysnet' allowed_domains = ['sysnet.pe.kr'] start_urls = ['http://sysnet.pe.kr/'] def parse(self, response): pass </pre> <br /> 여기서, scrap 관련한 코드를 원하는 목적에 맞게 수정해야 합니다. 가령 제 경우에는 제 웹 사이트에 있는 글의 "제목"을 스크립하고 싶은데요, 다음과 같은 식으로 위의 코드를 변경해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > # items.py의 기본 내용을 다음과 같이 변경 import scrapy class Sample1Item(scrapy.Item): title = scrapy.Field() </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > # ./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 </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > # 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() </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > # settings.py에 ITEM_PIPELINES 설정을 새롭게 추가 # ...[생략]... ITEM_PIPELINES = { 'sample1.pipelines.JsonPipeline': 300, } # ...[생략]... </pre> <br /> 이렇게 하고, scrapy를 다음과 같이 실행하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > (scraptest) testusr@TESTPC:~/pyenv/scraptest/sample1$ <span style='color: blue; font-weight: bold'>scrapy crawl sysnet</span> </pre> <br /> 오류 없이 실행되었으면 result.json 파일에 다음과 같이 5페이지에 해당하는 분량의 제목이 추출된 것을 볼 수 있습니다. ^^<br /> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> [{"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 사용법(?)"}]<br /> </div><br /> <br /> <hr style='width: 50%' /><br /> <br /> 위에서, Spider의 parse 함수 내의 코드에서 결과물을 XPath 또는 CSS를 이용해 select하는 것이 어려울 때는 scrapy를 명령행에서 실행시켜 테스트하는 것이 더 편합니다.<br /> <br /> 일례로, 위의 경우 페이지 하나를 scrap 하는 다음의 명령을 실행하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>scrapy shell</span> '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 <span style='color: blue; font-weight: bold'>>>></span> </pre> <br /> 진입한 shell 모드에서 다음과 같은 식으로 테스트해 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > >>> <span style='color: blue; font-weight: bold'>response.css('#contentPane > table.postlist > tbody').getall()</span> [] >>> <span style='color: blue; font-weight: bold'>response.css('#contentPane > table.postlist > tr').getall()</span> [...[생략]...] </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1596
(왼쪽의 숫자를 입력해야 합니다.)