jsoup — это парсер Java HTML, который может напрямую анализировать URL-адрес и текстовое содержимое HTML. Он предоставляет очень простой API для извлечения данных и управления ими с помощью DOM, CSS и методов манипуляции, подобных jQuery.
В настоящее время я работаю над чем-то, что требует региональных данных по всей стране, от провинций и городов до округов, поселков и улиц. Различные поисковые запросы Ду Нианг и Google не смогли найти полных данных. В конце концов, тяжелая работа окупилась, и я наконец нашел относительно полные данные. Однако данные здесь точны только на уровне города, а на уровне деревни нет данных (позже я узнал, почему, проанализировав данные). источник, хаха). Кроме того, некоторые данные, предоставленные блоггерами, являются избыточными. Для меня, страдающего обсессивно-компульсивным расстройством и стремящегося к совершенству, я подумал, что должен найти эту часть данных сам.
Содержимое приведенного выше сообщения в блоге довольно богато. Для его реализации блоггер использовал PHP. Поскольку он занял первое место в рейтинге языков программирования в 2015 году, мы не можем показать слабость. Теперь я покажу вам, как использовать Java. просканировать нужные нам данные с веб-страницы...
Первый шаг, подготовка (источник данных + инструменты):
Источник данных (самые полные и авторитетные официальные данные на данный момент): http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/
Инструменты для сканирования данных (инструменты сканирования): http://jsoup.org/
Второй шаг, анализ источника данных:
Прежде всего, я не буду здесь объяснять использование инструмента jsoup. Если вам интересно, вы можете проверить его самостоятельно.
При разработке вам следует больше узнать об использовании некоторых программных инструментов. Только когда вы столкнетесь с ними в обычном процессе разработки, вы поймете, с чего начать. Я призываю всех уделять больше внимания программным инструментам вокруг вас на случай, если они вам понадобятся. их. До создания этой штуки я не знал, как использовать jsoup, но знаю, для чего его можно использовать. Когда мне понадобится его использовать, я поищу информацию и научусь сам.
Вышеупомянутый источник данных был опубликован Национальным бюро статистики Китайской Народной Республики в 2013 году, и его точность и авторитетность очевидны.
Далее давайте проанализируем структуру источника данных, начиная с домашней страницы:
Анализируя исходный код домашней страницы, мы можем получить следующие три момента:
1. Весь макет страницы контролируется тегом table. То есть, если мы хотим выбирать гиперссылки через jsoup, то надо обратить внимание на то, что на картинке выше отмечены не только места. в провинциях, городах и регионах, которые используют таблицы, на всей странице имеется несколько таблиц, поэтому невозможно передать таблицу напрямую.
Document Connect = Connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/");
Элементы rowProvince = Connect.select("таблица");
для анализа данных.
2. Сколько мест на странице имеют гиперссылки? Возможно, чиновник подумал, почему таким программистам, как вы, нужно получать такие данные. Страница очень чистая, за исключением регистрационного номера, под которым находится избыточная гиперссылка, другие ссылки можно сканировать напрямую.
3. Шаблоны данных по провинциям и городам. Каждая строка таблицы, содержащая достоверную информацию, имеет атрибут классапровинциятр. Этот атрибут очень важен. Что касается того, почему он важен, читайте дальше, в каждой строке данных есть несколько тегов td, и каждый тег td содержит гиперссылку; . , и эта гиперссылка — именно та гиперссылка, которая нам нужна. Текст гиперссылки — это название провинции (муниципалитета и т. д.).
Давайте еще раз посмотрим на страницу общих данных (страницы общих данных включают трехуровневые страницы отображения данных на уровне города, округа и города):
Причина, по которой мы объединили три вышеупомянутые страницы, заключается в том, что посредством анализа мы можем обнаружить, что страницы данных этих трех уровней данных полностью согласованы. Единственная разница заключается в том, что атрибуты класса строки данных tr в данных исходного кода HTML. таблицы противоречивы соответственно: citytr, Countrytr и Towntr. Все остальное соответствует. Таким образом, мы можем использовать общий метод для решения проблемы сканирования данных этих трех страниц.
Далее давайте проанализируем структуру источника данных, начиная с домашней страницы:
Наконец, взгляните на страницу данных на уровне деревни:
Формат данных на уровне деревни не соответствует формату данных городов, округов и поселков, упомянутых выше. Данные, представленные на этом уровне, являются самым низким уровнем, поэтому связь отсутствует, поэтому используется метод сканирования города, округа. и данные города, указанные выше, не могут быть использованы. городская и сельская классификация (формат данных городов, округов и поселков различен. Этот элемент существует), а третий столбец — это название города.
Поняв вышеизложенное, мы можем приступить к кодированию.
Третий шаг, реализация кодирования:
импорт java.io.BufferedWriter; импорт java.io.FileWriter; импорт java.io.IOException; импорт java.util.Map; импорт org.jsoup.Jsoup; org.jsoup.nodes.Document импорт org.jsoup.nodes.Element; org.jsoup.select.Elements; /** * Сканирование данных по провинциям, городам, округам, поселкам и деревням по всей стране* @author liushaofeng * @date -- am:: * @version .. */ public class JsoupTest { частная статическая Map<Integer, String> cssMap = new HashMap<Integer, String>(); частная статическая BufferedWriter bufferedWriter = null static { cssMap.put (; "provincetr");// Провинция cssMap.put(, "citytr");// Город cssMap.put(, "countytr");// Округ cssMap.put(, "towntr");// Город cssMap.put (, "villagetr");//village} public static void main(String[] args) бросает IOException { int level = ; initFile() // Получение информации о провинциях по всей стране. Document Connect = Connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm//"); " + cssMap.get(level)); for (Element rightsElement : rowProvince)//Обход провинций и городов в каждой строке{ Elements select =провинцияElement.select("a"); for (Элемент провинции: select)//Каждая провинция (провинция Сычуань) { parseNextLevel(province, level + } } closeStream(); попробуйте {ufferedWriter = новый BufferedWriter (новый FileWriter (новый файл («d://CityInfo.txt»), true)); (IOException e) { e.printStackTrace(); } } Private static void closeStream() { if (bufferedWriter != null) { try {ufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); ufferedWriter = null;}} Private static void parseNextLevel (ElementparentElement, int level) выдает 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));// // Получаем строку данных из таблицы для (Element element : newsHeadlines) { printInfo(element, level + ); Elements select = element.select("a");// При рекурсивном вызове необходимо определить, являются ли это данными уровня деревни. data не имеет тега if (select.size() != ) { parseNextLevel(select.last(), level + } } } } /** * Записываем строку данных в файл данных* @param); элемент данных для обхода элемента* @param level уровень города*/ Private static void printInfo(Element element, int level) { try { bufferedWriter.write(element.select("td").last().text() + "{" + level + "}[" + element.select("td").first().text() + "]"); ufferedWriter.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]
Районный комитет Дуофу Лейн {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]
Районный комитет сообщества Вейцзя{6}[110101002005]
Районный комитет сообщества Ванжима {6}[110101002006]
Районный комитет сообщества Ист-стрит Цзиншань {6}[110101002008]
Районный комитет улицы Хуанчэн Гэнбэй {6}[110101002009]
Районный офис Цзяодаокоу{5}[110101003000]
Районный комитет общины Цзяодун{6}[110101003001]
Районный комитет общины Фусян{6}[110101003002]
Районный комитет сообщества Дасин {6}[110101003003]
Районный комитет сообщества Фусюэ{6}[110101003005]
Районный комитет общины Гулоуюань{6}[110101003007]
Районный комитет сообщества Джуер {6}[110101003008]
Районный комитет сообщества Наньлуогусян{6}[110101003009]
Районный офис Аньдинмэнь{5}[110101004000]
Районный комитет сообщества Цзяобэй Тутяо {6}[110101004001]
Районный комитет Бэйлогусян{6}[110101004002]
Районный комитет общины Гоцзицзянь{6}[110101004003]
...
После получения вышеуказанных данных вы можете реализовать все, что хотите, самостоятельно. Приведенный выше код можно запустить напрямую. После сканирования из источника данных его можно напрямую преобразовать в нужный вам формат.