Есть ли более быстрый способ проверить, существует ли внешняя веб-страница?

Я написал этот метод, чтобы проверить, существует ли страница или нет:

protected bool PageExists(string url)
{
try
    {
        Uri u = new Uri(url);
        WebRequest w = WebRequest.Create(u);

            w.Method = WebRequestMethods.Http.Head;

        using (StreamReader s = new StreamReader(w.GetResponse().GetResponseStream()))
        {
            return (s.ReadToEnd().Length >= 0);
        }
    }
        catch
    {
        return false;
        }
    }

Я использую его для проверки набора страниц (итерации из AAAA-AAAZ), и для запуска всего цикла требуется от 3 до 7 секунд. Есть ли более быстрый или эффективный способ сделать это?

Ответ 1

Я думаю, что ваш подход довольно хорош, но изменил бы его на загрузку заголовков, добавив w.Method = WebRequestMethods.Http.Head; перед вызовом GetResponse.

Это может сделать это:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.example.com");
request.Method = WebRequestMethods.Http.Head;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
bool pageExists = response.StatusCode == HttpStatusCode.OK;

Возможно, вам захочется также проверить другие коды состояния.

Ответ 2

static bool GetCheck(string address)
{
    try
    {
        HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
        request.Method = "GET";
        request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
        var response = request.GetResponse();
        return (response.Headers.Count > 0);
    }
    catch
    {
        return false;
    }
}
static bool HeadCheck(string address)
{
    try
    {
        HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
        request.Method = "HEAD";
        request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
        var response = request.GetResponse();
        return (response.Headers.Count > 0);
    }
    catch
    {
        return false;
    }
}

Остерегайтесь, некоторые страницы (например, файлы WCF.svc) могут ничего не возвращать из запроса главы. Я знаю, потому что сейчас я работаю над этим. EDIT - я знаю, что есть лучшие способы проверить возвращаемые данные, чем подсчет заголовков, но это копия/вставка из материала, где это важно для нас.

Ответ 3

Одно очевидное ускорение заключается в том, чтобы запускать несколько запросов параллельно - большая часть времени будет потрачена на IO, поэтому размножение 10 потоков для каждой проверки страницы завершит всю итерацию примерно в 10 раз быстрее.

Ответ 4

  • Вы можете сделать это, используя асинхронный путь, потому что теперь вы ожидаете результатов после каждого запроса. Для нескольких страниц вы можете просто бросить свою функцию в ThreadPool и дождаться завершения всех запросов. Для получения дополнительных запросов вы можете использовать асинхронные методы для ResponseStream() (BeginRead и т.д.).
  • Другая вещь, которая может вам помочь (помогите мне точно) - очистить свойство .Proxy:
w.Proxy = null;

Без этого, по крайней мере, 1-й запрос намного медленнее, по крайней мере на моей машине.
3. Вы не можете загрузить целую страницу, но загружать только заголовок, установив параметр .Method на "HEAD".

Ответ 5

Я просто использовал ответ Фредрика Мёрка выше, но поместил его в метод:

private bool checkURL(string url)
        {
            bool pageExists = false;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = WebRequestMethods.Http.Head;
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                pageExists = response.StatusCode == HttpStatusCode.OK;
            }
            catch (Exception e)
            {
                //Do what ever you want when its no working...
                //Response.Write( e.ToString());
            }
            return pageExists;
        }