초기 단계에서 우리는 다음 링크에서 제목을 크롤링했습니다.
http://www.zhihu.com/explore/recommendations
하지만 분명히 이 페이지에서는 답변을 얻을 수 없습니다.
전체 질문 페이지는 다음과 같습니다.
http://www.zhihu.com/question/22355264
자세히 살펴보면, 아하, 캡슐화 클래스를 추가로 패키징해야 합니다. 질문 설명을 저장하려면 최소한questionDescription이 필요합니다.
import java.util.ArrayList;
공개 클래스 Zhihu {
공개 문자열 질문 // 질문
public String QuestionDescription; // 질문 설명
공개 문자열 zhihuUrl;//웹페이지 링크
public ArrayList<String> Answers; // 모든 답변을 저장할 배열
// 생성자가 데이터를 초기화합니다.
공개 지후() {
질문 = "";
질문설명 = "";
zhihuUrl = "";
답변 = new ArrayList<String>();
}
@보수
공개 문자열 toString() {
return "질문:" + 질문 + "/n" + "설명:" + 질문설명 + "/n"
+ "링크:" + zhihuUrl + "/n답변:" + 답변 + "/n";
}
}
URL 값을 설정하기 위해 Zhihu 생성자에 매개변수를 추가합니다. URL이 결정되므로 질문에 대한 설명과 답변을 캡처할 수 있습니다.
Zhihu 객체를 획득하는 Spider의 방법을 변경하고 URL만 획득해 보겠습니다.
static ArrayList<Zhihu> GetZhihu(문자열 내용) {
// 결과를 저장할 ArrayList를 미리 정의합니다.
ArrayList<Zhihu> 결과 = new ArrayList<Zhihu>();
// 질문에 대한 링크인 URL과 일치하는 데 사용됩니다.
패턴 urlPattern = Pattern.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
일치자 urlMatcher = urlPattern.matcher(content);
//성공적으로 일치하는 객체가 있는지 여부
부울 isFind = urlMatcher.find();
동안(isFind) {
//캡처된 정보를 저장할 Zhihu 객체를 정의합니다.
지후 zhihuTemp = new Zhihu(urlMatcher.group(1));
//성공적인 일치 결과 추가
결과.추가(zhihuTemp);
// 다음 일치하는 객체를 계속해서 찾습니다.
isFind = urlMatcher.find();
}
결과를 반환합니다.
}
다음으로 Zhihu의 구성 방법에서는 URL을 통해 모든 세부 데이터를 가져옵니다.
먼저 URL을 처리해야 합니다. 왜냐하면 일부 답변의 URL은 다음과 같기 때문입니다.
http://www.zhihu.com/question/22355264/answer/21102139
일부는 문제와 관련이 있으며 해당 URL은 다음과 같습니다.
http://www.zhihu.com/question/22355264
그러면 우리에게 분명히 필요한 것은 두 번째 유형이므로 첫 번째 유형의 링크를 두 번째 유형으로 잘라내는 일반 규칙을 사용해야 합니다. 이는 Zhihu에서 함수를 작성하여 수행할 수 있습니다.
// URL 처리
부울 getRealUrl(문자열 URL) {
// http://www.zhihu.com/question/22355264/answer/21102139 변경
//http://www.zhihu.com/question/22355264로 변환
//그렇지 않으면 변화가 없습니다.
패턴 패턴 = Pattern.compile("질문/(.*?)/");
일치자 matcher = Pattern.matcher(url);
if (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} 또 다른 {
거짓을 반환;
}
사실을 반환;
}
다음 단계는 다양한 부품을 얻는 것입니다.
먼저 제목을 살펴보겠습니다.
해당 클래스를 정규 형식으로 파악하면 다음과 같이 작성할 수 있습니다: zm-editable-content/">(.+?)<
결과를 보려면 실행하세요.
아야, 나쁘지 않네.
다음으로 문제 설명을 확인하세요.
아하, 같은 원칙으로 클래스를 가져오세요. 클래스가 이것의 고유 식별자여야 하기 때문입니다.
확인 방법: 페이지 소스 코드를 보려면 마우스 오른쪽 버튼을 클릭하고, 페이지에 다른 문자열이 있는지 확인하려면 Ctrl+F를 클릭하세요.
나중에 확인한 후에 뭔가 정말 잘못되었습니다.
제목 앞의 클래스와 설명 내용 앞의 클래스는 동일합니다.
이는 일반 패턴을 수정해야만 다시 캡처할 수 있습니다.
// 제목 일치
패턴 = Pattern.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
matcher = 패턴.매처(content);
if (matcher.find()) {
질문 = matcher.group(1);
}
// 일치 설명
패턴=패턴
.compile("zh-question-detail.+?<div.+?>(.*?)</div>");
matcher = 패턴.매처(content);
if (matcher.find()) {
질문 설명 = matcher.group(1);
}
마지막으로 답을 얻기 위해 루프를 반복하는 것입니다.
예비 임시 정규문: /answer/content.+?<div.+?>(.*?)</div>
코드를 변경한 후에는 각 웹 페이지를 방문하고 그 내용을 캡처해야 하기 때문에 소프트웨어가 상당히 느리게 실행된다는 것을 알게 됩니다.
예를 들어 에디터가 추천하는 질문이 20개라면 웹페이지를 20번 방문해야 속도가 느려진다.
시도해 보세요. 좋아 보입니다.
좋아, 지금은 이대로 놔두자~ 다음에는 멀티스레딩, 로컬에서 IO 스트림 쓰기 등과 같은 세부적인 조정을 계속해보겠습니다.
첨부된 프로젝트 소스 코드는 다음과 같습니다.
Zhihu.java
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
공개 클래스 Zhihu {
공개 문자열 질문 // 질문
public String QuestionDescription; // 질문 설명
공개 문자열 zhihuUrl;//웹페이지 링크
public ArrayList<String> Answers; // 모든 답변을 저장할 배열
// 생성자가 데이터를 초기화합니다.
공개 Zhihu(문자열 URL) {
//속성 초기화
질문 = "";
질문설명 = "";
zhihuUrl = "";
답변 = new ArrayList<String>();
// URL이 유효한지 확인합니다.
if (getRealUrl(url)) {
System.out.println("crawling" + zhihuUrl);
// URL을 기반으로 질문과 답변의 세부정보를 가져옵니다.
문자열 내용 = Spider.SendGet(zhihuUrl);
패턴 패턴;
일치자 일치자;
// 제목 일치
패턴 = Pattern.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
matcher = 패턴.매처(content);
if (matcher.find()) {
질문 = matcher.group(1);
}
// 일치 설명
패턴=패턴
.compile("zh-question-detail.+?<div.+?>(.*?)</div>");
matcher = 패턴.매처(content);
if (matcher.find()) {
질문 설명 = matcher.group(1);
}
// 답변 일치
패턴 = Pattern.compile("/answer/content.+?<div.+?>(.*?)</div>");
matcher = 패턴.매처(content);
부울 isFind = matcher.find();
동안(isFind) {
Answers.add(matcher.group(1));
isFind = matcher.find();
}
}
}
// 자신의 URL을 기반으로 자신만의 질문, 설명 및 답변을 가져옵니다.
공개 부울 getAll() {
사실을 반환;
}
// URL 처리
부울 getRealUrl(문자열 URL) {
// http://www.zhihu.com/question/22355264/answer/21102139 변경
//http://www.zhihu.com/question/22355264로 변환
//그렇지 않으면 변화가 없습니다.
패턴 패턴 = Pattern.compile("질문/(.*?)/");
일치자 matcher = Pattern.matcher(url);
if (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} 또 다른 {
거짓을 반환;
}
사실을 반환;
}
@보수
공개 문자열 toString() {
return "질문:" + 질문 + "/n" + "설명:" + 질문설명 + "/n"
+ "링크:" + zhihuUrl + "/n답변:" + Answers.size() + "/n";
}
}
Spider.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
java.net.URL 가져오기;
java.net.URLConnection 가져오기;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
공개 클래스 스파이더 {
정적 문자열 SendGet(문자열 URL) {
//웹 페이지 콘텐츠를 저장할 문자열을 정의합니다.
문자열 결과 = "";
//버퍼링된 문자 입력 스트림 정의
BufferedReader = null;
노력하다 {
//문자열을 URL 객체로 변환
URL realUrl = 새 URL(url);
// 해당 URL에 대한 링크를 초기화합니다.
URLConnection 연결 = realUrl.openConnection();
// 실제 연결 시작
연결.연결();
//URL의 응답을 읽기 위해 BufferedReader 입력 스트림을 초기화합니다.
in = 새로운 BufferedReader(새로운 InputStreamReader(
Connection.getInputStream(), "UTF-8"));
// 캡처된 각 행의 데이터를 임시로 저장하는 데 사용됩니다.
스트링라인;
while ((line = in.readLine()) != null) {
// 캡처된 각 행을 순회하여 결과에 저장합니다.
결과 += 줄;
}
} 잡기(예외 e) {
System.out.println("GET 요청을 보내는 중 예외가 발생했습니다!" + e);
e.printStackTrace();
}
// 입력 스트림을 닫으려면 finally를 사용하세요.
마지막으로 {
노력하다 {
if (in != null) {
넣다();
}
} 잡기(예외 e2) {
e2.printStackTrace();
}
}
결과 반환;
}
// 편집자가 추천하는 모든 Zhihu 콘텐츠를 가져옵니다.
static ArrayList<Zhihu> GetRecommendations(문자열 내용) {
// 결과를 저장할 ArrayList를 미리 정의합니다.
ArrayList<Zhihu> 결과 = new ArrayList<Zhihu>();
// 질문에 대한 링크인 URL과 일치하는 데 사용됩니다.
패턴 패턴 = 패턴
.compile("<h2>.+?question_link.+?href="(.+?)/".+?</h2>");
일치자 matcher = Pattern.matcher(content);
//성공적으로 일치하는 객체가 있는지 여부
부울 isFind = matcher.find();
동안(isFind) {
//캡처된 정보를 저장할 Zhihu 객체를 정의합니다.
지후 zhihuTemp = new Zhihu(matcher.group(1));
//성공적인 일치 결과 추가
결과.추가(zhihuTemp);
// 다음 일치하는 객체를 계속해서 찾습니다.
isFind = matcher.find();
}
결과를 반환합니다.
}
}
Main.java
import java.util.ArrayList;
공개 클래스 메인 {
공개 정적 무효 메인(String[] args) {
// 방문할 링크 정의
문자열 url = "http://www.zhihu.com/explore/recommendations";
//링크에 액세스하여 페이지 콘텐츠 가져오기
문자열 내용 = Spider.SendGet(url);
// 편집자 추천 받기
ArrayList<Zhihu> myZhihu = Spider.GetRecommendations(content);
// 결과 출력
System.out.println(myZhihu);
}
}
위의 내용은 Zhihu 답변을 얻은 전체 기록입니다. 도움이 필요한 친구들이 참고할 수 있습니다.