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; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!