我想創建一個程序,將一個字符串輸入到像Google這樣的網站上的文本框(不使用他們的公共API),然後提交表單並獲取結果。這可能嗎?抓取結果將需要使用我假設的HTML抓取,但是如何將數據輸入到文本字段並提交表單?我會被迫使用公共API嗎?像這樣的東西只是不可行?我需要找出查詢字符串/參數嗎?如何在不使用API的情況下以編程方式執行搜索?
謝謝
我想創建一個程序,將一個字符串輸入到像Google這樣的網站上的文本框(不使用他們的公共API),然後提交表單並獲取結果。這可能嗎?抓取結果將需要使用我假設的HTML抓取,但是如何將數據輸入到文本字段並提交表單?我會被迫使用公共API嗎?像這樣的東西只是不可行?我需要找出查詢字符串/參數嗎?如何在不使用API的情況下以編程方式執行搜索?
謝謝
理論
我會做的是創建一個小程序,可以任何形式的數據自動提交到任何地方,回來的結果。在Java中使用HTTPUnit很容易。任務如下:
你選擇將取決於多種因素,包括解決方案:
例如,你可以試試下面的應用程序提交數據給你:
然後grep(AWK或sed的)生成的網頁。
屏幕抓取是下載示例HTML文件並在vi(或VIM)中手動解析它的另一個技巧。將擊鍵保存到文件中,然後在運行查詢時,將這些擊鍵應用於生成的網頁以提取數據。這種解決方案不可維護,也不可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的和FormElements類$ CLASSPATH):
java -cp $CLASSPATH FormElements com.mellon.properties "John" "Doe" "[email protected]" "To whom it may concern ..."
合法性
Another answe r提到它可能違反使用條款。首先檢查一下,然後再花時間研究技術解決方案。非常好的建議。
大多數情況下,您可以發送簡單的HTTP POST請求。
我建議你試着玩Fiddler來了解網絡的工作原理。
幾乎所有的編程語言和框架都有發送原始請求的方法。
而且您可以隨時針對Internet Explorer ActiveX控件進行編程。我相信很多編程語言都支持它。
嗯,這裏是從谷歌頁面的HTML:
<form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top>
<td width=25%> </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> <a href=/advanced_search?hl=en>
Advanced Search</a><br>
<a href=/preferences?hl=en>Preferences</a><br>
<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
如果您下載Cygwin,並將Cygwin \ bin添加到您的路徑中,則可以使用curl來檢索頁面和grep/sed/whatever來解析結果。爲什麼填寫表格時,谷歌可以使用querystring參數,反正?使用curl,您也可以發佈信息,設置標題信息等。我使用它從命令行調用Web服務。
哇,謝謝你。時間閱讀:D – kgrad 2009-07-17 04:13:57