Int curloc; // содержит текущее положение в ответе



if (args.Length != 1) {

Console.WriteLine("Применение: MiniCrawler <uri>");

return;

}

string uristr = args[0]; // содержит текущий URI  

HttpWebResponse resp = null;

try {

do {

Console.WriteLine("Переход по ссылке " + uristr);

 

Создать объект запроса типа WebRequest по указанному URI.

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create(uristr);

uristr = null; // запретить дальнейшее использование этого URI

 

Отправить сформированный запрос и получить на него ответ,

resp = (HttpWebResponse)req.GetResponse();

Stream istrm = resp.GetResponseStream();

 

Заключить поток ввода в оболочку класса StreamReader.

StreamReader rdr = new StreamReader(istrm);

 

Прочитать всю страницу,

str = rdr.ReadToEnd();

curloc = 0;

do {

Найти следующий URI для перехода по ссылке,

link = FindLink(str, ref curloc);

if (link != null) {

Console.WriteLine("Найдена ссылка: " + link);

Console.Write("Перейти по ссылке, Искать дальше, Выйти?");

answer = Console.ReadLine();

if (string.Equals(answer, "П", StringComparison.OrdinalIgnoreCase)) {

uristr = string.Copy(link); break;

}

else if (string.Equals(answer, "B", StringComparison.OrdinalIgnoreCase)) {

break;

}

else if (string.Equals(answer, "И", StringComparison.OrdinalIgnoreCase)) {

Console.WriteLine("Поиск следующей ссылки.");

}

}

else {

Console.WriteLine("Больше ссылок не найдено.");

break;

}

} while (link.Length > 0);

 

Закрыть ответный поток,

if (resp != null) resp.Close();

} while (uristr != null);

}

catch (WebException exc) {

Console.WriteLine("Сетевая ошибка: " + exc.Message +

"Код состояния: " + exc.Status);

}

catch (ProtocolViolationException exc) {

Console.WriteLine("Протокольная ошибка: " + exc.Message);

}

catch (UriFormatException exc) {

Console.WriteLine("Ошибка формата URI: " + exc.Message);

}

catch (NotSupportedException exc) {

Console.WriteLine("Неизвестный протокол: " + exc.Message);

}

catch (IOException exc) {

Console.WriteLine("Ошибка ввода-вывода: " + exc.Message);

}

finally {

if (resp != null) resp.Close();

Console.WriteLine("Завершение программы MiniCrawler.");

}

}

}

 

Ниже приведен пример сеанса поиска, начиная с адреса www .McGraw-Hill. com. Следует иметь в виду, что конкретный результат поиска зависит от состояния содержимого на момент поиска.

 

Переход по ссылке http://mcgraw-hill.com

Найдена ссылка: http://sti.mcgraw-hill.com:9000/cgi-bin/query?mss=search&pg=aq

Перейти по ссылке, Искать дальше, Выйти? И

Поиск следующей ссылки.

Найдена ссылка: http: //investor .mcgraw-hill. com/phoenix. zhtml?c=96562&p=irol-irhome  

Перейти по ссылке,Искать дальше, Выйти? П

Переход по ссылке http://investor.mcgraw-hill .com/phoenix. zhtml?c=96562&p=irol-irhome

Найдена ссылка: http://www.mcgraw-hill.com/index.html

Перейти по ссылке, Искать дальше, Выйти? П

Переход по ссылке http://www.mcgraw-hill.com/index.html

Найдена ссылка: http://sti.mcgraw-hill.com:9000/cgi-bin/query?mss=search&pg=aq

Перейти по ссылке, Искать дальше, Выйти? В

Завершение программы MiniCrawler.

 

Рассмотрим подробнее работу программы MiniCrawler. Она начинается с ввода пользователем конкретного URI в командной строке. В методе Main() этот URI сохраняется в строковой переменной uristr. Затем по указанному URI формируется запрос, и переменной uristr присваивается пустое значение, указывающее на то, что данный URI уже использован. Далее отправляется запрос и получается ответ. После этого содержимое читается из потока ввода, возвращаемого методом GetResponseStream() и заключаемого в оболочку класса StreamReader. Для этой цели вызывается метод ReadToEnd(), возвращающий все содержимое в виде строки из потока ввода.

Далее программа осуществляет поиск ссылки в полученном содержимом. Для этого вызывается статический метод FindLink(), определяемый в программе MiniCrawler. Этот метод вызывается со строкой содержимого и исходным положением, с которого начинается поиск в полученном содержимом. Эти значения передаются методу FindLink() в виде параметров htmlstr и startloc соответственно. Обратите внимание на то, что параметр startloc относится к типу ref. Сначала в методе FindLink() создается копия строки содержимого в нижнем регистре, а затем осуществляется поиск подстроки href="http, обозначающей ссылку. Если эта подстрока найдена, то URI копируется в строковую переменную uri, а значение параметра startloc обновляется и становится равным концу ссылки. Но поскольку параметр startloc относится к типу ref, то это приводит к обновлению соответствующего аргумента метода Main(), активизируя поиск с того места, где он был прерван. В конечном итоге возвращается значение переменной uri. Эта переменная инициализирована пустым значением, и поэтому если ссылка не найдена, то возвращается пустая ссылка, обозначающая неудачный исход поиска.

Если ссылка, возвращаемая методом FindLink(), не является пустой, то она отображается в методе Main(), и далее программа запрашивает у пользователя очередные действия. Пользователю предоставляются одна из трех следующих возможностей: перейти по найденной ссылке, нажав клавишу <П>, искать следующую ссылку в имеющемся содержимом, нажав клавишу <И>, или же выйти из программы, нажав клавишу <В>. Если пользователь нажмет клавишу <П>, то программа осуществит переход по найденной ссылке и получит новое содержимое по этой ссылке. После этого поиск очередной ссылки будет начат уже в новом содержимом. Этот процесс продолжается до тех пор, пока не будут исчерпаны все возможные ссылки.

В качестве упражнения вы сами можете усовершенствовать программу MiniCrawler, дополнив ее, например, возможностью перехода по относительным ссылкам. Сделать это не так уж и трудно. Кроме того, вы можете полностью автоматизировать поисковый робот, чтобы он сам переходил по найденной ссылке без вмешательства со стороны пользователя, начиная со ссылки, обнаруженной на самой первой странице полученного содержимого, и продолжая переход по ссылкам на новых страницах. Как только будет достигнут тупик, поисковый робот должен вернуться на один уровень назад, найти следующую ссылку и продолжить переход по ссылке. Для организации именно такого алгоритма работы программы вам потребуется стек, в котором должны храниться идентификаторы URI и текущее состояние поиска в строке URL С этой целью можно, в частности, воспользоваться коллекцией класса Stack. В качестве более сложной, но интересной задачи попробуйте организовать вывод ссылок в виде дерева.

 

 

Применение класса WebClient

 

В заключение этой главы уместно рассмотреть класс WebClient. Как упоминалось в самом ее начале, класс WebClient рекомендуется использовать вместо классов WebRequest и WebResponse в том случае, если в приложении требуется лишь выгружать или загружать данные из Интернета. Преимущество класса WebClient заключается в том, что он автоматически выполняет многие операции, освобождая от их программирования вручную.

В классе WebClient определяется единственный конструктор.

 

Public WebClient()

 

Кроме того, в классе WebClient определяются свойства, сведенные в табл.26.6, а также целый ряд методов, поддерживающих как синхронную, так и асинхронную передачу данных. Но поскольку рассмотрение асинхронной передачи данных выходит за рамки этой главы, то в табл. 26.7 приведены только те методы, которые поддерживают синхронную передачу данных. Все методы класса WebClient генерируют исключение WebException, если во время передачи данных возникает ошибка.

 

Таблица 26.6. Свойства, определенные в классе WebClient

 

Свойство - Описание

 

public string BaseAddress { get; set; } -  Получает или устанавливает базовый адрес требуемого URI. Если это свойство установлено, то адреса, задаваемые в методах класса WebClient, должны определяться относительно этого базового адреса

public RequestCachePolicy CachePolicy { get; set; } -  Получает или устанавливает правила, определяющие, когда именно используется кэш

public ICredentials Credentials { get; set; } -  Получает или устанавливает мандат, т.е. учетные данные пользователя. По умолчанию это свойство имеет пустое значение

public Encoding Encoding { get; set; } -  Получает или устанавливает схему кодирования символов при передаче строк

 

public WebHeaderCollection Headers{ get; set; } -  Получает или устанавливает коллекцию заголовков запроса

public bool IsBusy { get; } -  Принимает логическое значение true, если данные по-прежнему передаются по запросу, а иначе — логическое значение false

public IWebProxy Proxy { get; set; } -  Получает или устанавливает прокси-сервер

public NameValueCollection QueryString { get; set; } -  Получает или устанавливает строку запроса, состоящую из пар “имя-значение”, которые могут быть присоединены к запросу. Строка запроса отделяется от URI символом ?. Если же таких пар несколько, то каждая из них отделяется символом @

public WebHeaderCollection ResponseHeaders{ get; } -  Получает коллекцию заголовков ответа

public bool UseDefaultCredentials { get; set; } -  Получает или устанавливает значение, которое определяет, используется ли для аутентификации устанавливаемый по умолчанию мандат. Если принимает логическое значение true, то используется мандат, устанавливаемый по умолчанию, т.е. учетные данные пользователя, в противном случае этот мандат не используется

 

Таблица 26.7. Методы синхронной передачи, определенные в классе WebClient

 

Метод - Определение

 

public byte[] DownloadData(string address) -  Загружает информацию по адресу URI, обозначаемому параметром address. Возвращает результат в виде массива байтов

public byte[] DownloadData(Uri address) -  Загружает информацию по адресу URI, обозначаемому параметром address. Возвращает результат в виде массива байтов

public void DownloadFile(string uri,  string fileName) -  Загружает информацию по адресу URI, обозначаемому параметром fileName. Сохраняет результат в файле fileName

public void DownloadFile(Uri  address, string fileName) -  Загружает информацию по адресу URI, обозначаемому параметром address. Сохраняет результат в файле fileName

public string DownloadString(string  address) -  Загружает информацию по адресу URI, обозначаемому параметром address. Возвращает результат в виде символьной строки типа string

public string DownloadString(Uri address) -  Загружает информацию по адресу URI, обозначаемому параметром address. Возвращает результат в виде символьной строки типа string

public Stream OpenRead(string address) -  Возвращает поток ввода для чтения информации по адресу URI, обозначаемому параметром address. По окончании чтения информации этот поток необходимо закрыть

public Stream OpenRead(Uri  address) -  Возвращает поток ввода для чтения информации по адресу URI, обозначаемому параметром address. По окончании чтения информации этот поток необходимо закрыть

public Stream OpenWrite(string address) -  Возвращает поток вывода для записи информации по адресу URI, обозначаемому параметром address. По окончании записи информации этот поток необходимо закрыть

public Stream OpenWrite(Uri  address) -  Возвращает поток вывода для записи информации по адресу URI, обозначаемому параметром address. По окончании записи информации этот поток необходимо закрыть

public Stream OpenWrite(string address,  string method) -  Возвращает поток вывода для записи информации по адресу URI, обозначаемому параметром address. По окончании записи информации этот поток необходимо закрыть. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public Stream OpenWrite(Uri  address, string method) -  Возвращает поток вывода для записи информации по адресу URI, обозначаемому параметром address. По окончании записи информации этот поток необходимо закрыть. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public byte[] UploadData(string address,  byte[] data) -  Записывает информацию из массива data по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ

public byte[] UploadData(Uri  address, byte[] data) -  Записывает информацию из массива data по адресу URI, 'обозначаемому параметром address. В итоге возвращается ответ

public byte[] UploadData(string address,  string method, byte[] data) -  Записывает информацию из массива data по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ. В строке, передаваемой в качестве параметра method, указывается, как именно следует записывать информацию

public byte[] UploadData(Uri  address, string method,  byte[] data) -  Записывает информацию из массива data по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ. В строке, передаваемой в качестве параметра method, указывается, как именно следует записывать информацию

public byte[] UploadFile(string address,  string fileName) -  Записывает информацию в файл fileName по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ

public byte[] UploadFile(Uri  address, string fileName) -  Записывает информацию в файл fileName по адресу URI, обозначаемому параметром address. В итоге возвращается ответ

public byte[] UploadFile (string address,  string method, string  fileName) -  Записывает информацию в файл fileName по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public byte[] UploadFile(Uri  address, string method , string fileName) -  Записывает информацию в файл fileName по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public string UploadString(string address,  string data) -  Записывает строку data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ

public string UploadString(Uri address,  string data) -  Записывает строку data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ

public string UploadString(string address,  string method, string data) -  Записывает строку data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public string UploadString(Uri address,  string method, string data) -  Записывает строку data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public byte[] UploadValues(string address,  NameValueCollection data) -  Записывает значения из коллекции data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ

public byte[] UploadValues(Uri address,  NameValueCollection data) -  Записывает значения из коллекции data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ

public byte[] UploadValues(string  address, string method,  NameValueCollection data) -  Записывает значения из коллекции data по адресу URI, обозначаемому параметром address.  В итоге возвращается ответ. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

public byte[] UploadValues(Uri  address, string method,  NameValueCollection data) -  Записывает значения из коллекции data по адресу URI, обозначаемому параметром address. В итоге возвращается ответ. В строке, передаваемой в качестве параметра method , указывается, как именно следует записывать информацию

 

В приведенном ниже примере программы демонстрируется применение класса WebClient для загрузки данных в файл по указанному сетевому адресу.

 

// Использовать класс WebClient для загрузки данных  

// в файл по указанному сетевому адресу.

using System;

using System.Net;

using System.IO;

class WebClientDemo {

static void Main() {

WebClient user = new WebClient();

string uri = "http://www.McGraw-Hill.com";

string fname = "data.txt";

try {

Console.WriteLine("Загрузка данных по адресу "  

+ uri + " в файл " + fname);

user.DownloadFile(uri, fname);

}

catch (WebException exc) {

Console.WriteLine(exc);

}

Console.WriteLine("Загрузка завершена.");

}

}

 

 

Эта программа загружает информацию по адресу www .McGrawHill. com и помещает ее в файл data.txt. Обратите внимание на строки кода этой программы, в которых осуществляется загрузка информации. Изменив символьную строку uri, можно загрузить информацию по любому адресу URI, включая и конкретные файлы, доступные по указываемому URL

Несмотря на то что классы WebRequest и WebResponse предоставляют больше возможностей для управления и доступа к более обширной информации, для многих приложений оказывается достаточно и средств класса WebClient. Этим классом особенно удобно пользоваться в тех случаях, когда требуется только загрузка информации из веб-ресурса. Так, с помощью средств класса WebClient можно получить из Интернета обновленную документацию на приложение.

 

ПРИЛОЖЕНИЕ


Дата добавления: 2019-02-12; просмотров: 261; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!