2009-07-17 26 views
7

GoogleのようなサイトのテキストボックスにパブリックAPIを使用せずに文字列を入力し、フォームを送信して結果を取得するプログラムを作成したいと考えています。これは可能ですか?結果を取得するには、私が想定するHTMLスクレイピングを使用する必要がありますが、テキストフィールドにデータを入力してフォームを送信するにはどうすればよいですか?公開APIを使用するように強制されますか?このようなものは実現不可能なのでしょうか?クエリ文字列/パラメータを把握する必要がありますか?APIを使用せずにプログラムで検索を実行するにはどうすればよいですか?

ありがとうございました

答えて

4

理論

は自動的に任意の場所に任意の形式のデータを提出し、その結果に戻って来ることができる小さなプログラムを作成することです。これはJavaでHTTPUnitで簡単に実行できます。タスクは次のようになります。

  • Webサーバーに接続します。
  • ページを解析します。
  • ページの最初のフォームを取得します。
  • フォームデータを入力します。
  • フォームを送信してください。
  • 結果を読み込んで(解析する)。

あなたが選ぶソリューションを含め、様々な要因に依存します:あなたはその後

  • どの言語でのデータで行う必要がありますどのようなJavaScriptの
  • をエミュレートする必要があるかどうか

    • あなたは熟練しています
    • アプリケーション速度(1つのクエリまたはこれは100,000ですか?)
    • アプリケーションをいつ実行する必要がありますか
    • これは単発ですか、それとも維持する必要がありますか?たとえば、

    、あなたはあなたのためにデータを提出するには、次のアプリケーションを試みることができる:

    を次にgrep(awkは、またはSED )結果のWebページ。

    スクリーンスクレイピングのもう一つのトリックは、サンプルのHTMLファイルをダウンロードしてvi(またはVIM)で手動で解析することです。キーストロークをファイルに保存し、クエリを実行するたびに、結果のWebページにキーストロークを適用してデータを抽出します。この解決策は維持可能ではなく、100%の信頼性もありません(ウェブサイトからのスクリーンスクレイピングはめったにありません)。それは動作し、高速です。

    それが役に立つかもしれないと期待して、(特にウェブサイトにログを扱う)以下であるウェブサイトのフォームを提出する半汎用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はパスと$ CLASSPATHのためFormElementsとクラスを置き換え):

    java -cp $CLASSPATH FormElements com.mellon.properties "John" "Doe" "[email protected]" "To whom it may concern ..." 
    

    法律

    もう1つの回答rは使用条件に違反する可能性があると述べました。技術的な解決策を検討する前にまずそれを確認してください。非常に良いアドバイス。

  • +0

    うわー、ありがとう。それを読む時間:D – kgrad

    +0

    あなたを歓迎します。デジタルダストを集めて座っていた。 –

    2

    ほとんどの場合、単純なHTTP POSTリクエストを送信できます。

    ウェブの仕組みを理解するには、Fiddlerで試してみることをおすすめします。

    ほとんどすべてのプログラミング言語とフレームワークには、未処理の要求を送信するためのメソッドがあります。

    いつでもInternet ExplorerのActiveXコントロールに対してプログラムすることができます。私は多くのプログラミング言語がそれをサポートしていると信じています。

    1

    さて、ここでは、GoogleのページからHTMLです:

    <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 
    
    2

    私は(そのことについて弁護士に相談してください!:プログラマは法的助言を与えるのが得意ではありません)これは、使用の用語の法的違反して置くと考えている、しかし、技術的には、あなたが検索できますfoob​​arの場合はURL http://www.google.com/search?q=foobarにアクセスし、結果として得られるHTMLをスクラップするだけです。あなたはおそらくUser-Agent HTTPヘッダーとおそらく他のものを偽造する必要があります。

    おそらく、この使用条件でこれを禁止していない検索エンジンがあります。あなたとあなたの弁護士は、これが本当に事実であるかどうかを見回すように十分にアドバイスされるかもしれません。

    0

    CygwinをダウンロードしてCygwin \ binをパスに追加すると、curlを使用してページを取得し、grep/sed /を使用して結果を解析できます。とにかく、あなたはクエリ文字列のパラメータを使用することができますGoogleでフォームを記入する理由は?カールでは、情報を投稿したり、ヘッダー情報を設定したりできます。コマンドラインからWebサービスを呼び出すために使用します。私はどうなるのか

    関連する問題