2009-07-17 29 views
7

Tôi muốn tạo một chương trình sẽ nhập chuỗi vào hộp văn bản trên một trang web như Google (không sử dụng API công khai của họ) và sau đó gửi biểu mẫu và lấy kết quả. Điều này có thể không? Nắm bắt các kết quả sẽ yêu cầu sử dụng các mẩu tin lưu niệm HTML tôi sẽ giả định, nhưng làm cách nào để nhập dữ liệu vào trường văn bản và gửi biểu mẫu? Tôi có bị buộc phải sử dụng API công khai không? Là một cái gì đó như thế này chỉ là không khả thi? Tôi có phải tìm ra chuỗi truy vấn/tham số không?Làm cách nào tôi có thể thực hiện tìm kiếm theo chương trình mà không cần sử dụng API?

Cảm ơn

Trả lời

4

Theory

gì tôi sẽ làm là tạo ra một chương trình nhỏ mà có thể tự động gửi bất kỳ dữ liệu mẫu để bất cứ nơi nào và trở lại với kết quả. Điều này rất dễ thực hiện trong Java với HTTPUnit. Tác vụ như sau:

  • Kết nối với máy chủ web.
  • Phân tích trang.
  • Nhận biểu mẫu đầu tiên trên trang.
  • Điền vào dữ liệu biểu mẫu.
  • Gửi biểu mẫu.
  • Đọc (và phân tích cú pháp) kết quả.

Giải pháp bạn chọn sẽ phụ thuộc vào nhiều yếu tố, bao gồm:

  • dù bạn cần phải bắt chước Javascript
  • Những gì bạn cần làm với các dữ liệu sau đó
  • Những ngôn ngữ với bạn thành thạo
  • Tốc độ ứng dụng (cho một truy vấn hoặc 100.000?)
  • Ứng dụng cần phải hoạt động bao lâu
  • Đây có phải là một sự cố, hoặc nó sẽ phải được duy trì?

Ví dụ, bạn có thể thử các ứng dụng sau đây để gửi dữ liệu cho bạn:

Sau đó grep (awk, hoặc sed) (các) trang web kết quả.

Một mẹo khác khi cạo màn hình là tải xuống tệp HTML mẫu và phân tích cú pháp thủ công trong vi (hoặc VIM) theo cách thủ công. Lưu các tổ hợp phím vào một tệp và sau đó bất cứ khi nào bạn chạy truy vấn, hãy áp dụng các lần nhấn phím đó vào (các) trang web kết quả để trích xuất dữ liệu. Giải pháp này không thể duy trì, cũng không đáng tin cậy 100% (nhưng hiếm khi có màn hình cạo từ trang web). Nó hoạt động và nhanh.

Ví dụ

Một lớp Java bán chung để nộp tờ trang web (đặc biệt là đối phó với đăng nhập vào một trang web) là dưới đây, với hy vọng rằng nó có thể có ích. Không sử dụng nó cho cái ác.

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(); 
    } 
} 

Một tập tin ví dụ thuộc tính sẽ như thế nào:

$ 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 

Run nó tương tự như sau (thay thế đường dẫn đến HttpUnit và lớp FormElements với $ CLASSPATH):

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

Tính hợp pháp

Câu trả lời khác r đã đề cập rằng nó có thể vi phạm điều khoản sử dụng. Kiểm tra điều đó trước tiên, trước khi bạn dành bất kỳ lúc nào để xem xét giải pháp kỹ thuật. Lời khuyên cực kỳ tốt.

+0

Ồ, cảm ơn vì điều này. Đã đến lúc đọc nó: D – kgrad

+0

Bạn được chào đón; nó đang ngồi xung quanh thu thập bụi kỹ thuật số. –

2

Hầu hết thời gian, bạn chỉ có thể gửi yêu cầu HTTP POST đơn giản.

Tôi khuyên bạn nên thử chơi xung quanh với Fiddler để hiểu cách hoạt động của web.

Gần như tất cả các ngôn ngữ lập trình và khung công tác đều có phương pháp gửi yêu cầu thô.

Và bạn luôn có thể lập trình chống lại điều khiển ActiveX của Internet Explorer. Tôi tin rằng nhiều ngôn ngữ lập trình hỗ trợ nó.

1

Vâng, đây là html từ trang 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> 

Nếu bạn biết làm thế nào để thực hiện một yêu cầu HTTP từ ngôn ngữ lập trình yêu thích của bạn, chỉ cần cung cấp cho nó một thử và xem những gì bạn nhận lại. Hãy thử điều này ví dụ:

http://www.google.com/search?hl=en&q=Stack+Overflow 
2

Tôi tin rằng điều này sẽ đưa vào vi phạm pháp luật của các điều khoản sử dụng (tham khảo ý kiến ​​một luật sư về điều đó: các lập trình viên không giỏi đưa ra lời khuyên pháp lý), nhưng, về mặt kỹ thuật, bạn có thể tìm kiếm cho foobar bằng cách chỉ cần truy cập URL http://www.google.com/search?q=foobar và, như bạn nói, hãy xoá HTML kết quả. Có thể bạn cũng sẽ cần giả mạo tiêu đề HTTP User-Agent và có thể một số tiêu đề khác.

Có thể có các công cụ tìm kiếm có điều khoản sử dụng không cấm điều này; bạn và luật sư của bạn có thể được khuyên nên nhìn xung quanh để xem đây có phải là trường hợp không.

0

Nếu bạn tải xuống Cygwin và thêm Cygwin \ bin vào đường dẫn, bạn có thể sử dụng curl để truy xuất trang và grep/sed/bất kỳ thứ gì để phân tích kết quả. Tại sao phải điền vào biểu mẫu khi có google, bạn có thể sử dụng tham số chuỗi truy vấn? Với curl, bạn cũng có thể đăng thông tin, đặt thông tin tiêu đề, v.v. Tôi sử dụng nó để gọi các dịch vụ web từ một dòng lệnh.

Các vấn đề liên quan