jsoup は、URL アドレスと HTML テキスト コンテンツを直接解析できる Java HTML パーサーです。 DOM、CSS、および jQuery のような操作メソッドを通じてデータを取得および操作するための、非常に低労力の API を提供します。
私は現在、州や都市から郡、町、通りに至るまで、全国の地域データを必要とすることに取り組んでいます。 Du Niang や Google でさまざまな検索を行っても、完全なデータは見つかりませんでした。結局、苦労の甲斐あって、比較的完全なデータを見つけることができました。ただし、ここでのデータは町レベルまでしか正確ではなく、村レベルのデータはありませんでした(後でデータを分析してその理由が分かりました)。ソース、笑)また、強迫性障害で完璧を求める私にとっては、ブロガーが提供するデータの一部が冗長であるため、この部分は自分で這い出さなければならないと考えました。
上記のブログ投稿の内容は非常に充実しています。2015 年のプログラミング言語ランキングで 1 位になったので、ここでは Java の使用方法を紹介します。 Web ページから必要なデータをクロールします...
最初のステップ、準備 (データ ソース + ツール):
データソース (これまでで最も包括的で信頼できる公式データ): http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/
データをクロールするためのツール (クローラー ツール): http://jsoup.org/
2 番目のステップであるデータ ソース分析:
まず、ここでは jsoup ツールの使用法については説明しませんので、興味がある方はご自身で確認してください。
開発を行うときは、通常の開発プロセスでソフトウェア ツールに遭遇したときにのみ、その使用方法について詳しく学ぶ必要があります。必要に応じて、周囲のソフトウェア ツールにもっと注意を払うことをお勧めします。彼ら。これを作る前はjsoupの使い方が分かりませんでしたが、必要になったときに自分で調べて勉強してみます。
上記のデータソースは中華人民共和国国家統計局が2013年に発表したものであり、その正確性と信頼性は自明です。
次に、ホームページから始めて、データ ソースの構造を分析しましょう。
ホームページのソースコードを分析すると、次の 3 つのポイントがわかります。
1. ページ全体のレイアウトは table タグによって制御されます。つまり、jsoup を通じてハイパーリンクを選択したい場合は、上の図で でマークされた場所だけが選択されるわけではないという事実に注意する必要があります。テーブルを使用する州、市、地域では、ページ全体に複数のテーブルがあるため、テーブルを直接渡すことはできません。
ドキュメント connect = connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/");
要素 rowProvince = connect.select("table");
データを解析します。
2. ページ上にハイパーリンクは何箇所ありますか?おそらく担当者は、あなたのようなプログラマがなぜそのようなデータを取得する必要があるのかを考えているのでしょう。ページは、冗長なハイパーリンクである登録番号を除いて、他のリンクを直接クロールできます。
3. 州と都市のデータパターン。有効な情報を含むテーブルの各行にはクラス属性「provintr」があります。この属性が非常に重要である理由については、データの各行に複数の td タグがあり、各 td タグにハイパーリンクが含まれています。 . 、このハイパーリンクはまさに私たちが望むハイパーリンクです。ハイパーリンクのテキストは州 (市区町村など) の名前です。
もう一度、一般データ ページを見てみましょう (一般データ ページには、市、郡、町レベルの 3 レベルのデータ表示ページが含まれます)。
上記 3 つのページをまとめた理由は、分析の結果、これら 3 つのレベルのデータ ページが完全に一致していることが判明したためです。唯一の違いは、HTML ソース コード データ内のデータ行 tr のクラス属性です。テーブルはそれぞれ citytr、countrytr、towntr に対応します。それ以外はすべて一貫しています。このようにして、共通の方法を使用して、これら 3 つのページのデータ クローリングを解決できます。
次に、ホームページから始めて、データ ソースの構造を分析しましょう。
最後に、村レベルのデータ ページを見てください。
村レベルのデータ形式は、上記の市、郡、町のデータ形式と一致しないため、このレベルで表されるデータはリンクがないため、市、郡のクローリング方法が使用されます。上記の町データは使用できません。ここでデータを表示するテーブル行のクラスは、これら 2 つのポイントに加えて、データの各行に 3 つの列が含まれています。都市と農村の分類 (市、郡、町のデータ形式は異なります。この項目は存在します)、3 番目の列は都市名です。
上記のポイントを理解したら、コーディングを開始できます。
3 番目のステップ、コーディング実装:
インポート java.io.BufferedWriter; インポート java.io.FileWriter; インポート java.util.Map; org.jsoup.nodes.Document インポート; 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 = static { cssMap.put(, "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//"); 要素 rowProvince = connect.select("tr. " + cssMap.get(level)); for (Element sinnerElement : rowProvince)//各行の州と都市をトラバースします{要素 select = statesElement.select("a"); for (要素省 : select)//各省 (四川省) { parseNextLevel(province, level + ) } } private static void initFile(); try {bufferedWriter = new BufferedWriter(new FileWriter(new File("d://CityInfo.txt"), true)); (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(ElementparentElement, int level) throws IOException {try { Thread.sleep();//スリープ、それ以外の場合はさまざまなエラーステータスコードが発生する可能性があります} catch (InterruptedException e) { e.printStackTrace(); } Document doc = connect(parentElement.attr("abs:href")); doc != null) { Elements newsHeadlines = doc.select("tr." + cssMap.get(level));// // テーブルからデータ行を取得します。 (Element element : newsHeadlines) { printInfo(element, level + ); Elements select = element.select("a");// 再帰的に呼び出す場合、村レベルのデータかどうかを判定します。データにタグがありません if (select.size() != ) { parseNextLevel(select.last(), level + ) } } } } /** * データ行をデータ ファイルに書き込みます* @param要素 クロールされたデータ要素* @param レベル都市レベル*/ private static void printInfo(Element element, int level) { 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() } }データ クローリング プロセスは長いプロセスです。笑、プログラムの実行には時間がかかるので、コンソールに出力を表示しないでください。そうしないと、プログラムの動作に影響が出る可能性があります。
最終的に取得されるデータの形式は次のとおりです (「{}」は都市レベルを表し、「[]」の内容は都市コードを表します)。
市区町村 {3}[110100000000]
東城区{4}[110101000000]
東華門区役所{5}[110101001000]
Duofu Lane コミュニティ近隣委員会 {6}[110101001001]
銀閘地域自治委員会{6}[110101001002]
東昌地域自治委員会{6}[110101001005]
志秀コミュニティ近隣委員会{6}[110101001006]
ナンチージ コミュニティ近隣委員会{6}[110101001007]
黄土港コミュニティ近隣委員会{6}[110101001008]
登市口地域自治委員会{6}[110101001009]
正義路コミュニティ近隣委員会 {6}[110101001010]
甘生コミュニティ自治委員会 {6}[110101001011]
太地昌地域自治委員会{6}[110101001013]
邵州コミュニティ近隣委員会{6}[110101001014]
王府井コミュニティ近隣委員会{6}[110101001015]
景山区役所{5}[110101002000]
龍福寺コミュニティ自治委員会 {6}[110101002001]
吉祥コミュニティ近隣委員会 {6}[110101002002]
黄花門地域自治委員会{6}[110101002003]
中谷コミュニティ近隣委員会{6}[110101002004]
Weijia コミュニティ近隣委員会{6}[110101002005]
王芝地域自治委員会 {6}[110101002006]
景山東街コミュニティ自治委員会 {6}[110101002008]
黄城源北街コミュニティ自治委員会 {6}[110101002009]
膠島口支区事務所{5}[110101003000]
交通自治区自治委員会{6}[110101003001]
復興コミュニティ近隣委員会{6}[110101003002]
大興コミュニティ近隣委員会 {6}[110101003003]
フクスエ コミュニティ近隣委員会{6}[110101003005]
鼓楼源コミュニティ近隣委員会{6}[110101003007]
ジュエル コミュニティ近隣委員会{6}[110101003008]
Nanluoguxiang コミュニティ近隣委員会{6}[110101003009]
安定門区役所{5}[110101004000]
焦北頭条コミュニティ近隣委員会 {6}[110101004001]
北洛鼓郷コミュニティ近隣委員会 {6}[110101004002]
Guozjian コミュニティ近隣委員会{6}[110101004003]
...
上記のデータを取得したら、上記のコードをデータ ソースから直接実行して、必要な形式に変換できます。