본 게시글은 nomade.kr의 문제를 보고 풀이한 게시글입니다.
문제주소
https://askdjango.github.io/lv3/
문제 화면
여기서 list 제목만 출력해 보겠습니다.
1. 페이지 살펴보기
[오른마우스 클릭] - [페이지소스보기]를 선택하여 확인한 결과 자바스크립트로 보내주고 있는 것을 확인하였습니다.
그렇다면 이 자바스크립트를 가지고 와서 출력하면 되겠네요.
주의사항
BeautifulSoup는 해당 자바스크립트 부분을 일반 문자열로 인식하기 때문에 따로 가져와서 출력해줘야 합니다.
1 2 3 4 5 6 | import re #정규표현식 import requests url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text print(html) | cs |
url을 html에 넣고 text로 출력해보았습니다.
나오긴 나왔지만 모든내용 전체가 나왔습니다.
당연한 결과죠. 이제 이부분을 제가 원하는 name부분만 잘라내 보려고 합니다.
자바스크립트 마지막엔 항상 세미콜론(;)이 있으므로 정규표현식을 사용하여 세미콜론 별로 잘라내 보겠습니다.
2. 단순 정규표현식의 이해
1 2 3 4 5 6 7 8 9 10 11 | import re #정규표현식 import requests url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text #정규표현식에서 일부만 매칭되길 원하면 search #정규표현식에서 전부를 매칭되길 원하면 match를 사용 #re.search(r'var courses = ();') # 끝에 있는 ()부분을 뽑아내겠다는 뜻 re.search(r'var courses = (.*);', html) # .: 모든 *:문자열 즉 .* :모든문자열 | cs |
re.search를 사용하여 html문자열 안에 var courses 의 모든문자열(.*) 을 뽑아내겠다는 뜻입니다.
하지만 None를 리턴했기 때문에 반응이 없습니다.
왜그럴까?
파이썬 re 공식문서 (클릭) 에 보시면
라고 나와있습니다.
이 내용이 무엇이냐면 스페셜 캐릭터가 전부 매칭이 되는데, ' . ' 옵션을 주면 newline까지 같이 포함하게 됩니다.
하지만 이 옵션(' . ')이 없으면 newline를 포함하지 않습니다.
지금 이 스크립트에는 한줄 끝날때마다 개행(newline)가 시작되기 때문에 (' , '때문에) 이 필요한 것입니다.
즉 re.S 옵션을 포함시켜줘야 값을 리턴할 수 있다는 말입니다.
코드수정
1 2 3 4 5 6 7 | import re #정규표현식 import requests url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text re.search(r'var courses = (.*);', html, re.S) # re.S를 사용하여 개행을 포함하여 인식한다 | cs |
re.S를 추가시킨 후 실행해 보겠습니다.
지저분하지만 "name": "개발환경 구축하기"라고 반갑게 맞이하고 있습니다.
디테일하게 깎아보겠습니다.
코드
1 2 3 4 5 6 7 8 9 10 11 12 | import re #정규표현식 import requests url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text #matched 변수에 저장을 합니다 matched = re.search(r'var courses = (.*);', html, re.S) #group으로 모두 출력하는데 1번째줄부터 출력합니다. #만약 (0)을 주면 첫째줄인 var courses = [도 출력될것입니다. print(matched.group(1)) | cs |
8번째줄부터 12번째줄 수정.
코드설명은 주석을 달았습니다.
group(1)을 사용하여 var courses안의 1번째줄부터 출력된 것을 확인할 수 있습니다.
보시면 모든 세미콜론(;)을 출력했네요.
그러므로 우린 첫번째 세미콜론만 잘라서 출력해보겠습니다.
? 를 사용한 최소매칭
1 2 3 4 5 6 7 8 9 10 | import re #정규표현식 import requests url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text # ' ? '을 사용하여 최소 매칭을 해줍니다. matched = re.search(r'var courses = (.*?);', html, re.S) print(matched.group(1)) | cs |
8번째 줄만 수정
첫번째 세미콜론 까지만 최소매칭되어 출력되었네요!
그렇다면 이부분이 json문자열로 지정할수 있겠죠?
json 문자열로 지정
1 2 3 4 5 6 7 8 9 10 11 12 | import re import requests import json #json url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text matched = re.search(r'var courses = (.*?);', html, re.S) #print를 json_string으로 변경 json_string = matched.group(1) json.loads(json_string) | cs |
json형태로 잘 가져왔습니다.
이제 다왔습니다 이 목록들을 예쁘게 출력해 보겠습니다.
json 예쁘게 출력하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import re import requests import json url = 'https://askdjango.github.io/lv3/' html = requests.get(url).text matched = re.search(r'var courses = (.*?);', html, re.S) json_string = matched.group(1) #json을 output_list에 삽입 output_list = json.loads(json_string) #json 차례대로 for output in output_list: print('{name} {url}'.format(**output)) | cs |
예쁘게 성공했습니다!!
'파이썬 프로그래밍 > 파이썬 크롤링' 카테고리의 다른 글
[Python] 네이버 검색 크롤링 실습 및 풀이 (11) | 2017.08.05 |
---|---|
[Python] 네이버 실시간검색어 크롤링 실습 (3) | 2017.07.24 |
[Python] 크롤링 예제. Lv2 Ajax 렌더링 크롤링 풀이 (0) | 2017.07.21 |
[Python] 크롤링 예제. Lv1 단순 HTML 크롤링 풀이 (0) | 2017.07.21 |
[Python] Pillow 이미지 붙이기 예제. 웹툰 전부 붙이기 (1) | 2017.07.20 |