Как программно выполнить поиск без использования API? - PullRequest
7 голосов
/ 17 июля 2009

Я хотел бы создать программу, которая будет вводить строку в текстовое поле на сайте, таком как Google (без использования их общедоступного API), а затем отправлять форму и получать результаты. Это возможно? Я бы предположил, что для получения результатов потребуется использовать очистку HTML, но как мне ввести данные в текстовое поле и отправить форму? Буду ли я вынужден использовать публичный API? Что-то подобное просто невозможно? Должен ли я выяснить строки запроса / параметры?

Спасибо

Ответы [ 5 ]

4 голосов
/ 17 июля 2009

Theory

Что я хотел бы сделать, так это создать небольшую программу, которая может автоматически отправлять любые данные формы в любое место и возвращаться с результатами. Это легко сделать в Java с HTTPUnit . Задача выглядит так:

  • Подключение к веб-серверу.
  • Разобрать страницу.
  • Получить первую форму на странице.
  • Заполните данные формы.
  • Отправьте форму.
  • Чтение (и анализ) результатов.

Решение, которое вы выберете, будет зависеть от множества факторов, в том числе:

  • Нужно ли эмулировать JavaScript
  • Что нужно сделать с данными потом
  • На каких языках вы владеете
  • Скорость приложения (это для одного запроса или 100 000?)
  • Как скоро приложение должно работать
  • Это один раз или его нужно будет поддерживать?

Например, вы можете попробовать следующие приложения, чтобы предоставить данные для вас:

Затем grep (awk, или sed) результирующие веб-страницы.

Еще одна хитрость при очистке экрана - это загрузить образец HTML-файла и вручную проанализировать его в vi (или VIM). Сохраните нажатия клавиш в файл, а затем всякий раз, когда вы запускаете запрос, применяйте эти нажатия клавиш к результирующим веб-страницам для извлечения данных. Это решение не является ни обслуживаемым, ни на 100% надежным (но скриншот экрана с сайта редко бывает). Это работает и быстро.

* 1 060 * Пример * ** 1 063 тысяча шестьдесят-дв * Ниже представлен полуграничный класс Java для отправки форм веб-сайта (в частности, для входа на веб-сайт) в надежде, что он может быть полезен. Не используйте это для зла. import java.io.FileInputStream; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.SubmitButton; import com.meterware.httpunit.WebClient; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebForm; import com.meterware.httpunit.WebLink; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; public class FormElements extends Properties { private static final String FORM_URL = "form.url"; private static final String FORM_ACTION = "form.action"; /** These are properly provided property parameters. */ private static final String FORM_PARAM = "form.param."; /** These are property parameters that are required; must have values. */ private static final String FORM_REQUIRED = "form.required."; private Hashtable fields = new Hashtable( 10 ); private WebConversation webConversation; public FormElements() { } /** * Retrieves the HTML page, populates the form data, then sends the * information to the server. */ public void run() throws Exception { WebResponse response = receive(); WebForm form = getWebForm( response ); populate( form ); form.submit(); } protected WebResponse receive() throws Exception { WebConversation webConversation = getWebConversation(); GetMethodWebRequest request = getGetMethodWebRequest(); // Fake the User-Agent so the site thinks that encryption is supported. // request.setHeaderField( "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv\\:1.7.3) Gecko/20040913" ); return webConversation.getResponse( request ); } protected void populate( WebForm form ) throws Exception { // First set all the .param variables. // setParamVariables( form ); // Next, set the required variables. // setRequiredVariables( form ); } protected void setParamVariables( WebForm form ) throws Exception { for( Enumeration e = propertyNames(); e.hasMoreElements(); ) { String property = (String)(e.nextElement()); if( property.startsWith( FORM_PARAM ) ) { String fieldName = getProperty( property ); String propertyName = property.substring( FORM_PARAM.length() ); String fieldValue = getField( propertyName ); // Skip blank fields (most likely, this is a blank last name, which // means the form wants a full name). // if( "".equals( fieldName ) ) continue; // If this is the first name, and the last name parameter is blank, // then append the last name field to the first name field. // if( "first_name".equals( propertyName ) && "".equals( getProperty( FORM_PARAM + "last_name" ) ) ) fieldValue += " " + getField( "last_name" ); showSet( fieldName, fieldValue ); form.setParameter( fieldName, fieldValue ); } } } protected void setRequiredVariables( WebForm form ) throws Exception { for( Enumeration e = propertyNames(); e.hasMoreElements(); ) { String property = (String)(e.nextElement()); if( property.startsWith( FORM_REQUIRED ) ) { String fieldValue = getProperty( property ); String fieldName = property.substring( FORM_REQUIRED.length() ); // If the field starts with a ~, then copy the field. // if( fieldValue.startsWith( "~" ) ) { String copyProp = fieldValue.substring( 1, fieldValue.length() ); copyProp = getProperty( copyProp ); // Since the parameters have been copied into the form, we can // eke out the duplicate values. // fieldValue = form.getParameterValue( copyProp ); } showSet( fieldName, fieldValue ); form.setParameter( fieldName, fieldValue ); } } } private void showSet( String fieldName, String fieldValue ) { System.out.print( "<p class='setting'>" ); System.out.print( fieldName ); System.out.print( " = " ); System.out.print( fieldValue ); System.out.println( "</p>" ); } private WebForm getWebForm( WebResponse response ) throws Exception { WebForm[] forms = response.getForms(); String action = getProperty( FORM_ACTION ); // Not supposed to break out of a for-loop, but it makes the code easy ... // for( int i = forms.length - 1; i >= 0; i-- ) if( forms[ i ].getAction().equalsIgnoreCase( action ) ) return forms[ i ]; // Sadly, no form was found. // throw new Exception(); } private GetMethodWebRequest getGetMethodWebRequest() { return new GetMethodWebRequest( getProperty( FORM_URL ) ); } private WebConversation getWebConversation() { if( this.webConversation == null ) this.webConversation = new WebConversation(); return this.webConversation; } public void setField( String field, String value ) { Hashtable fields = getFields(); fields.put( field, value ); } private String getField( String field ) { Hashtable<String, String> fields = getFields(); String result = fields.get( field ); return result == null ? "" : result; } private Hashtable getFields() { return this.fields; } public static void main( String args[] ) throws Exception { FormElements formElements = new FormElements(); formElements.setField( "first_name", args[1] ); formElements.setField( "last_name", args[2] ); formElements.setField( "email", args[3] ); formElements.setField( "comments", args[4] ); FileInputStream fis = new FileInputStream( args[0] ); formElements.load( fis ); fis.close(); formElements.run(); } } Примеры файлов свойств будут выглядеть так: $ cat com.mellon.properties form.url=https://www.mellon.com/contact/index.cfm form.action=index.cfm form.param.first_name=name form.param.last_name= form.param.email=emailhome form.param.comments=comments # Submit Button #form.submit=submit # Required Fields # form.required.to=zzwebmaster form.required.phone=555-555-1212 form.required.besttime=5 to 7pm Запустите его аналогично следующему (замените путь на HTTPUnit и класс FormElements на $ CLASSPATH): java -cp $CLASSPATH FormElements com.mellon.properties "John" "Doe" "John.Doe@gmail.com" "To whom it may concern ..." Законность В другом ответе упоминается, что он может нарушать условия использования. Сначала проверьте это, прежде чем тратить время на поиск технического решения. Очень хороший совет.
3 голосов
/ 17 июля 2009

В большинстве случаев вы можете просто отправить простой запрос HTTP POST.

Я бы посоветовал вам поиграть с Fiddler , чтобы понять, как работает сеть.

Почти все языки программирования и платформы имеют методы для отправки необработанных запросов.

И вы всегда можете программировать против элемента управления ActiveX Internet Explorer. Я верю, что многие языки программирования поддерживают это.

2 голосов
/ 17 июля 2009

Я считаю, что это может привести к юридическому нарушению условий использования (проконсультируйтесь с юристом об этом: программисты не умеют давать юридические советы!), Но технически вы можете искать foobar, просто перейдя по URL http://www.google.com/search?q=foobar и, как вы говорите, извлекаете полученный HTML-код. Возможно, вам также понадобится подделать HTTP-заголовок User-Agent и, возможно, некоторые другие.

Возможно, существуют поисковые системы, условия использования которых не запрещают этого; вам и вашему адвокату можно посоветовать осмотреться, чтобы понять, так ли это на самом деле.

1 голос
/ 17 июля 2009

Ну, вот HTML-код со страницы Google:

<form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top>
<td width=25%>&nbsp;</td><td align=center nowrap>
<input name=hl type=hidden value=en>
<input type=hidden name=ie value="ISO-8859-1">
<input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value="">
<br>
<input name=btnG type=submit value="Google Search">
<input name=btnI type=submit value="I'm Feeling Lucky">
</td><td nowrap width=25% align=left>
<font size=-2>&nbsp;&nbsp;<a href=/advanced_search?hl=en>
Advanced Search</a><br>&nbsp;&nbsp;
<a href=/preferences?hl=en>Preferences</a><br>&nbsp;&nbsp;
<a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table>
</form>

Если вы знаете, как сделать HTTP-запрос с вашего любимого языка программирования, просто попробуйте и посмотрите, что вы получите. Попробуйте это например:

http://www.google.com/search?hl=en&q=Stack+Overflow
0 голосов
/ 17 июля 2009

Если вы загружаете Cygwin и добавляете Cygwin \ bin к своему пути, вы можете использовать curl для получения страницы и grep / sed / what для анализа результатов. Зачем заполнять форму, если с помощью Google вы все равно можете использовать параметры строки запроса? С помощью curl вы также можете публиковать информацию, устанавливать информацию заголовка и т. Д. Я использую ее для вызова веб-служб из командной строки.

...