jsoup는 URL 주소와 HTML 텍스트 콘텐츠를 직접 구문 분석할 수 있는 Java HTML 파서입니다. DOM, CSS 및 jQuery와 유사한 조작 방법을 통해 데이터를 검색하고 조작할 수 있는 매우 간편한 API를 제공합니다.
현재는 지방, 시, 군, 읍, 거리까지 전국의 지역 데이터를 필요로 하는 일을 하고 있습니다. 다양한 Du Niang 및 다양한 Google 검색에서 완전한 데이터를 찾지 못했습니다. 결국 노력한 결과 비교적 완전한 데이터를 찾았습니다. 그러나 여기의 데이터는 마을 수준까지만 정확하고 마을 수준의 데이터는 없습니다(나중에 데이터를 분석하면서 이유를 알게 되었습니다.) 출처, ㅎㅎ) 게다가 블로거들이 제공하는 데이터 중 일부는 중복되는 부분이 있어서 강박장애가 있고 완벽함을 추구하는 저로서는 이 부분을 제가 직접 크롤링해야겠다는 생각이 들었습니다.
위 블로그 게시물의 내용은 상당히 풍부합니다. 블로거는 이를 구현하기 위해 PHP를 사용했습니다. 2015년 프로그래밍 언어 순위에서 1위를 차지했기 때문에 이제 Java 사용 방법을 살펴보겠습니다. 웹페이지에서 원하는 데이터를 크롤링합니다...
첫 번째 단계, 준비(데이터 소스 + 도구):
데이터 소스(지금까지 가장 포괄적이고 권위 있는 공식 데이터): http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/
데이터 크롤링 도구(크롤러 도구): http://jsoup.org/
두 번째 단계, 데이터 소스 분석:
우선 여기서는 jsoup 도구의 사용법을 설명하지 않겠습니다. 관심이 있으신 분은 직접 확인해 보시면 됩니다.
개발을 할 때 일부 소프트웨어 도구의 사용에 대해 더 많이 배워야 합니다. 일반적인 개발 과정에서 이러한 도구를 접해야만 필요할 경우를 대비하여 주변의 소프트웨어 도구에 더 많은 주의를 기울이는 것이 좋습니다. 그들을. 이거 만들기 전에는 jsoup 사용법을 몰랐는데, jsoup이 어떤 용도로 사용될 수 있는지는 알고 있어요. 필요할 때 직접 찾아보고 배워보겠습니다.
상기 자료 출처는 중화인민공화국 국가통계국이 2013년에 발표한 것으로 그 정확성과 권위는 자명합니다.
다음으로 홈 페이지부터 시작하여 데이터 소스의 구조를 분석해 보겠습니다.
홈페이지 소스코드를 분석하면 다음 세 가지 점을 얻을 수 있습니다.
1. 페이지의 전체 레이아웃은 테이블 태그에 의해 제어됩니다. 즉, jsoup을 통해 하이퍼링크를 선택하려면 위 그림에서 표시된 위치만이 아니라는 사실에 주의해야 합니다. 테이블을 사용하는 지방, 시, 지역의 경우 전체 페이지에 여러 개의 테이블이 있으므로 테이블을 직접 전달할 수 없습니다.
문서 연결 = 연결("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/");
요소 rowProvince = connect.select("table");
데이터를 구문 분석합니다.
2. 페이지에 하이퍼링크가 몇 군데나 있나요? 아마도 관계자는 당신과 같은 프로그래머가 그러한 데이터를 얻어야 하는 이유를 고려했을 것입니다. 페이지는 중복된 하이퍼링크인 등록 번호를 제외하고는 매우 깨끗합니다.
3. 지방 및 도시의 데이터 패턴. 유효한 정보를 포함하는 테이블의 각 행에는 Provincetr 클래스 속성이 있습니다. 이 속성이 중요한 이유는 각 데이터 행에 여러 개의 td 태그가 있으며 각 td 태그에는 하이퍼링크가 포함되어 있기 때문입니다. , 이 하이퍼링크는 정확히 우리가 원하는 하이퍼링크입니다. 하이퍼링크의 텍스트는 지방 이름(자치단체 등)입니다.
일반 데이터 페이지를 다시 살펴보겠습니다(일반 데이터 페이지에는 시, 군, 읍 수준의 3단계 데이터 표시 페이지가 포함되어 있음).
위의 세 페이지를 하나로 묶은 이유는 분석을 통해 이 세 가지 데이터 수준의 데이터 페이지가 완전히 일치한다는 것을 알 수 있기 때문입니다. 유일한 차이점은 html 소스 코드 데이터의 데이터 행 tr의 클래스 속성입니다. 테이블은 각각 citytr, countrytr 및 towntr에 해당합니다. 다른 모든 것은 일관됩니다. 이러한 방식으로 우리는 일반적인 방법을 사용하여 이 세 페이지의 데이터 크롤링을 해결할 수 있습니다.
다음으로 홈 페이지부터 시작하여 데이터 소스의 구조를 분석해 보겠습니다.
마지막으로 마을 수준 데이터 페이지를 살펴보세요.
마을 수준의 데이터 형식은 위에서 언급한 시군구의 데이터 형식과 일치하지 않습니다. 이 수준에서 표현되는 데이터는 가장 낮은 수준이므로 링크가 없으므로 시군 크롤링 방법은 다음과 같습니다. 위의 도시 데이터는 사용할 수 없습니다. 여기서 데이터를 표시하는 테이블 행의 클래스는 villagegetr입니다. 이 두 포인트 외에도 각 데이터 행에는 세 개의 데이터 열이 포함되어 있습니다. 도시 및 농촌 분류(시, 군, 읍의 데이터 형식이 다릅니다. 이 항목이 존재합니다.), 세 번째 열은 도시 이름입니다.
위의 사항을 파악한 후 코딩을 시작할 수 있습니다.
세 번째 단계, 코딩 구현:
import java.io.FileWriter; import java.util.HashMap; import org.jsoup. org.jsoup.nodes.Document; 가져오기 org.jsoup.nodes.Element; org.jsoup.select.Elements; /** * 전국의 성, 시, 군, 마을 및 마을의 데이터 크롤링 * @author liushaofeng * @date -- am:: * @version .. */ public class JsoupTest { private static Map<Integer, String> cssMap = new HashMap<Integer, String>(); private static BufferedWriter bufferedWriter = null; "provincetr");// 주 cssMap.put(, "citytr");// 시 cssMap.put(, "countytr");// 군 cssMap.put(, "towntr");// 시 cssMap.put (, "villagetr");//village} public static void main(String[] args) throws IOException { int level = ; initFile(); // 전국의 지역 정보 가져오기 Document connect = connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm//") Elements rowProvince = connect.select("tr. " + cssMap.get(level)); for (요소 ProvinceElement : rowProvince)//각 행의 지방과 도시를 탐색합니다.{ 요소 select = ProvinceElement.select("a"); for (요소 지방: select)//각 성(쓰촨 성) {parseNextLevel(province, level + ) } } closeStream() } private static void initFile(); try { bufferedWriter = new BufferedWriter(new FileWriter(new File("d://CityInfo.txt"), true) } catch (IOException e) { e.printStackTrace(); } } private static void closeStream() { if (bufferedWriter != null) { try { bufferedWriter.close() } catch (IOException e) { e.printStackTrace(); bufferedWriter = null; } } private static void parseNextLevel(Element parentElement, int level) throws IOException { try { Thread.sleep();//Sleep, 그렇지 않으면 다양한 오류 상태 코드가 발생할 수 있습니다.} catch (InterruptedException e) { e.printStackTrace() } Document doc = connect(parentElement.attr("abs:href")); doc != null) { Elements newsHeadlines = doc.select("tr." + cssMap.get(level));// // 테이블에서 데이터 행을 가져옵니다. (요소 요소 : newsHeadlines) { printInfo(element, level + ); 요소 select = element.select("a");// 재귀적으로 호출할 때 마을 수준 데이터인지 확인하기 위한 것입니다. data에 태그가 없습니다. if (select.size() != ) {parseNextLevel(select.last(), level + ) } } } } /** * 데이터 파일에 데이터 한 줄 쓰기* @param 요소 크롤링된 데이터 요소* @param 수준 도시 수준*/ private static void printInfo(요소 요소, int 수준) { try { bufferedWriter.write(element.select("td").last().text() + "{" + 레벨 + "}[" + element.select("td").first().text() + "]"); bufferedWriter.flush(); } catch (IOException e) { e.printStackTrace(); } } private static Document connect(String url) { if (url == null || url.isEmpty()) { throw new IllegalArgumentException(" 입력 url('" + url + "')이 유효하지 않습니다!"); } try { return Jsoup.connect(url).timeout( * ).get(); } catch (IOException e) { e.printStackTrace() return null; 데이터 크롤링 과정이 길어요 천천히 기다려주세요 ㅎㅎ 프로그램 실행하는데 시간이 오래 걸리므로 콘솔에 출력을 출력하지 마세요. 그렇지 않으면 프로그램 작동에 영향을 줄 수 있습니다....
획득된 최종 데이터의 형식은 다음과 같습니다("{}"는 도시 수준을 나타내고 "[]" 안의 내용은 도시 코드를 나타냄).
지방자치단체 {3}[110100000000]
둥청구{4}[110101000000]
동화먼 동사무소{5}[110101001000]
Duofu Lane 지역사회 주민위원회 {6}[110101001001]
Yinzha 지역사회 주민위원회{6}[110101001002]
동창자치위원회{6}[110101001005]
Zhide 지역사회 주민위원회{6}[110101001006]
Nanchizi 지역사회 주민위원회{6}[110101001007]
황투강 지역사회 주민위원회{6}[110101001008]
덩시커우 지역사회 주민위원회{6}[110101001009]
Zhengyi Road 커뮤니티 주민 위원회 {6}[110101001010]
간유 커뮤니티 주민 위원회 {6}[110101001011]
태지창 지역사회 주민위원회{6}[110101001013]
Shaojiu 커뮤니티 주민 위원회{6}[110101001014]
왕푸징 지역사회 주민위원회{6}[110101001015]
징산 동사무소{5}[110101002000]
용복사 지역사회 주민위원회 {6}[110101002001]
Jixiang 지역사회 주민위원회 {6}[110101002002]
황화문 지역사회 주민위원회{6}[110101002003]
중구 지역사회 주민위원회{6}[110101002004]
웨이자 지역사회 주민위원회{6}[110101002005]
왕즈마 주민자치위원회 {6}[110101002006]
경산동거리 지역사회 주민위원회 {6}[110101002008]
황청 겐베이 거리 커뮤니티 주민 위원회 {6}[110101002009]
자오다오커우 동사무소{5}[110101003000]
자오둥 지역사회 주민위원회{6}[110101003001]
푸샹 지역사회 주민위원회{6}[110101003002]
다싱 지역사회 주민위원회 {6}[110101003003]
Fuxue 커뮤니티 지역 위원회{6}[110101003005]
구러우위안 지역사회 주민위원회{6}[110101003007]
Juer 지역사회 주민위원회{6}[110101003008]
Nanluoguxiang 지역사회 주민위원회{6}[110101003009]
안딩먼 동사무소{5}[110101004000]
Jiaobei Toutiao 커뮤니티 이웃 위원회 {6}[110101004001]
Beiluoguxiang 지역사회 주민위원회 {6}[110101004002]
Guozijian 지역사회 주민위원회{6}[110101004003]
...
위의 데이터를 얻은 후에는 원하는 작업을 스스로 실현할 수 있으며, 위의 코드를 직접 실행할 수 있으며, 데이터 소스에서 크롤링한 후 원하는 형식으로 직접 변환할 수 있습니다.