데이터 읽을 일이 있어서 크롤링하는데
페이지가 EUC-KR로 되어있어 이거 디코딩하는방법을 몰라서.. 시간이 많이들었다.
제목에는 Jsoup만 써놨지만, org.apache.http 패키지(http코어)를 쓸 때도 encoding문제를 해결 할 수 있다.
일단 제목에 나온대로 Jsoup부터 해결방법을 제시하겠다.
--- JSoup 의존라이브러리 ---
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
-- 아파치 코어 의존라이브러리 --
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.12</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
공통 필드
URL객체는 따로 적지않았다. 링크 문자열을 주기 바람
ex) private final static String Url = "http://example.com";
(사실 FINAL 상수 변수명은 대문자로 적어야하는데 URL 객체때문에 불가피했다 다른 이름으로 쓰는것을 권장한다.)
JSoup 해결방법
public static void main(String[] args) throws IOException {
Document doc = Jsoup.parse(new URL(Url).openStream(), "euc-kr", url);
System.out.println(doc.outerHtml());
}
진짜 이 단 두줄이면 끝난다.
첫번째인자는 스트림, 파싱할 문자열셋, 그다음 baseURL(String객체)이다.
URL객체에서 스트림 열어서 주어진 문자열 디코딩하는 것이라고 볼 수 있다.
그렇기때문에, 세번째인자는 중요도가 많이 떨어진다.
스트림에서 디코딩 한 문자열들을 가져오기때문이다.(실질적으로 쓰는게 스트림에서 가져온것들이니까)
겹치는 부분이 아파치 http코어와 많기 때문에 아래에서 다시 설명하겠다.
아파치 HTTP 해결법
public static void main(String[] args) throws IOException {
// 주소 세팅
HttpPost http = new HttpPost(Url);
// 가져오기 실행할 클라이언트 객체 생성
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse response = httpClient.execute(http);
// DOM 데이터 담음
HttpEntity httpEntity = response.getEntity();
ContentType contentType = ContentType.get(httpEntity);
System.out.println(contentType);
BufferedReader is = new BufferedReader(new InputStreamReader(httpEntity.getContent(), "euc-kr"));
StringBuffer sb = new StringBuffer();
String line = "";
while((line = is.readLine()) != null)
{
sb.append(line + "\n");
}
System.out.println(sb.toString());
여기서 우리가 주의깊게봐야하는것은 InputStreamReader이다.
InputStream은 바이트단위, InputStreamReader는 캐릭터형(2byte)단위로 읽는다.
html문서내용은 문자열이기때문에 InputStreamReader로 읽어야하고, InputStreamReader의 생성자 매개변수에는
Charset(문자열 형태도 허용함)이 들어간다.
여기다 해당 문자열 형태만 넣어주면 매우 스무스하게 디코딩이 되는것이다.
여기서 의문을 가질 분들이 있다.
난 데이터 가져와서 byte로 "euc-kr" 인코딩으로 변환한 후에 출력했는데, 왜 문자열이 깨지는거죠?
필자의 생각이지만, 가져올 때 Stream으로 문자열 필터(Filter)를 적용해서 가져오는 것과
가져와서 이미 다 깨진 데이터에 작업을 하는것은.. 근본적으로 다르다고 생각한다.
개인적으로는 자바같은 객체지향에서는 가독성과 코드라인을 줄이는게 최고이므로
활용할 수 있는 라이브러리는 최대한 활용해야하는 것이 필자의 평소생각이므로 JSoup을 많이 사용할 것 같다.
'Java' 카테고리의 다른 글
embed tomcat 설정하기 (2) | 2020.01.29 |
---|---|
H2 데이터베이스 의존성 문제 (0) | 2020.01.16 |
MySQL JDBC 연동 시 타임존 에러 (0) | 2019.12.10 |
Maven Project 빌드 시 (CLI 환경) 각종 설명 및 팁 (0) | 2019.12.09 |
로그백 실행방법(logback, java) (0) | 2019.11.07 |