Хочу спарсить сайт metanit.com
Стандартными средствами(пример кода https://github.com/extremecodetv/Html-Parser-Tutorial) не выходит. Просто отдает одну пустую страницу.
Пытался использовать Selenium
, но тоже работает через раз, да и способ этот мне не нравится: ради парсинга целый движок браузера загружать.
Может вы знаете способ лучше? И почему не работает обычный System.Net.Http.HttpClient
?
Проверил я данный сайт. Получаете вы не пустую страницу как таковую, а ошибку 403, которая гласит:
Access forbidden!
You don't have permission to access the requested object.
It is either read-protected or not readable by the server.
Из за чего это может быть?
Хм, ну по сути это происходит по двум причинам:
Для начала нам стоит отловить запрос, который мы посылаем при заходе на сервер и по очереди добавлять в наш код все, что необходимо.
Лично я всегда использую подобный код для отправки запросов:
public async Task<string> SendRequest(string url)
{
string data;
var baseAddress = new Uri("https://metanit.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var result = await client.GetAsync(url);
data = await result.Content.ReadAsStringAsync();
}
return data;
}
И так, пробуем по порядку, попробуем задать другой User-Agent. Для этого нам достаточно добавить подобную строку до получения result
переменной:
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17120");
И о чудо, сервер открыл нам доступ!
Если бы сервер требовал от нас Cookie, то стоило бы добавить что то вроде этого до result
:
cookieContainer.Add(baseAddress, new Cookie("key", "value"));
В общем, экспериментируйте и смотрите что именно отправляет ваш браузер на сервер, тогда будет в разы легче сделать то, что вы хотите.
Приведу пример с HttpWebRequest
код получен, парсить можно чем угодно дальше.
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
namespace TestParse
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
txtLog.Text = Parser("https://metanit.com");
}
public static string Parser(string url)
{
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Accept = "application/json";
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
StringBuilder output = new StringBuilder();
output.Append(reader.ReadToEnd());
response.Close();
return output.ToString();
}
}
}
Раз вы упомянули Selenium
приведу пример с использованием WebDriver с возможностью обхода Cloudflare
public string GetHtml(string url)
{
string html = null;
try
{
var driverService = PhantomJSDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
var Driver = new PhantomJSDriver(driverService);
Driver.Navigate().GoToUrl(url);
while (Driver.PageSource.Contains("setTimeout(function()"))
Thread.Sleep(1000);
html = Driver.PageSource;
Driver.Close();
Driver.Quit();
return html;
}
catch { }
return null;
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Можете ли вы пояснить мне, возможно ли использование статических библиотек, написанных на C++, в приложениях на C# и PythonВо время компиляции...
У меня в программе есть Combobox с четырьмя значениями и четыре radiobutton'aМне нужно выбрать первый элемент в combobox, нажать на нужные radiobutton'ы, выбрать...