Я также раньше использовал сканеров, например, использование Nutch для ползания указанного семени, поиск на основе ползлевых данных и примерно рассмотрение некоторого исходного кода. Конечно, Nutch считает, что сканеры очень всесторонне и тщательно. Всякий раз, когда я вижу информацию о веб -странице и информации о обработке, которые ползали по экрану, я всегда чувствую, что это очень темная технология. На этот раз я воспользовался возможностью разобраться в весеннем MVC и хотел сделать небольшой гусениц сам. Неважно, смогу ли я просто сделать это, и некоторые небольшие ошибки не имеют значения. Все, что мне нужно, - это сайт семян, который может ползти нужной информации. Если есть исключение, это может быть связано с тем, что некоторые API используются неправильно, или они могут столкнуться с ненормальным статусом HTTP -запроса, или есть проблема с чтением и написанием базы данных. В процессе отчетности исключений и решений исключений Jewelcrawler (прозвище сына) уже могут самостоятельно заползть данные, а также есть небольшой навык для эмоционального анализа, основанного на алгоритме Word2VEC.
Могут быть неизвестные исключения, ожидающие того, что будут решены позже, и необходимо оптимизировать некоторые производительность, такие как взаимодействие с базой данных, чтение и написание данных и т. Д. Однако у меня нет много энергии, чтобы поместить это в год, поэтому я дам простое резюме сегодня. Первые две статьи в основном сосредоточены на функциях и результатах. В этой статье рассказывается о том, как родился Jewelcrawler, и помещает код на GitHub (адрес исходного кода находится в конце статьи). Если вы заинтересованы, вы можете обратить внимание (только для общения и обучения, пожалуйста, Douban. Пожалуйста, Douban. Будьте более искренним и меньше вреда)
Введение окружающей среды
Инструменты разработки: IntelliJ Idea 14
База данных: MySQL 5.5 + инструмент управления базами данных NAVICAT (можно использовать для подключения к базам данных запросов)
Язык: Java
Управление пакетами JAR: Maven
Управление версией: git
Структура каталога
в
com.ansj.vec - это реализация версии Java of Word2VEC Algorithm
com.jackie.crawler.doubanmovie - это модуль реализации Crawler, который также включает
Некоторые пакеты пусты, потому что эти модули еще не используются, среди которых
Модуль ресурса хранит файлы конфигурации и файлы ресурсов, такие как
Тестовый модуль - это тестовый модуль, используемый для записи UT.
Конфигурация базы данных
1. Добавить пакеты зависимостей
Jewelcrawler использует Maven Management, поэтому вам нужно только добавить соответствующие зависимости в 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> <artifactid> commons-dbcp </artifactid> <artifactid> commons-dbcp </artifactid> <sersive> 1.4 </version> </vehydency> <DegyD> <GroupId> mySql </GroupD> <ratifactid> mysql-connector-java </artifactid> <sersion> 5.1.38 </version> </depervice> <deyedency> <groupid> mysql </groupid> <artifactid> mysql-connector-java </artifactid> <serse>
2. Объявите бон источника данных
Нам нужно объявить бобы источника данных в Beans.xml
<context:property-placeholder location="classpath*:*.properties"/><bean id="dataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value = "$ {jdbc.username}"/> <name = "password" value = "$ {jdbc.password}"/>Примечание. Вот внешний файл конфигурации JDBC.Properties, и параметры конкретного источника данных считываются из этого файла.
Если вы столкнетесь с проблемой: «SQL [вставьте в значения пользователя (ID) (?)]; Поля« Имя »не имеет значения по умолчанию»; Решение состоит в том, чтобы установить соответствующее поле таблицы в поле самонадера.
Проблемы встречаются на страницах анализа
Для данных веб -страницы, которые вы заполняли, вам необходимо проанализировать структуру DOM и получить нужные данные. В течение этого периода вы столкнетесь с следующей ошибкой
org.htmlparser.node не распознается
Решение: добавить зависимость от пакета JAR
<Depective> <groupid> org.htmlparser </GroupId> <artifactId> htmlParser </artifactid> <sersive> 1.6 </version> </depervice>
org.apache.http.httpentity не распознается
Решение: добавить зависимость от пакета JAR
<Depective> <groupid> org.apache.httpcomponents </GroupId> <artifactId> httpclient </artifactid> <sersive> 4.5.2 </version> </deperency>
Конечно, это проблема, возникающая в течение периода, и наконец используется анализ страницы, выполняемый JSoup.
Maven Warehouse Скорость загрузки медленная
Я раньше использовал репозиторий Maven Central Maven, и скорость загрузки пакетов JAR была очень медленной. Я не знаю, была ли это моей сетевой проблемой или другими причинами. Позже я нашел хранилище Maven Alibaba Cloud Online. После обновления было рекомендовано рвать кровь по сравнению с ранее.
<зеркала> <Irror> <id> alimaven </id> <mame> aliyun maven </name> <url> http://maven.aliyun.com/nexus/content/groups/public/ </url> <mirrorof> Central </mirrorof> </mirror> </mirrors> </mirrors> </mirrors> </mirrors> </mirrors> </url>
Найдите файл stens.xml Maven и добавьте это изображение.
Способ прочитать файлы в модуле ресурса
Например, прочитайте файл Seed.properties
@Test public void testfile () {file seedfile = new File (this.getClass (). GetResource ("/seed.properties"). GetPath ()); System.out.print ("===========" + seedfile.length () + "================="); }О регулярных выражениях
При использовании регулярных выражений REGREX, если определенный шаблон соответствует, вам необходимо вызвать метод поиска совпадений, прежде чем вы сможете использовать метод группы для поиска подстроения. Невозможно найти желаемый результат, вызывая метод группы напрямую.
Я посмотрел на исходный код класса маттера выше
пакет java.util.regex; import java.util.objects; публичный финальный сочетание класса реализует MatchResult { /*** Объект шаблона, который создал этот сочеток. */ Pattern parentpattern; /*** хранилище, используемое группами. Они могут содержать неверные значения, если * группа была пропущена во время соответствия. */ int [] группы; /*** Диапазон в последовательности, который должен быть сопоставлен. Якоря * совпадают на этих «жестких» границах. Изменение региона * изменяет эти значения. */ int от, до; /** * Lookbehind использует это значение, чтобы гарантировать, что совпадение подпрофессионала * заканчивается в точке, где встречался Lokebehind. */ int lookbehindto; /*** Оригинальная строка соответствует. */ Char -sevecence text; /*** Состояние сочетания, используемое последним узлом. NOANCHOR используется, когда A * Match не должен потреблять весь вход. Endanchor - это режим, используемый для сопоставления всего ввода. */ static final int endanchor = 1; статический финал int noanchor = 0; int acceptmode = noanchor; /*** Диапазон строки, которая в последний раз соответствует шаблону. Если последнее * матч не удалось, то сначала составляет -1; Последнее изначально удерживает 0, затем * удерживает индекс конца последнего матча (где начинается * следующий поиск *. */ int first = -1, last = 0; /*** Конечный индекс того, что соответствовало последней операции матча. */ int oldlast = -1; /*** Индекс последней позиции, применяемой в замене. */ int lastAppendPosition = 0; /** * Хранение, используемое узлами, чтобы сказать, какое повторение они находятся в * схеме, и где начинаются группы. Сами узлы без гражданства, поэтому они полагаются на это поле, чтобы удерживать состояние во время матча. */ int [] местные жители; /** * Boolean, указывая, может ли больше ввода изменить * результаты последнего совпадения. * * Если Hited верно, и было найдено совпадение, то больше ввода * может вызвать другое совпадение. * Если Hited верна, а совпадение не было найдено, то больше * ввода может привести к найму совпадения. * Если Hited является ложным, а совпадение не было найдено, то больше * ввода не приведет к найму совпадения. */ boolean hited; /** * Boolean, указывая, может ли больше ввода изменить * положительное соответствие на отрицательный. * * Если требуется, что это правда, и было найдено совпадение, тогда больше * ввода может привести к потере матча. * Если требование является ложным, а совпадение было найдено, то больше * ввода может изменить матч, но матч не будет потерян. * Если совпадение не было найдено, то требуется, что это не имеет значения. */ boolean требуется; /** * Если TransparentBounds верны, то границы области этого * совпадения прозрачны для Lookhead, Lookbehind, * и соответствующих границ, которые пытаются видеть за ними. */ boolean transparentbounds = false; /** * Если привязки к привязке верны, то границы этого * матчера соответствующего маттера соответствуют такими якорями, как ^ и $. */ boolean archoringbounds = true; /*** Нет конструктора по умолчанию. * / Matcher () {} / *** Все совпадения имеют состояние, используемое шаблоном во время матча. */Matcher (pattern parent, char -pextence text) {this.parentpattern = parent; this.text = text; // выделять состояние State Storage int parentGroupCount = math.max (parent.captingGroupCount, 10); Groups = new Int [ParentGroupCount * 2]; местные жители = новый int [parent.localcount]; // Поместите поля в начальные состояния Reset ();} ..../*** Возвращает последующую последующую входную последующую связь, соответствующую предыдущему совпадению. * * <p> для совпадения <i> m </i> с последовательности ввода <i> s </i>, * Экспрессии <i> m. </i> <tt> Group () </tt> и * <i> s. </i> <tt> substring (</tt> <i> m. </i> <tt> start (), </tt> <i> m. </i> <tt> end ()) </tt> * эквивалентны. </p> * * <p> Обратите внимание, что некоторые шаблоны, например, <tt> a * </tt>, сопоставьте пустую * строку. Этот метод вернет пустую строку, когда шаблон * успешно соответствует пустой строке при входе. </p> * * @return (возможно пустая) последовательность, сопоставленная предыдущим матчем, * в строковой форме * * @Throws allodalStateException * Если еще не было предпринято никакого соответствия, * или если предыдущая операция матча не удалась */public String Group () {return Group (0);}/** * Возвращает входную последующую, захваченную данной группой во время * предыдущей операции матча. * * <p> для совпадения <i> m </i>, входной последовательности <i> s </i> и группы Group * <i> g </i>, выражения <i> m. </i> <tt> группа (</tt> <i> g </i> <tt>) </tt> и * <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> * equivel. </p> * * <p> <a href = "pattern.html#cg"> захватывающие группы </a> индексируются слева * направо, начиная с одного. Group Zero обозначает весь шаблон, так что * выражение <tt> m.group (0) </tt> эквивалентно <tt> m.group () </tt>. * </p> * * <p> Если совпадение было успешным, но указанная группа не соответствовала * любой части входной последовательности, то <tt> null </tt> возвращается. Примечание * что некоторые группы, например, <tt> (a *) </tt>, соответствуют пустой строке. * Этот метод вернет пустую строку, когда такая группа успешно * соответствует пустой строке при входе. </p> * @param Group * Индекс группы захвата в шаблоне этого совместного сочетания * * @return (возможно, пустое) последующее, захваченное группой * во время предыдущего матча, или <tt> null </tt>, если группа * не соответствовала части ввода * * @Throws allosalStateExex * Если не было совпадает, * или, если предыдущая операция матча * atextSe * atexteS * atexteS * atextOr * atexteS * atextOr * atexTe -strections * atexTe -strections * atexouncous * atextos * atextos * atextos * или, если предыдущая операция матча. В шаблоне не существует группы захвата * с данным индексом */public String Group (int group) {if (First <0) бросить новое allosalstateexception («Нет совпадения»); if (group <0 || group> groupcount ()) бросить новый indexoutofboundsexception ("no Group" + Group); if ((группы [группа*2] == -1) || (группа [группа*2+1] == -1)) возвращает NULL; return getSubsence (группы [группа * 2], группы [группа * 2 + 1]). ToString ();}/** * Попытки найти следующую последовательность входной последовательности, которая соответствует * шаблону. * * <p> Этот метод начинается в начале региона этого маттера, или, если * предыдущий вызов метода был успешным, и с тех пор не был сброшен, а на первом символе не соответствовал предыдущему * матчу. * * <p> Если совпадение достигает успеха, то дополнительная информация может быть получена через методы * <tt> start </tt>, <tt> end </tt> и <tt> </tt>. </p> * * @return <tt> true </tt> if, и только если, последовательность последовательности ввода * соответствует шаблону этого соответствующего */public boolean find () {int nextsearchindex = last; if (nextSearchIndex == Сначала) nextSearchIndex ++; // Если следующий поиск начинается до региона, запустите его в регионе if (nextSearchIndex <from) nextSearchIndex = from; // Если следующий поиск начинается за пределы региона, то он не работает, если (nextSearchIndex> to) {for (int i = 0; i <Groups.length; i ++) группы [i] = -1; вернуть ложь; } return Search (nextSearchIndex);} /*** Инициирует поиск, чтобы найти шаблон в данных границах. * Группы заполнены значениями по умолчанию, и называется совпадение корня * состоящей машины. Государственная машина будет держать состояние * матча по мере его поступления в этот маттер. * * Matcher.from здесь не установлен, потому что это «жесткая» граница * начала поиска, на который будут установить якоря. FROM PARAM * - это «мягкая» граница начала поиска, что означает, что * regex пытается соответствовать этому индексу, но ^ не совпадает там. Последующие * вызовы в методах поиска начинаются с новой «мягкой» границы, которая является * конец предыдущего матча. */boolean search (int от) {this.hitend = false; this.requireend = false; от = от <0? 0: от; this.first = from; this.oldlast = oldlast <0? От: Oldlast; для (int i = 0; i <groups.length; i ++) группы [i] = -1; acceptmode = noanchor; логический результат = parentpattern.root.match (this, from, text); if (! result) this.first = -1; this.oldlast = this.last; вернуть результат;} ...}Причина в следующем: если вы сначала не называете метод Find и напрямую позвоните в группу, вы можете обнаружить, что группа группы вызывает группу (int Group). Есть, если первое <0 в теле метода метода. Очевидно, что это условие здесь верно, потому что первоначальное значение первого составляет -1, поэтому здесь будет брошено исключение. Однако, если вы позвоните в метод поиска, вы можете найти, что поиск (NextSearchIndex) в конечном итоге будет вызван. Обратите внимание, что NextSearchIndex здесь был назначен последним, а значение последнего - 0, а затем перейти к методу поиска
логический поиск (int of) {this.hitend = false; this.requireend = false; от = от <0? 0: от; this.first = from; this.oldlast = oldlast <0? От: Oldlast; для (int i = 0; i <groups.length; i ++) группы [i] = -1; acceptmode = noanchor; логический результат = parentpattern.root.match (this, from, text); if (! result) this.first = -1; this.oldlast = this.last; вернуть результат;} Этот NextSearchIndex передается от и из -за того, что он назначен сначала в теле метода. Следовательно, после вызова метода поиска, первое из этого больше не -1, и он не бросает исключение.
Исходный код был загружен в Baidu NetDisk: http://pan.baidu.com/s/1dfwtvnz
Проблемы, упомянутые выше, относительно разрушены, и они являются некоторыми резюме при столкновении с проблемами и их решением. Во время конкретных операций будут другие проблемы. Если у вас есть какие -либо вопросы или предложения, пожалуйста, не стесняйтесь упоминать ^^.
Наконец, поместите несколько фрагментов полных данных до сих пор
Таблица записей
Среди них хранятся 79 032, и 48 471 полза
Стол фильма
В настоящее время ползали 2964 кино и телевизионные работы
Комментарии таблицы
29 711 записей были заполнены
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.