html파일에서 원하는 부분을 끌어오는 대표적인 방법들에 대해서 알아보자.
import requests
from bs4 import BeautifulSoup
url = 'https://kr.indeed.com/%EC%B7%A8%EC%97%85?q=django&l=%EC%84%9C%EC%9A%B8+%EA%B0%95%EB%82%A8%EA%B5%AC'
html = requests.get(url).text
soup = BeautifulSoup(html,'html.parser')
우선 해당 페이지의 url을 읽어와 BeautifulSoup parser의 객체를 soup 인스턴스에 넣어준다.
<a target="_blank" id="jl_ffd9cedb23e97344" href="/rc/clk?jk=ffd9cedb23e97344&fccid=df5e7ec512668ebf&vjs=3" onmousedown="return rclk(this,jobmap[0],0);" onclick="setRefineByCookie([]); return rclk(this,jobmap[0],true,0);" rel="noopener nofollow" title="파이썬SW 금융분야 특화 챗봇 개발 함께 할 엔지니어" class="jobtitle turnstileLink " data-tn-element="jobTitle">
<b>파이</b>썬SW 금융분야 특화 챗봇 개발 함께 할 엔지니어</a>
위의 부분은 indeed홈페이지에서 python을 검색하면 title부분에 나오는 html 소스코드이다. 페이지에 있는 모든 title을 가져오기 위해서 우리는 위와같은 title부분에서 공통점을 찾은 결과 class="jobtitle turnstileLink " 부분은 모든 title의 a태그가 가지고 있는 부분이다.
soup.find_all(class_="jobtitle turnstileLink")
위와같이 매서드를 사용해주면 다음과같은 결과가 나온다.
[<a class="jobtitle turnstileLink" data-tn-element="jobTitle" href="/rc/clk?jk=55a19c92c845685e&fccid=74d05cee5b52f133&vjs=3" id="jl_55a19c92c845685e" onclick="setRefineByCookie([]); return rclk(this,jobmap[0],true,0);" onmousedown="return rclk(this,jobmap[0],0);" rel="noopener nofollow" target="_blank" title="Developer / Designer recruit">
Developer / Designer recruit</a>, <a class="jobtitle turnstileLink" data-tn-element="jobTitle" href="/rc/clk?jk=6c1d50662fa2d7f7&fccid=71bba75c2a7d79a0&vjs=3" id="jl_6c1d50662fa2d7f7" onclick="setRefineByCookie([]); return rclk(this,jobmap[1],true,0);" onmousedown="return rclk(this,jobmap[1],0);" rel="noopener nofollow" target="_blank" title="서울 강남구 인썸니아 시니어 개발자 및 퍼블리셔">
서울 강남구 인썸니아 시니어 개발자 및 퍼블리셔</a>, .........
즉 class="jobtitle turnstileLink"를 가진 a태그를 전부 리스트의 인자로 가져왔다.
여기서 a태그안의 url을 얻기 위해서는 href속성을 가져와야한다.
titles_all[0]['href']
위와같이 반환된 전체리스트인 soup.findall(class="jobtitle turnstileLink")
에서 0번째 인덱스의 'href'속성을 가져오는 코드를 실행해보면
/rc/clk?jk=55a19c92c845685e&fccid=74d05cee5b52f133&vjs=3
와같이 url만 가져온다.
그렇다면 a태그를 명시해주면서 'a태그자체의 속성 href'는 어떻게 가져올 수 있는 직관적인 코드를 알아보자.
titles_all[0].attrs['href']
위의 코드는 titles_all리스트 안의 0번째 인덱스(즉, a태그)에서 'href'속성을 가져오는 함수이다. 즉 titles_all[0]['href']
와 같은 결과를 리턴하지만 a태그 안에서의 attribute인 href를 가져온다는 좀 더 직관적인 코드라고 할수 있다.
여기서 주의할 점은
titles_all[0].a['href']
와 같이 리스트의 0번째 인덱스객체로 취급해서 a태그안의 href를 가져오는 시도는 애러를 발생시킨다는 것이다.
이유는 이미 find_all을 통해서 가져온 값들이 전부 a태그 그 자체이기 때문에 특정 값을 찾을 때 'a태그 안의 href'와 같은 코드를 작성하면 syntax error을 발생시킨다.
이제 해당 url을 가져왔으니 for문을 통해서 모든 url을 추출할 수 있다.
soup.select('div.title > a')
class='title'인 div 태그의 하위 a태그의 값을 가져온다.
[<a class="jobtitle turnstileLink" data-tn-element="jobTitle" href="/rc/clk?jk=55a19c92c845685e&fccid=74d05cee5b52f133&vjs=3" id="jl_55a19c92c845685e" onclick="setRefineByCookie([]); return rclk(this,jobmap[0],true,0);" onmousedown="return rclk(this,jobmap[0],0);" rel="noopener nofollow" target="_blank" title="Developer / Designer recruit">
Developer / Designer recruit</a>, <a class="jobtitle turnstileLink" data-tn-element="jobTitle" href="/rc/clk?jk=6c1d50662fa2d7f7&fccid=71bba75c2a7d79a0&vjs=3" id="jl_6c1d50662fa2d7f7" onclick="setRefineByCookie([]); return rclk(this,jobmap[1],true,0);" onmousedown="return rclk(this,jobmap[1],0);" rel="noopener nofollow" target="_blank" title="서울 강남구 인썸니아 시니어 개발자 및 퍼블리셔">
서울 강남구 인썸니아 시니어 개발자 및 퍼블리셔</a>,.....
위와같이 결과가나오는데 soup.findall(class="jobtitle turnstileLink")
와 똑같이 a태그 전체를 리스트에 담아서 가져온 것을 알 수 있다. 따라서 원하는 값을 얻으려면
titles[0]['href']
titles[0].attrs['href']
둘중 하나를 쓰면 원하는 url을 얻을 수 있다.
하지만 실재로 웹페이지에서 selector 복사를 하면 아래와 같은 값이 복사된다.
soup.select('div.title')
즉, class='title'인 div태그 만으로도 충분히 같은 형식의 원하는 데이터를 가져올 수 있다는 뜻이다.
[<div class="title">
<a class="jobtitle turnstileLink" data-tn-element="jobTitle" href="/rc/clk?jk=55a19c92c845685e&fccid=74d05cee5b52f133&vjs=3" id="jl_55a19c92c845685e" onclick="setRefineByCookie([]); return rclk(this,jobmap[0],true,0);" onmousedown="return rclk(this,jobmap[0],0);" rel="noopener nofollow" target="_blank" title="Developer / Designer recruit">
Developer / Designer recruit</a>
</div>,
결과는 위와같이 나온다. div의 하위테이블에는 우리가 타겟팅하는 a태그밖에 없다. 그렇다면 굳이 a태그 까지 내려갈 필요 없이 url값을 가져올 수 있다.
titles[0].a['href']
이제는 a태그의 부모태그인 div태그 까지 같이 가지고 왔기 때문에 위와같이 titles의 0번째 인덱스값에서 a태그까지 내려가서 href를 찾아줘야 syntax error없이 url값을 리턴한다