Zhihu는 각계각층의 엘리트들을 연결하는 친절하고 합리적이며 진지한 커뮤니티 분위기를 갖춘 진정한 온라인 Q&A 커뮤니티입니다. 그들은 서로의 전문 지식, 경험 및 통찰력을 공유하고 중국 인터넷에 고품질 정보를 지속적으로 제공합니다.
먼저 로고를 디자인하는 데 3~5분 정도 소요됩니다. =프로그래머로서 저는 항상 예술가가 되고 싶은 마음을 가지고 있었습니다!
좋습니다. 임시변통이므로 지금은 이만 처리하겠습니다.
다음으로 우리는 Zhihu의 크롤러를 만들기 시작했습니다.
먼저 첫 번째 목표인 편집자 추천을 결정합니다.
웹 링크: http://www.zhihu.com/explore/recommendations
페이지의 콘텐츠를 얻는 기능을 먼저 달성하기 위해 마지막 코드를 약간 수정했습니다.
import java.io.*;
java.net.* 가져오기;
import java.util.regex.*;
공개 클래스 메인 {
정적 문자열 SendGet(문자열 URL) {
//웹 페이지 콘텐츠를 저장할 문자열을 정의합니다.
문자열 결과 = "";
//버퍼링된 문자 입력 스트림 정의
BufferedReader = null;
노력하다 {
//문자열을 URL 객체로 변환
URL realUrl = 새 URL(url);
// 해당 URL에 대한 링크를 초기화합니다.
URLConnection 연결 = realUrl.openConnection();
// 실제 연결 시작
연결.연결();
//URL의 응답을 읽기 위해 BufferedReader 입력 스트림을 초기화합니다.
in = 새로운 BufferedReader(새로운 InputStreamReader(
연결.getInputStream()));
// 캡처된 각 행의 데이터를 임시로 저장하는 데 사용됩니다.
스트링라인;
while ((line = in.readLine()) != null) {
// 캡처된 각 행을 순회하여 결과에 저장합니다.
결과 += 줄;
}
} 잡기(예외 e) {
System.out.println("GET 요청을 보내는 중 예외가 발생했습니다!" + e);
e.printStackTrace();
}
// 입력 스트림을 닫으려면 finally를 사용하세요.
마지막으로 {
노력하다 {
if (in != null) {
넣다();
}
} 잡기(예외 e2) {
e2.printStackTrace();
}
}
결과 반환;
}
정적 문자열 RegexString(문자열 targetStr, 문자열 패턴Str) {
// 정규식을 사용하여 스타일 템플릿을 정의하고 캡처할 내용은 괄호 안에 있습니다.
// 함정을 묻는 것과 동일하며 일치하면 떨어집니다.
패턴 패턴 = Pattern.compile(patternStr);
//매칭을 위한 매처 정의
일치자 matcher = Pattern.matcher(targetStr);
// 발견된 경우
if (matcher.find()) {
// 결과를 출력한다
matcher.group(1)을 반환합니다.
}
"아무것도"를 반환합니다.
}
공개 정적 무효 메인(String[] args) {
// 방문할 링크 정의
문자열 url = "http://www.zhihu.com/explore/recommendations";
//링크에 액세스하여 페이지 콘텐츠 가져오기
문자열 결과 = SendGet(url);
// 정규식을 사용하여 이미지의 src 콘텐츠를 일치시킵니다.
//String imgSrc = RegexString(result, "src=/"(.+?)/"");
// 결과 출력
System.out.println(결과);
}
}
실행한 후에는 문제가 없습니다. 다음 단계는 일반적인 매칭 문제입니다.
먼저 이 페이지의 모든 질문을 받아보겠습니다.
제목을 마우스 오른쪽 버튼으로 클릭하고 요소를 검사합니다.
아하, 제목이 실제로는 하이퍼링크인 a 태그인 것을 알 수 있는데, 다른 하이퍼링크와 구별할 수 있는 것은 클래스 선택자인 클래스여야 합니다.
따라서 우리의 정규문은 다음과 같습니다: Question_link.+?href=/"(.+?)/"
RegexString 함수를 호출하고 매개변수를 전달합니다.
공개 정적 무효 메인(String[] args) {
// 방문할 링크 정의
문자열 url = "http://www.zhihu.com/explore/recommendations";
//링크에 액세스하여 페이지 콘텐츠 가져오기
문자열 결과 = SendGet(url);
// 정규식을 사용하여 이미지의 src 콘텐츠를 일치시킵니다.
String imgSrc = RegexString(result, "question_link.+?>(.+?)<");
// 결과 출력
System.out.println(imgSrc);
}
아하, 제목을 성공적으로 캡처한 것을 볼 수 있습니다(참고: 하나만).
잠깐만, 이 난장판은 다 뭐야? !
긴장하지 마세요 =. =그냥 왜곡된 문자일 뿐입니다.
인코딩 문제는 HTML 문자 집합을 참조하세요.
일반적으로 중국어를 더 잘 지원하는 주류 인코딩은 UTF-8, GB2312 및 GBK 인코딩입니다.
웹페이지는 메타 태그의 문자 집합을 통해 웹페이지 인코딩을 설정할 수 있습니다. 예를 들면 다음과 같습니다.
<meta charset="utf-8" />
페이지 소스 코드를 보려면 마우스 오른쪽 버튼을 클릭하세요.
보시다시피 Zhihu는 UTF-8 인코딩을 사용합니다.
여기에서는 페이지 소스 코드를 보는 것과 요소를 검사하는 것의 차이점을 설명하겠습니다.
페이지 소스 코드를 보는 것은 전체 페이지의 코드를 모두 표시합니다. 이는 HTML 태그에 따라 형식화되지 않습니다. 이는 소스 코드를 직접 보는 것과 같습니다. 메타.
요소 검사(Inspect element) 또는 일부 브라우저에서는 이를 뷰 요소(view element)라고 부르는데, 이는 div 또는 img와 같이 마우스 오른쪽 버튼을 클릭한 요소를 보는 것입니다. 개체의 속성 및 태그를 개별적으로 보는 데 더 적합합니다.
자, 이제 문제가 인코딩에 있다는 것을 알았습니다. 다음 단계는 캡처된 콘텐츠의 인코딩을 변환하는 것입니다.
Java에서의 구현은 매우 간단합니다. 단지 InputStreamReader에서 인코딩 방법을 지정하기만 하면 됩니다.
//URL의 응답을 읽기 위해 BufferedReader 입력 스트림을 초기화합니다.
in = 새로운 BufferedReader(새로운 InputStreamReader(
Connection.getInputStream(),"UTF-8"));
이때 프로그램을 다시 실행하면 제목이 정상적으로 표시되는 것을 확인할 수 있습니다.
좋아요! 매우 좋은!
하지만 이제 제목은 하나뿐이므로 모든 제목이 필요합니다.
정규식을 약간 수정하고 검색된 결과를 ArrayList에 저장합니다.
import java.io.*;
java.net.* 가져오기;
import java.util.ArrayList;
import java.util.regex.*;
공개 클래스 메인 {
정적 문자열 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();
}
}
결과 반환;
}
static ArrayList<String> RegexString(String targetStr, String PatternStr) {
// 결과를 저장할 ArrayList를 미리 정의합니다.
ArrayList<String> 결과 = new ArrayList<String>();
// 정규식을 사용하여 스타일 템플릿을 정의하고 캡처할 내용은 괄호 안에 있습니다.
패턴 패턴 = Pattern.compile(patternStr);
//매칭을 위한 매처 정의
일치자 matcher = Pattern.matcher(targetStr);
// 발견된 경우
부울 isFind = matcher.find();
// 루프를 사용하여 문장의 모든 켈빈을 찾아 바꾸고 내용을 sb에 추가합니다.
동안(isFind) {
//성공적인 일치 결과 추가
results.add(matcher.group(1));
// 다음 일치하는 객체를 계속해서 찾습니다.
isFind = matcher.find();
}
결과를 반환합니다.
}
공개 정적 무효 메인(String[] args) {
// 방문할 링크 정의
문자열 url = "http://www.zhihu.com/explore/recommendations";
//링크에 액세스하여 페이지 콘텐츠 가져오기
문자열 결과 = SendGet(url);
// 정규식을 사용하여 이미지의 src 콘텐츠를 일치시킵니다.
ArrayList<String> imgSrc = RegexString(result, "question_link.+?>(.+?)<");
// 결과 출력
System.out.println(imgSrc);
}
}
이는 모든 결과와 일치합니다(ArrayList가 직접 인쇄되므로 일부 대괄호와 쉼표가 있습니다).
자, 이것이 Zhihu 크롤러의 첫 번째 단계입니다.
하지만 이런 방식으로는 모든 질문과 답변을 담아낼 수 있는 방법은 없다는 것을 알 수 있습니다.
캡처된 모든 개체를 저장하려면 Zhihu 캡슐화 클래스를 설계해야 합니다.
Zhihu.java 소스 코드:
import java.util.ArrayList;
공개 클래스 Zhihu {
공개 문자열 질문 // 질문
공개 문자열 zhihuUrl;//웹페이지 링크
public ArrayList<String> Answers; // 모든 답변을 저장할 배열
// 생성자가 데이터를 초기화합니다.
공개 지후() {
질문 = "";
zhihuUrl = "";
답변 = new ArrayList<String>();
}
@보수
공개 문자열 toString() {
return "질문:" + 질문 + "/nLink:" + zhihuUrl + "/nAnswer:" + 답변 + "/n";
}
}
일반적으로 사용되는 크롤러 기능을 저장하기 위해 새로운 Spider 클래스를 만듭니다.
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();
}
}
결과 반환;
}
static ArrayList<Zhihu> GetZhihu(문자열 내용) {
// 결과를 저장할 ArrayList를 미리 정의합니다.
ArrayList<Zhihu> 결과 = new ArrayList<Zhihu>();
// 제목을 일치시키는 데 사용됩니다.
패턴 질문Pattern = Pattern.compile("question_link.+?>(.+?)<");
일치자questionMatcher=questionPattern.matcher(content);
// 질문에 대한 링크인 URL과 일치하는 데 사용됩니다.
패턴 urlPattern = Pattern.compile("question_link.+?href=/"(.+?)/"");
일치자 urlMatcher = urlPattern.matcher(content);
// 질문과 링크가 모두 일치해야 합니다.
부울 isFind = 질문Matcher.find() && urlMatcher.find();
동안(isFind) {
//캡처된 정보를 저장할 Zhihu 객체를 정의합니다.
지후 zhuhuTemp = new Zhihu();
zhuhuTemp.question = QuestionMatcher.group(1);
zhuhuTemp.zhihuUrl = "http://www.zhihu.com" + urlMatcher.group(1);
//성공적인 일치 결과 추가
results.add(zhuhuTemp);
// 다음 일치하는 객체를 계속해서 찾습니다.
isFind = 질문Matcher.find() && urlMatcher.find();
}
결과를 반환합니다.
}
}
마지막 주요 메소드는 호출을 담당합니다.
import java.util.ArrayList;
공개 클래스 메인 {
공개 정적 무효 메인(String[] args) {
// 방문할 링크 정의
문자열 url = "http://www.zhihu.com/explore/recommendations";
//링크에 액세스하여 페이지 콘텐츠 가져오기
문자열 내용 = Spider.SendGet(url);
// 이 페이지의 모든 Zhihu 개체를 가져옵니다.
ArrayList<Zhihu> myZhihu = Spider.GetZhihu(content);
// 결과 출력
System.out.println(myZhihu);
}
}
알았어, 그게 다야. 실행하고 결과를 확인하세요.
좋은 결과.
다음 단계는 링크에 액세스하여 모든 답변을 얻는 것입니다.
다음번에 소개해드리겠습니다.
좋아요, 위 내용은 Zhihu 편집자가 추천하는 콘텐츠를 캡처하기 위해 Java를 사용하는 전체 과정에 대한 간략한 소개입니다. 도움이 필요한 친구들은 이를 참조하고 자유롭게 확장할 수 있습니다. 하하.