我正在抓取一个在经典 asp.net 中完成的网站。它有 2 个带 ID 的字段。一个是输入文本,另一个是按钮。我需要填写输入框并单击按钮。并得到回应。该按钮是提交类型。
我使用的是 HTML 敏捷包。但是仅仅填写输入框并点击按钮是不够的。
代码示例是: '
<table class="MainTable">
<tbody>
<tr>
<td class="styleIndent"> </td>
<td class="Labels"><span id="ctl00_MainContent_lblLastName" class="fieldHeader" for="ctl00_MainContent_txtLastName">Name:</span></td>
<td class="styleColumnBody">
<input name="ctl00$MainContent$txtLastName" type="text" value="sberbank" maxlength="250" id="ctl00_MainContent_txtLastName" tabindex="2" title="Enter name as search criteria." style="width:200px;">
</td>
<td class="Labels"><span id="ctl00_MainContent_lblCity" class="fieldHeader" for="ctl00_MainContent_txtCity">City:</span></td>
<td class="styleColumnBody">
<input name="ctl00$MainContent$txtCity" type="text" maxlength="250" id="ctl00_MainContent_txtCity" tabindex="6" title="Enter city name as search criteria." style="width:200px;">
</td>
</tr>
<tr>
<td class="Labels"></td>
<td style="text-align: left">
<input type="submit" name="ctl00$MainContent$btnSearch" value="Search" id="ctl00_MainContent_btnSearch" tabindex="9" style="font-weight:normal;height:22px;width:96px;">
<input type="submit" name="ctl00$MainContent$btnReset" value="Reset" id="ctl00_MainContent_btnReset" tabindex="10" style="font-weight:normal;height:22px;width:96px;">
</td>
</tr>
</tbody></table>
'
这是一个经典的 .Net,点击按钮即可重新加载页面 (ctl00_MainContent_btnSearch)。所以通过检查页面很难知道任何事情:
Html Agility Pack 旨在解析、查询和操作 HTML DOM。某种爬虫将是它的用例。但是你想实际run http 请求、javascript 事件或那些按钮后面的任何东西。具有大多数功能的最简单方法是远程控制网络浏览器。
首先安装 Selenium 和浏览器驱动程序。我在这里使用 Firefox,因为它是免费的、开源的并且关注隐私:
Install-Package Selenium.WebDriver
Install-Package Selenium.Firefox.WebDriver
下载浏览器的驱动程序可执行文件。 Firefox gecko 驱动程序可以在 github 上找到:https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-win64.zip版本概述如果帖子变老:https //github.com/mozilla/geckodriver/releases
现在执行存档并将其路径复制到变量:
string geckoDriverPath = @"D:\Downloads\geckodriver-v0.24.0-win64";
我们准备开始使用 Firefox。一个简单的例子,在 stackoverflow 的搜索字段中输入一些查询,然后单击右侧的搜索按钮:
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using System;
class Program {
static void Main(string[] args) {
string geckoDriverPath = @"D:\Downloads\geckodriver-v0.24.0-win64";
using (var driver = new FirefoxDriver(geckoDriverPath)) {
driver.Navigate().GoToUrl("https://stackoverflow.com");
var searchBox = driver.FindElementByCssSelector("#search .js-search-field");
searchBox.SendKeys("Selenium");
var searchButton = driver.FindElementByCssSelector("#search .js-search-submit");
searchButton.Click();
Console.Read();
}
}
}
请耐心等待,初始化浏览器可能需要几秒钟。
根据您点击按钮的作用,可能还有其他方法。如果是某种 http 请求(表单或 ajax 调用),您可以手动发送。这更快,节省资源,您可以轻松地无头运行它。但这更难实现。特别是在需要从页面源中提取 id 等数据的复杂页面上。如果你关心性能和资源,你可以考虑这个。
如果表单是标准的HTML表单,可以获取post-back url,然后自己post表单数据。本质上,您正在执行按钮通常会执行的操作,而不是填写表单本身。
要使其正常工作,您需要发布到的 URL 以及发布回服务器的元素的名称。您可以通过任何 Web 检查器工具轻松获得它。拥有它后,您可以执行以下操作:
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = HttpMethod.Post.ToString();
request.ContentType = "application/json";
// replace name1, name2, value1, value2 with the
// key value pairs that need to be posted.
var content = $"{name1}={value1}&{name2}={value2}"
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(content);
}
request.ContentLength = content.Length;
using (var response = (HttpWebResponse)request.GetResponse())
{
var encoding = Encoding.GetEncoding(response.CharacterSet);
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream, encoding))
{
return reader.ReadToEnd();
}
}
}
如果您使用的是 .NET 4.5 或更高版本,您可以使用 HttpClient 类,这使这变得更加简单:
var httpClient = new HttpClient();
response = await httpClient.PostAsync(uri, new StringContent(data));
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
使用 headless chrome 怎么样?您可以导航到网页并根据需要进行任何操作。
https://github.com/kblok/puppeteer-sharp
// lauch browser and save in variable
var _browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
ExecutablePath = _config.ChromePath, // get path to chrome executable
});
// go to page
var _page = await _browser.NewPageAsync();
var page.GoToAsync("http://www.example.com");
// click on form input
await _page.ClickAsync("#name");
// set data
await _page.Keyboard.SendCharacterAsync("John");
// submit form
await _page.ClickAsync("#SubmitButton");
首先,您需要在项目中安装Selenium WebDriver NuGet 包。您可以使用以下命令从 NuGet 控制台执行此操作:
安装包 Selenium.WebDriver
在您的控制器中,您可以定义一个操作,该操作接收要搜索的 ID 号并使用 Selenium WebDriver 导航到搜索页面、填写表单并获取结果。这是此操作的示例:
public IActionResult Index()
{
var userAgent = HttpContext.Request.Headers["User-Agent"];
return View();
}
public IActionResult Search(string dni)
{
var options = new ChromeOptions();
options.AddArgument("headless");
options.AddArgument("disable-gpu");
IWebDriver driver = new ChromeDriver(options);
try
{
// Navegar a la página de búsqueda
driver.Navigate().GoToUrl("https://eldni.com/pe/buscar-por-dni");
// Llenar el formulario con el número de DNI
var inputElement = driver.FindElement(By.Name("dni"));
inputElement.SendKeys(dni);
// Hacer clic en el botón de búsqueda
var buttonElement = driver.FindElement(By.XPath("//button[contains(@class, 'btn-success')]"));
buttonElement.Click();
//// Esperar a que la página de resultados cargue completamente
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement resultsElement = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("div-copy")));
// Obtener los resultados
string nombre = resultsElement.FindElement(By.Id("nombres")).GetAttribute("Value");
string apellidop = resultsElement.FindElement(By.Id("apellidop")).GetAttribute("Value");
string apellidom = resultsElement.FindElement(By.Id("apellidom")).GetAttribute("Value");
// Devolver los resultados en la vista
return Json(new { Nombre = nombre, ApellidoP = apellidop, ApellidoM = apellidom });
}
finally
{
// Cerrar el navegador
driver.Quit();
}
}
在你的视图中,可以显示上一步得到的结果:
$(document).ready(function () {
$("#searchButton").click(function () {
var dni = $("#dni").val();
$.ajax({
type: "POST",
url: "/Controller/Search?dni=" + dni,
success: function (data) {
$("#resultado").html(
"<br><br>" +
"<h3>RESULTADO</h3>" +
"<table class='table-bordered table-striped' style='width: 100%' >" +
"<thead><tr><th>NOMBRES</th><th>A. PATERNO</th><th>A. MATERNO</th></tr></thead>" +
"<tbody><tr><td>" + data.Nombre + "</td><td>" + data.ApellidoP + "</td><td>" + data.ApellidoM + "</td></tr></tbody>" +
"</table>"
);
}
});
});
});
<div class="form-group">
<label for="dni">DNI: </label>
<input type="number" class="form-control" id="dni" name="dni" maxlength="8" value="@Model" oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);">
</div>
<button type="button" class="btn btn-primary" id="searchButton">Consultar Datos</button>
<div id="resultado"></div>
希望对你有帮助。问候