자바 콩잎 영화 파충류-작은 파충류 성장 기(소스 코드)
그 다음 에 알 수 없 는 Exception 이 해결 되 기 를 기다 리 고 있 을 수도 있 고 일부 성능 도 최적화 되 어야 한다.예 를 들 어 데이터 베이스 와 의 상호작용,데이터 의 읽 기와 쓰기 등 이다.하지만 연내 에 이 위 에 신경 을 많이 쓰 지 않 았 기 때문에 오늘 은 간단 한 정 리 를 하 겠 습 니 다.그리고 앞의 두 편 은 주로 기능 과 결과 에 중심 을 두 었 습 니 다.이 편 은 JewelCrawler 가 어떻게 태 어 났 는 지,그리고 코드 를 Github 에 올 려 놓 았 습 니 다.(소스 주 소 는 글 의 마지막 에 있 습 니 다)관심 있 는 것 은 주목 하 셔 도 됩 니 다.덜 상처
환경 소개
개발 도구:Intellij idea 14
데이터베이스:Mysql 5.5+데이터베이스 관리 도구 Navicat(데이터베이스 연결 가능)
언어:자바
Jar 가방 관리:Maven
버 전 관리:Git
디 렉 터 리 구조
그 속
com.ansj.vec 는 Word2Vec 알고리즘 의 자바 버 전 구현
com.jackie.crawler.doubanmovie 는 파충류 실현 모듈 로 그 중에서 도 포함 된다.
어떤 가방 들 은 비어 있다.왜냐하면 이 모듈 들 은 아직 사용 되 지 않 았 기 때문이다.
4.567917.constants 가방 은 상수 류 를 저장 합 니 다크롤 백 파충류 입구 보관 프로그램entity 패키지 매 핑 데이터베이스 테이블 의 실체 클래스테스트 패키지 저장 테스트 클래스
utils 패키지 저장 도구 류
resource 모듈 은 설정 파일 과 자원 파일 을 저장 합 니 다.예 를 들 어
데이터베이스 설정
1.의존 하 는 가방 추가
JewelCrawler 가 사용 하 는 maven 관리 이기 때문에 pom.xml 에 해당 하 는 의존 도 를 추가 하면 됩 니 다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
2.데이터 원본 bean 설명저 희 는 beans.xml 에서 데이터 원본 을 설명 하 는 bean 이 필요 합 니 다.
<context:property-placeholder location="classpath*:*.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
메모:외부 프로필 jdbc.properties 를 연결 하 였 습 니 다.구체 적 인 데이터 원본 의 매개 변 수 는 이 파일 에서 읽 습 니 다.문제 가 발생 하면"SQL[insert into user(id)values(?)];Field 'name' doesn't have a default value;”해결 방법 은 표 의 해당 필드 를 자체 성장 필드 로 설정 하 는 것 이다.
질문
기어 오 르 는 웹 페이지 데 이 터 는 dom 구 조 를 분석 하고 원 하 는 데 이 터 를 가 져 와 야 합 니 다.그 동안 다음 과 같은 오류 가 발생 했 습 니 다.
org.htmlparser.Node 인식 되 지 않 음
해결 방법:jar 패키지 의존 추가
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>1.6</version>
</dependency>
org.apache.http.HttpEntity 인식 되 지 않 음해결 방법:jar 패키지 의존 추가
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
물론 그동안 겪 었 던 문제 이 고 마지막 으로 Jsoup 이 만 든 페이지 로 해석 했다.maven 창고 다운로드 속도 가 느 립 니 다.
이전 에는 기본 maven 중앙 창 고 를 사 용 했 습 니 다.jar 가방 을 다운로드 하 는 속도 가 느 렸 습 니 다.제 네트워크 문제 인지 다른 원인 인지 모 르 겠 습 니 다.나중에 인터넷 에서 아 리 클 라 우 드 의 maven 창 고 를 찾 았 습 니 다.업 데 이 트 된 후 이전 보다 초 단위 로 피 를 토 하 는 것 을 추천 합 니 다.
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
Maven 의 settings.xml 파일 을 찾 으 면 이 미 러 를 추가 하면 됩 니 다.resource 모듈 에서 파일 을 읽 는 방법
예 를 들 어 seed.properties 파일 읽 기
@Test
public void testFile(){
File seedFile = new File(this.getClass().getResource("/seed.properties").getPath());
System.out.print("===========" + seedFile.length() + "===========" );
}
정규 표현 식regrex 정규 표현 식 을 사용 할 때 정 의 된 Pattern 과 일치 하면 matcher 의 find 방법 을 먼저 호출 한 다음 에 group 방법 으로 하위 문자열 을 찾 을 수 있 습 니 다.그룹 을 직접 호출 하 는 방법 은 당신 이 원 하 는 결 과 를 찾 을 수 없습니다.
위 에 Matcher 류 의 소스 코드 를 봤 어 요.
package java.util.regex;
import java.util.Objects;
public final class Matcher implements MatchResult {
/**
* The Pattern object that created this Matcher.
*/
Pattern parentPattern;
/**
* The storage used by groups. They may contain invalid values if
* a group was skipped during the matching.
*/
int[] groups;
/**
* The range within the sequence that is to be matched. Anchors
* will match at these "hard" boundaries. Changing the region
* changes these values.
*/
int from, to;
/**
* Lookbehind uses this value to ensure that the subexpression
* match ends at the point where the lookbehind was encountered.
*/
int lookbehindTo;
/**
* The original string being matched.
*/
CharSequence text;
/**
* Matcher state used by the last node. NOANCHOR is used when a
* match does not have to consume all of the input. ENDANCHOR is
* the mode used for matching all the input.
*/
static final int ENDANCHOR = 1;
static final int NOANCHOR = 0;
int acceptMode = NOANCHOR;
/**
* The range of string that last matched the pattern. If the last
* match failed then first is -1; last initially holds 0 then it
* holds the index of the end of the last match (which is where the
* next search starts).
*/
int first = -1, last = 0;
/**
* The end index of what matched in the last match operation.
*/
int oldLast = -1;
/**
* The index of the last position appended in a substitution.
*/
int lastAppendPosition = 0;
/**
* Storage used by nodes to tell what repetition they are on in
* a pattern, and where groups begin. The nodes themselves are stateless,
* so they rely on this field to hold state during a match.
*/
int[] locals;
/**
* Boolean indicating whether or not more input could change
* the results of the last match.
*
* If hitEnd is true, and a match was found, then more input
* might cause a different match to be found.
* If hitEnd is true and a match was not found, then more
* input could cause a match to be found.
* If hitEnd is false and a match was found, then more input
* will not change the match.
* If hitEnd is false and a match was not found, then more
* input will not cause a match to be found.
*/
boolean hitEnd;
/**
* Boolean indicating whether or not more input could change
* a positive match into a negative one.
*
* If requireEnd is true, and a match was found, then more
* input could cause the match to be lost.
* If requireEnd is false and a match was found, then more
* input might change the match but the match won't be lost.
* If a match was not found, then requireEnd has no meaning.
*/
boolean requireEnd;
/**
* If transparentBounds is true then the boundaries of this
* matcher's region are transparent to lookahead, lookbehind,
* and boundary matching constructs that try to see beyond them.
*/
boolean transparentBounds = false;
/**
* If anchoringBounds is true then the boundaries of this
* matcher's region match anchors such as ^ and $.
*/
boolean anchoringBounds = true;
/**
* No default constructor.
*/
Matcher() {
}
/**
* All matchers have the state used by Pattern during a match.
*/
Matcher(Pattern parent, CharSequence text) {
this.parentPattern = parent;
this.text = text;
// Allocate state storage
int parentGroupCount = Math.max(parent.capturingGroupCount, 10);
groups = new int[parentGroupCount * 2];
locals = new int[parent.localCount];
// Put fields into initial states
reset();
}
....
/**
* Returns the input subsequence matched by the previous match.
*
* <p> For a matcher <i>m</i> with input sequence <i>s</i>,
* the expressions <i>m.</i><tt>group()</tt> and
* <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt> <i>m.</i><tt>end())</tt>
* are equivalent. </p>
*
* <p> Note that some patterns, for example <tt>a*</tt>, match the empty
* string. This method will return the empty string when the pattern
* successfully matches the empty string in the input. </p>
*
* @return The (possibly empty) subsequence matched by the previous match,
* in string form
*
* @throws IllegalStateException
* If no match has yet been attempted,
* or if the previous match operation failed
*/
public String group() {
return group(0);
}
/**
* Returns the input subsequence captured by the given group during the
* previous match operation.
*
* <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
* <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
* <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt> <i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
* are equivalent. </p>
*
* <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
* to right, starting at one. Group zero denotes the entire pattern, so
* the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
* </p>
*
* <p> If the match was successful but the group specified failed to match
* any part of the input sequence, then <tt>null</tt> is returned. Note
* that some groups, for example <tt>(a*)</tt>, match the empty string.
* This method will return the empty string when such a group successfully
* matches the empty string in the input. </p>
*
* @param group
* The index of a capturing group in this matcher's pattern
*
* @return The (possibly empty) subsequence captured by the group
* during the previous match, or <tt>null</tt> if the group
* failed to match part of the input
*
* @throws IllegalStateException
* If no match has yet been attempted,
* or if the previous match operation failed
*
* @throws IndexOutOfBoundsException
* If there is no capturing group in the pattern
* with the given index
*/
public String group(int group) {
if (first < 0)
throw new IllegalStateException("No match found");
if (group < 0 || group > groupCount())
throw new IndexOutOfBoundsException("No group " + group);
if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
return null;
return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}
/**
* Attempts to find the next subsequence of the input sequence that matches
* the pattern.
*
* <p> This method starts at the beginning of this matcher's region, or, if
* a previous invocation of the method was successful and the matcher has
* not since been reset, at the first character not matched by the previous
* match.
*
* <p> If the match succeeds then more information can be obtained via the
* <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
*
* @return <tt>true</tt> if, and only if, a subsequence of the input
* sequence matches this matcher's pattern
*/
public boolean find() {
int nextSearchIndex = last;
if (nextSearchIndex == first)
nextSearchIndex++;
// If next search starts before region, start it at region
if (nextSearchIndex < from)
nextSearchIndex = from;
// If next search starts beyond region then it fails
if (nextSearchIndex > to) {
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
return false;
}
return search(nextSearchIndex);
}
/**
* Initiates a search to find a Pattern within the given bounds.
* The groups are filled with default values and the match of the root
* of the state machine is called. The state machine will hold the state
* of the match as it proceeds in this matcher.
*
* Matcher.from is not set here, because it is the "hard" boundary
* of the start of the search which anchors will set to. The from param
* is the "soft" boundary of the start of the search, meaning that the
* regex tries to match at that index but ^ won't match there. Subsequent
* calls to the search methods start at a new "soft" boundary which is
* the end of the previous match.
*/
boolean search(int from) {
this.hitEnd = false;
this.requireEnd = false;
from = from < 0 ? 0 : from;
this.first = from;
this.oldLast = oldLast < 0 ? from : oldLast;
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
acceptMode = NOANCHOR;
boolean result = parentPattern.root.match(this, from, text);
if (!result)
this.first = -1;
this.oldLast = this.last;
return result;
}
...
}
그 이 유 는 다음 과 같 습 니 다.여기 서 find 방법 을 먼저 호출 하지 않 고 group 을 직접 호출 하면 group 방법 이 group(int group)을 호출 하 는 것 을 발견 할 수 있 습 니 다.이 방법 은 if first<0 이 있 습 니 다.여기 서 이 조건 이 성립 된 것 이 분명 합 니 다.first 의 초기 값 이-1 이기 때문에 여기 서 이상 을 던 집 니 다.그러나 find 방법 을 호출 하면 최종 적 으로 search(nextSearch Index)를 호출 합 니 다.여기 있 는 nextSearch Index 는 last 에 의 해 할당 되 었 고 last 의 값 은 0 이 며 search 방법 으로 이동 합 니 다.
boolean search(int from) {
this.hitEnd = false;
this.requireEnd = false;
from = from < 0 ? 0 : from;
this.first = from;
this.oldLast = oldLast < 0 ? from : oldLast;
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
acceptMode = NOANCHOR;
boolean result = parentPattern.root.match(this, from, text);
if (!result)
this.first = -1;
this.oldLast = this.last;
return result;
}
이 next SearchIndex 는 from 에 전 달 했 고 from 은 방법 체 에서 first 에 할당 되 었 기 때문에 find 방법 을 호출 한 후에 이 first 는-1 이 아니 라 이상 을 던 지 는 것 이 아 닙 니 다.원본 코드 가 바 이 두 네트워크 에 업로드 되 었 습 니 다http://pan.baidu.com/s/1dFwtvNz
이상 에서 말 한 문 제 는 비교적 깨 져 있 는데 모두 문제 에 부 딪 히 고 문 제 를 해결 할 때 정리 한 것 이다.구체 적 으로 조작 할 때 다른 문제 가 발생 할 수 있 습 니 다.문제 나 건의 가 있 으 면 말씀 해 주세요^^.
마지막 으로 지금까지 기어 오 른 데 이 터 를 몇 장 넣 습 니 다.
레코드 테이블
그 중 에 저 장 된 것 은 79032 건 이 고,오 른 웹 페이지 는 48471 건 이다.
영화 표
현재 2964 편의 영화 와 드라마 작품 을 얻 었 다.
코 멘 트
29711 개의 기록 을 얻 었 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.