jsoup es un analizador HTML de Java que puede analizar directamente una dirección URL y contenido de texto HTML. Proporciona una API de muy bajo esfuerzo para recuperar y manipular datos a través de métodos de manipulación similares a DOM, CSS y jQuery.
Actualmente estoy trabajando en algo que requiere datos regionales de todo el país, desde provincias y ciudades hasta condados, pueblos y calles. Varias búsquedas de Du Niang y Google no han podido encontrar datos completos. Al final, el arduo trabajo valió la pena y finalmente encontré datos relativamente completos. Sin embargo, los datos aquí solo son precisos a nivel de ciudad y no hay datos a nivel de aldea (más tarde supe por qué al analizar los datos). fuente, jaja). Además, algunos de los datos proporcionados por los blogueros son redundantes. Para mí, que tengo un trastorno obsesivo-compulsivo y busco la perfección, pensé que debía rastrear esta parte de los datos yo mismo.
El contenido de la publicación de blog anterior es bastante rico. El blogger usó PHP para implementarlo. Como el primer lugar en la clasificación de lenguajes de programación en 2015, no podemos mostrar debilidades. Ahora lo llevaré a ver cómo usar Java. rastrear los datos que queremos de la página web...
El primer paso, preparación (fuente de datos + herramientas):
Fuente de datos (los datos oficiales más completos y autorizados hasta el momento): http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/
Herramientas para rastrear datos (herramientas de rastreo): http://jsoup.org/
El segundo paso, análisis de la fuente de datos:
En primer lugar, no explicaré el uso de la herramienta jsoup aquí. Si está interesado, puede comprobarlo usted mismo.
Al realizar el desarrollo, debe aprender más sobre el uso de algunas herramientas de software. Solo cuando las encuentre en el proceso de desarrollo normal sabrá por dónde empezar. Animo a todos a que presten más atención a las herramientas de software que los rodean en caso de que las necesiten. a ellos. Antes de hacer esto, no sabía cómo usar jsoup, pero sé para qué se puede usar jsoup. Cuando necesite usarlo, buscaré la información y aprenderé por mi cuenta.
La fuente de datos mencionada anteriormente fue publicada por la Oficina Nacional de Estadísticas de la República Popular China en 2013, y su precisión y autoridad son evidentes.
A continuación, analicemos la estructura de la fuente de datos, comenzando por la página de inicio:
Al analizar el código fuente de la página de inicio, podemos obtener los siguientes tres puntos:
1. Todo el diseño de la página está controlado por la etiqueta de la tabla, es decir, si queremos seleccionar hipervínculos a través de jsoup, debemos prestar atención al hecho de que en la imagen de arriba no solo están los lugares marcados con. provincias, ciudades y regiones que usan tablas, hay varias tablas en toda la página, por lo que no es posible pasar la tabla directamente.
Conexión de documento = conexión ("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/");
Elementos rowProvince = connect.select("table");
para analizar los datos.
2. ¿En cuántos lugares de la página hay hipervínculos? Tal vez el funcionario haya considerado por qué los programadores como usted necesitan obtener dichos datos. La página está muy limpia. Excepto por el número de registro a continuación, que es un hipervínculo redundante, se pueden rastrear otros enlaces directamente.
3. Patrones de datos de provincias y ciudades. Cada fila de la tabla que contiene información válida tiene un atributo de clase provincia. Este atributo es muy importante. En cuanto a por qué es importante, siga leyendo. Hay varias etiquetas td en cada fila de datos y cada etiqueta td contiene un hipervínculo. , y este hipervínculo es exactamente el hipervínculo que queremos. El texto del hipervínculo es el nombre de la provincia (municipio, etc.).
Echemos un vistazo a la página de datos generales nuevamente (las páginas de datos generales incluyen páginas de visualización de datos de tres niveles a nivel de ciudad, condado y pueblo):
La razón por la que juntamos las tres páginas anteriores es porque a través del análisis podemos encontrar que las páginas de datos de estos tres niveles de datos son completamente consistentes. La única diferencia es que los atributos de clase de la fila de datos tr en los datos del código fuente html. tabla son inconsistentes, correspondientes a: citytr, countrytr y towntr. Todo lo demás es consistente. De esta forma, podemos utilizar un método común para solucionar el rastreo de datos de estas tres páginas.
A continuación, analicemos la estructura de la fuente de datos, comenzando por la página de inicio:
Finalmente, eche un vistazo a la página de datos a nivel de aldea:
El formato de datos a nivel de aldea es inconsistente con el formato de datos de las ciudades, condados y pueblos mencionados anteriormente. Los datos representados en este nivel son el nivel más bajo, por lo que no hay un vínculo, por lo que se utiliza el método de rastreo de ciudad y condado. y los datos de la ciudad anteriores no se pueden utilizar. La clase de la fila de la tabla que muestra los datos aquí es villagegetr. Además de estos dos puntos, cada fila de datos contiene tres columnas de datos. clasificación urbana y rural (el formato de datos de ciudades, condados y pueblos es diferente. Este elemento existe), y la tercera columna es el nombre de la ciudad.
Después de comprender los puntos anteriores, podemos comenzar a codificar.
El tercer paso, implementación de codificación:
importar java.io.BufferedWriter; importar java.io.File; importar java.io.FileWriter; importar java.io.IOException; importar java.util.Map; org.jsoup.nodes.Documento; importar org.jsoup.nodes.Element; org.jsoup.select.Elements; /** * Rastreo de datos de provincias, ciudades, condados, pueblos y aldeas de todo el país * @author liushaofeng * @date -- am:: * @version .. */ public class JsoupTest { Mapa estático privado <Integer, String> cssMap = new HashMap<Integer, String>(); BufferedWriter estático privado bufferedWriter = null; "provincetr");// Provincia cssMap.put(, "citytr");// Ciudad cssMap.put(, "countytr");// Condado cssMap.put(, "towntr");// Ciudad cssMap.put (, "villagetr");//village} public static void main(String[] args) lanza IOException { int nivel =; initFile(); // Obtener información provincial de todo el país Documento connect = connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm//"); Elementos rowProvince = connect.select("tr. " + cssMap.get(level)); for (Element provinciaElement: filaProvincia)//Recorre las provincias y ciudades en cada fila{ Elementos select = provinciaElement.select("a"); for (Elemento provincia: seleccionar)//Cada provincia (Provincia de Sichuan) { parseNextLevel(provincia, nivel + } } closeStream() } private static void initFile(); intente { 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 (Elemento parentElement, nivel int) lanza IOException { intentar { Thread.sleep();//Duerme, de lo contrario pueden aparecer varios códigos de estado de error} catch (InterruptedException e) { e.printStackTrace() } Document doc = connect(parentElement.attr("abs:href")); doc != null) { Elementos newsHeadlines = doc.select("tr." + cssMap.get(level));// // Obtiene una fila de datos de la tabla para (Elemento elemento: newsHeadlines) { printInfo(elemento, nivel +); Elementos select = element.select("a");// Cuando se llama de forma recursiva, esto es para determinar si se trata de datos a nivel de aldea. los datos no tienen una etiqueta if (select.size() != ) { parseNextLevel(select.last(), nivel + } } } } /** * Escribe una línea de datos en el archivo de datos* @param elemento de datos rastreados elemento* @param nivel nivel de ciudad*/ privado estático vacío printInfo(Elemento elemento, nivel int) { try { bufferedWriter.write(element.select("td").last().text() + "{" + nivel + "}[" + elemento.select("td").first().text() + "]"); bufferedWriter.flush(); } catch (IOException e) { e.printStackTrace(); } } Conexión de documento estático privado (String url) { if (url == null || url.isEmpty()) { throw new IllegalArgumentException(" ¡La URL de entrada('" + url + "') no es válida!"); } try { return Jsoup.connect(url).timeout( * ).get(); } captura (IOException e) { e.printStackTrace(); retorno nulo; El proceso de rastreo de datos es un proceso largo. Simplemente espere lentamente Jaja, debido a que el programa tarda mucho en ejecutarse, no imprima el resultado en la consola, de lo contrario puede afectar el funcionamiento del programa.
El formato de los datos finales obtenidos es el siguiente ("{}" representa el nivel de ciudad y el contenido en "[]" representa el código de ciudad):
Distrito municipal {3}[110100000000]
Distrito de Dongcheng{4}[110101000000]
Oficina del subdistrito de Donghuamen{5}[110101001000]
Comité Vecinal de la Comunidad de Duofu Lane {6}[110101001001]
Comité Vecinal de la Comunidad Yinzha{6}[110101001002]
Comité Vecinal de la Comunidad de Dongchang{6}[110101001005]
Comité Vecinal de la Comunidad Zhide{6}[110101001006]
Comité Vecinal de la Comunidad Nanchizi{6}[110101001007]
Comité Vecinal de la Comunidad de Huangtugang{6}[110101001008]
Comité Vecinal de la Comunidad Dengshikou{6}[110101001009]
Comité Vecinal Comunitario de Zhengyi Road {6}[110101001010]
Comité Vecinal de la Comunidad de Ganyu {6}[110101001011]
Comité Vecinal de la Comunidad de Taijichang{6}[110101001013]
Comité Vecinal de la Comunidad Shaojiu{6}[110101001014]
Comité Vecinal de la Comunidad de Wangfujing{6}[110101001015]
Oficina del subdistrito de Jingshan{5}[110101002000]
Comité Vecinal de la Comunidad del Templo Longfu {6}[110101002001]
Comité Vecinal de la Comunidad de Jixiang {6}[110101002002]
Comité Vecinal de la Comunidad de Huanghuamen{6}[110101002003]
Comité Vecinal de la Comunidad de Zhonggu{6}[110101002004]
Comité Vecinal de la Comunidad de Weijia{6}[110101002005]
Comité Vecinal de la Comunidad de Wangzhima {6}[110101002006]
Comité Vecinal Comunitario de Jingshan East Street {6}[110101002008]
Comité Vecinal Comunitario de la Calle Huangcheng Genbei {6}[110101002009]
Oficina del subdistrito de Jiaodaokou{5}[110101003000]
Comité Vecinal de la Comunidad Jiaodong{6}[110101003001]
Comité Vecinal de la Comunidad de Fuxiang{6}[110101003002]
Comité Vecinal de la Comunidad de Daxing {6}[110101003003]
Comité Vecinal de la Comunidad Fuxue{6}[110101003005]
Comité Vecinal de la Comunidad de Gulouyuan{6}[110101003007]
Comité Vecinal de la Comunidad Juer{6}[110101003008]
Comité Vecinal de la Comunidad de Nanluoguxiang{6}[110101003009]
Oficina del subdistrito de Andingmen{5}[110101004000]
Comité Vecinal de la Comunidad Jiaobei Toutiao {6}[110101004001]
Comité Vecinal de la Comunidad de Beiluoguxiang {6}[110101004002]
Comité Vecinal de la Comunidad de Guozijian{6}[110101004003]
...
Después de obtener los datos anteriores, puede realizar lo que quiera hacer usted mismo. El código anterior se puede ejecutar directamente desde la fuente de datos y se puede convertir directamente al formato que desee.