Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB6 > Как можно получить текст с web-страницы ?


Автор: svch 11.3.2008, 08:59
Добрый день !
Задача у меня вот какая: надо с страницы выдернуть текст.
Подошел бы HTML, но дело в том, что часть контента формируется с помощью JS, и соотв-но в HTML-коде этого контента нет. ResponseText из Msxml2.XMLHTTP возвращает почему-то HTML.
Получилось взять текст только с помощью InternetExplorer.Application, но он как-то уж очень медленно работает.
Если у кого есть идеи - буду очень признателен.

С уважением, Сергей.

Автор: Akina 11.3.2008, 09:22
MSInet Control получает текст непосредственно от сервера. Ему JS и исполнять-то нечем...

Автор: svch 11.3.2008, 11:40
Ну сервер-то отдаст что надо. А вот как получить текст, исполняемый в браузере ? Я так понимаю, что только создав что-то типа InternetExplorer.Application.
Честно говоря думал всегда, что ResponseText возвращает текст, а ResponseHTML соотв-но код страницы.

Автор: Akina 11.3.2008, 11:46
Цитата(svch @  11.3.2008,  12:40 Найти цитируемый пост)
как получить текст, исполняемый в браузере ? 

Ну русским же языком сказал - на форму MS Inet Control, Inet1.Execute URL, "GET" и выгребай свой яваскрипт

Автор: svch 11.3.2008, 12:23
Код

      Set obj = CreateObject("InetCtls.Inet.1")
      obj.RequestTimeout = 20

      sRequest = Trim("http://www.yandex.ru")
      sText = obj.OpenURL(CStr(sRequest))

      Set obj = Nothing


sText содержит HTML код. А как можно текст страницы получить ? Я все таки, наверное, не до конца понимаю.

Автор: Akina 11.3.2008, 13:54
См. аттач

Автор: svch 11.3.2008, 15:01
Говорит, что не хватает аргументов Inet1.Execute(URL, "GET")

Автор: Akina 11.3.2008, 15:17
Значит, у тебя референс на Microsoft Internet Transfer Control 6.0 улетел - восстанови. Проект - Компоненты.

Автор: svch 11.3.2008, 16:00
Вот тут написано, что у метода Execute (для HTTP) должно быть 4 аргумента
http://read.excode.ru/art696p1.html

Автор: Akina 11.3.2008, 16:27
Версию system32\msinet.ocx озвучьте плиз

Автор: svch 11.3.2008, 16:46
user posted image

Я, скорее всего что-то не так делаю, потому как в Access работает и такой код:

Код

Me.Inet1.Execute Me.text1.Value

т.е. с единственным аргументом.
И Inet1.GetChunk(1024, icString) все равно возвращает (в Access) HTML-код.

Автор: svch 11.3.2008, 17:14
В общем вот такая вот ситуация: работает только с таким кодом
Код

Inet1.Execute(URL, "GET", "", "")


Но все равно возвращает не текст с страницы, а ее HTML-код. Ай нид хелп. Буду очень признателен.

С уважением, Сергей.

Автор: Akina 11.3.2008, 17:51
Вот что получаю я...
Версия msinet.ocx - 6.00.8862, wininet.dll - 6.00.3790.4186 (srv03_sp2_qfe.071108-1306)

Автор: svch 11.3.2008, 18:10
Я тему специально назвал:
Как можно получить текст с web-страницы ? Не HTML-контент, а именно текст.


Тот пример, что Вы здесь привели возвращает именно HTML-код, среди которого, конечно, есть ЧАСТЬ текста страницы. Примером может служить всем известный Яндекс-директ, который на странице в браузере виден, а в HTML-коде его нет, только ява-скрипт.

Автор: Akina 11.3.2008, 19:07
Упс... вижу одно, думаю другое... сорри, бывает.
Тады чуть позже.

Автор: Naghual 11.3.2008, 19:17
Код

Private Sub Command2_Click()
    WebBrowser1.Navigate2 Trim(Text1.Text)
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Text2.Text = WebBrowser1.Document.body.innerText
End Sub

Автор: svch 12.3.2008, 13:03
Извините, а можно ли полный код представить ?
Ну что-то вроде:
Код

Set inet = CreateObject("....")
Inet.Navigate ...
MsgBox "Текст страницы ..."


Огромное Вам спасибо.
С уважением, Сергей.

Автор: Naghual 12.3.2008, 13:13
Так полнее некуда!  ;)

Кладешь на форму WebBrowser(WebBrowser1) и пользуешься кодом.

Добавлено через 10 минут и 6 секунд
Простите, понял свою ошибку - исправляю:

Подключаешь к проекту компонент "Microsoft Internet Controls" (ieframe.dll).
Кладешь на форму новый экземпляр объекта WebBrowser с именем WebBrowser1.
Используешь код.

Автор: svch 12.3.2008, 14:08
Вот, что у меня кажет :(

user posted image

Автор: Naghual 12.3.2008, 14:18
У вас на форме нет созданного экземпляра компонента.  В этом проблема.

Автор: svch 12.3.2008, 14:27
Ну как же нет, если даже навигация прошла и этот компонент получил html-код сайта ?

user posted image

Автор: Naghual 12.3.2008, 14:30
Странно. У меня на VB6 работает.
Попробуйте подключить рефференс того, чему у вас соответствует Body.

Автор: svch 12.3.2008, 15:30
А вы не могли бы выложить сюда нужные файлы (для регистрации и пример кода) ?
У меня просто VS 2005, я только начинающий ... и "подключить рефференс того, чему у вас соответствует Body" - не знаю, что это значит.

Спасибо.
С уважением, Сергей.

Автор: Naghual 12.3.2008, 15:53
Пожалуйста. Вот проект.

Автор: Akina 12.3.2008, 16:29
Цитата(svch @  12.3.2008,  16:30 Найти цитируемый пост)
У меня просто VS 2005, я только начинающий

Ну не до такой же степени, чтобы ошибаться разделом...

Тема перенесена

Автор: Akina 12.3.2008, 16:30
Перемещено в VB .NET.

Автор: svch 12.3.2008, 20:26
В общем что-то начало вырисовываться ...
В браузере открывается страница, текст получить могу.
Но есть одно "но".
Страниц этих у меня довольно много, и я сделал цикл по таблице с урлами.
При переходе на следующую запись в таблице я гружу текущий урл в браузер и вот тут получается затык.
Дело в том, что надо как-то дождаться, пока страница полностью загрузится и уже после получать с нее текст.

Пытался как-то обрабатывать WebBrowser_DocumentComplete и WebBrowser.Busy, но как-то безуспешно. 
Помогите добить до конца уж ...

С уважением, Сергей.

З.Ы. Может все таки тему обратно в VB6 перенести ? Я таки его себе установил.

Автор: Naghual 12.3.2008, 21:00
Загрузку каждого последующего адреса нужно вызывать в конце процедуры WebBrowser_DocumentComplete, после извлечения текста страницы.


Цитата(svch @  12.3.2008,  19:26 Найти цитируемый пост)
З.Ы. Может все таки тему обратно в VB6 перенести ? Я таки его себе установил. 

Попроси Akina.   smile 

Автор: Exception 13.3.2008, 16:19
Ну вы даёте smile . Вам вообще без разницы, на .NET писать или на 6 o_O ? Это же абсолютно разные вещи.
Перемещаю обратно.

Автор: svch 13.3.2008, 17:14
Цитата

Загрузку каждого последующего адреса нужно вызывать в конце процедуры WebBrowser_DocumentComplete

А как его там вызывать-то ? Если использовать что-то похожее на это.

Код

Private Sub Command1_Click()
    Do Until tbl.EOF
        WebBrowser1.Navigate (tbl!url)
        tbl.MoveNext
    Loop
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, url As Variant)
    MsgBox WebBrowser1.Document.body.innerText
End Sub


С уважением, Сергей.

Автор: Naghual 13.3.2008, 17:25
Ну хотя бы так:
Код

Private Sub Command1_Click()
        tbl.MoveFirst
        WebBrowser1.Navigate (tbl!url)
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, url As Variant)
    MsgBox WebBrowser1.Document.body.innerText
    if not tbl.EOF then
        tbl.MoveNext
        WebBrowser1.Navigate (tbl!url)
    end if
End Sub

Автор: svch 13.3.2008, 18:34
А по какой причине 
Код

WebBrowser1.Document.body.innerText

может возвращать пустое значение ? Хотя страница в браузер грузится.

Автор: Naghual 13.3.2008, 18:36
Ну например, если страница из фреймов.

Автор: svch 14.3.2008, 12:32
Нет, фреймов нет. Что-то все равно я не так делаю :(

Код

Private Sub Command1_Click()
    Dim db, tbl, sql, tmp_url
    Set db = CreateObject("ADODB.Connection")
    Set tbl = CreateObject("ADODB.RecordSet")
    db.Open ("base")
    sql = "select * from table where tmp = False"
    tbl.Open sql, db, 3, 1
    tbl.MoveFirst
    
    id.Text = tbl!n
    
    WebBrowser1.Navigate tbl!url
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, url As Variant)
    MsgBox WebBrowser1.Document.body.innerText
    
    Dim db, tbl, sql, tmp_url
    Set db = CreateObject("ADODB.Connection")
    Set tbl = CreateObject("ADODB.RecordSet")
    db.Open ("base")
    sql = "select * from table where tmp = False"
    tbl.Open sql, db, 3, 1
    
    If Not tbl.EOF Then
        tbl.MoveNext
        
        id.Text = tbl!n
        
        db.Execute "UPDATE table SET table.tmp = True WHERE (((table.N)=" & id.Text & "));"
        WebBrowser1.Navigate tbl!url
    End If
    
    tbl.Close
    Set tbl = Nothing
    db.Close
    Set db = Nothing
End Sub


Выдается пустой MsgBox, хотя если открыть этот урл по-простому
Код

WebBrowser1.Navigate ("нужный_мне_урл")
'тут надо что-то типа паузы или проверки, что все загрузилось
MsgBox WebBrowser1.Document.body.innerText

то все отображается нормально. Бьюсь, как рыба об лед. Решение где-то совсем уже рядом.

С уважением, Сергей.

Автор: AlexChuntonov 14.3.2008, 15:27
Народ! Похожая проблема...
Необходимо отслеживать изменеие некое инфы на странице. Структура документа сильно фреймованная. До нужного фрейма посредством DOM добрался. Свойство innerHTML и innerText не возвращает то, что нужно, ибо контент динамический...
Скрипт генерит контент весьма кудряво. Да и сам скрипт, генерящий контент, генерится многоступенчато другим скриптом из другого фрейма. Ну вот такой вот веб-программер извращенец...
НУЖНО:
нужно то, что показывается по меню правой кнопки, пункт "Исходный текст"
Можно конечно и хэндл окна получить, и мессиджи послать, и отловить хэндл окна просмотра исходного кода, и опять мессиджи послать, и текст выгрести... 
Но я не верю, что через DOM или объектную модель эту инфу извлечь невозможно! Я просто не понимаю...
Да и DOM в объекте WebBrowser урезанный какой-то!
WebBrowser.Document.all.frames(i).name возвращает, а...
WebBrowser.Document.all.frames(i).innerHtml - кричит, что неподдерживаемое свойство! Чоза? 

Автор: Naghual 14.3.2008, 15:29
Так у Вас, батенька, нет понимания алгоритма того что Вы же сами и делаете. Читайте основы.
Вот как примерно должно быть:
Код

Dim db, tbl, sql, tmp_url

Private Sub Command1_Click()
    Set db = CreateObject("ADODB.Connection")
    Set tbl = CreateObject("ADODB.RecordSet")
    db.Open ("base")
    sql = "select * from table where tmp = False"
    tbl.Open sql, db, 3, 1
    tbl.MoveFirst
    id.Text = tbl!n
    WebBrowser1.Navigate tbl!url
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, url As Variant)
    MsgBox WebBrowser1.Document.body.innerText
    If Not tbl.EOF Then
        tbl.MoveNext
        id.Text = tbl!n
        WebBrowser1.Navigate tbl!url
    Else
        tbl.Close
        Set tbl = Nothing
        db.Close
        Set db = Nothing
    End If
End Sub


AlexChuntonov, пожалуйста, создайте отдельную тему.

Автор: svch 14.3.2008, 17:02
Да, спасибо большое за поправку.
Но в данном виде код с моими урлами не работает. Такое ощущение, что
Код

MsgBox WebBrowser1.Document.body.innerText

срабатывает раньше, чем страница полностью загружена. 
Я сделал отдельную кнопку с этим событием, загрузил в браузер один из своих урлов, дождался загрузки. Нажал на кнопку и получит нужный текст.
Почитал, что есть события Busy и State. Busy не советуют, а вот как пользоваться State - я найти не могу.

С уважением, Сергей.

Автор: Naghual 14.3.2008, 17:36
В ошибках рождается истина!

Проконтролруйте, не срабатывает ли событие DocumentComplete несколько раз для одного УРЛа. Если да - продебагте все состояния State и Busy для выяснения закономерности.

Вариантов масса - пробуйте.

Автор: svch 14.3.2008, 18:16
Цитата

не срабатывает ли событие DocumentComplete несколько раз для одного УРЛа

Думаю, что нет. Сообщение выдается один раз на один урл. Просто контент страницы, как я говорил, сожержит яву-скрипт, который в свою очередь грузит доп.контент (с другого сайта). Поэтому, может, скачав вель локальный контент и происходит событие WebBrowser1_DocumentComplete ? А вот как дождаться, пока вся страница будет загружена ?
Ставил следующий код в WebBrowser1_DocumentComplete:
Код

Do While Len(WebBrowser1.Document.body.innerText) < 10

Loop

Ходит по этому циклу непереставая  smile 

С уважением, Сергей.

Автор: Naghual 14.3.2008, 18:20
УРЛ в студию!

Автор: svch 14.3.2008, 18:34
Урл в личку ушел.

Автор: Naghual 14.3.2008, 18:39
Ок. Я посмотрел на него.
Вопрос:  Какой текст вы хотите получить с этой страницы, если там НЕТ текста!  Все формируется динамической графикой.

Автор: Naghual 14.3.2008, 19:14
Я думаю над вашим вопросом...

Добавлено через 14 минут и 51 секунду
Вот что придумалось на текущий момент:
Код

Dim PercentageOK As Boolean


Private Sub Command1_Click()
    WebBrowser1.Navigate2 Trim$(Text1.Text)
    PercentageOK = False
End Sub

Private Sub WebBrowser1_DownloadComplete()
    If PercentageOK = True Then
        Text2.Text = WebBrowser1.Document.body.innerText
    End If
End Sub

Private Sub WebBrowser1_ProgressChange(ByVal Progress As Long, ByVal ProgressMax As Long)
    If Progress >= ProgressMax Then
        PercentageOK = True
    End If
End Sub



Пробуйте, пишите.

Автор: svch 17.3.2008, 11:31
В общем пляски с бубнами и помощь участников форума привела меня вот к чему:
в Нете я нашел события, которые есть у компонента WebBrowser, прописал их в код и смотрел, какое событие за каким срабатывает. У меня получилось, что всегда на последнем месте WebBrowser1_CommandStateChange, на него я свой обработчик и поставил. Событие срабатывает несколько раз за навигацию, поэтому надо еще отловить WebBrowser1_DownloadComplete (возможно, это мой частный случай)

Код

Private Sub WebBrowser1_DownloadComplete()
    Debug.Print "DownloadComplete " & Now
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Debug.Print "DocumentComplete " & Now
End Sub

Private Sub WebBrowser1_ProgressChange(ByVal Progress As Long, ByVal ProgressMax As Long)
    Debug.Print "ProgressChange " & Now
End Sub

Private Sub WebBrowser1_NewWindow(ByVal URL As String, ByVal Flags As Long, ByVal TargetFrameName As String, PostData As Variant, ByVal Headers As String, Processed As Boolean)
    Debug.Print "NewWindow " & Now
End Sub

Private Sub WebBrowser1_PropertyChange(ByVal szProperty As String)
    Debug.Print "PropertyChange " & Now
End Sub

Private Sub WebBrowser1_Quit(Cancel As Boolean)
    Debug.Print "Quit " & Now
End Sub

Private Sub WebBrowser1_StatusTextChange(ByVal Text As String)
    Debug.Print "StatusTextChange " & Now
End Sub

Private Sub WebBrowser1_TitleChange(ByVal Text As String)
    Debug.Print "TitleChange " & Now
End Sub

Private Sub WebBrowser1_BeforeNavigate(ByVal URL As String, ByVal Flags As Long, ByVal TargetFrameName As String, PostData As Variant, ByVal Headers As String, Cancel As Boolean)
    Debug.Print "beforeNavigation " & Now
End Sub

Private Sub WebBrowser1_CommandStateChange(ByVal Command As Long, ByVal Enable As Boolean)
    Debug.Print "CommandStateChange " & Now
    'вот тут у меня обработчик
End Sub

Private Sub WebBrowser1_DownloadBegin()
    Debug.Print "DownloadBegin " & Now
End Sub

Private Sub WebBrowser1_NavigateComplete(ByVal URL As String)
    Debug.Print "NavigateComplete " & Now
End Sub

Private Sub WebBrowser1_FrameBeforeNavigate(ByVal URL As String, ByVal Flags As Long, ByVal TargetFrameName As String, PostData As Variant, ByVal Headers As String, Cancel As Boolean)
    Debug.Print "FrameBeforeNavigate " & Now
End Sub

Private Sub WebBrowser1_FrameNavigateComplete(ByVal URL As String)
    Debug.Print "FrameNavigateComplete " & Now
End Sub

Private Sub WebBrowser1_FrameNewWindow(ByVal URL As String, ByVal Flags As Long, ByVal TargetFrameName As String, PostData As Variant, ByVal Headers As String, Processed As Boolean)
    Debug.Print "FrameNewWindow " & Now
End Sub


С уважением, Сергей.

Автор: svch 17.3.2008, 13:02
Появился еще трабл :(
При загрузке проги, переход по урлам нормальный и быстрый. Но после 5-10 урлов начинаются тормоза, которые только увеличиваются. Что нужно сделать с браузером, чтоб этого не происходило ? Память как-то очистить или еще что ?

Большое спасибо.
С уважением, Сергей.

Автор: svch 17.3.2008, 22:15
Уважаемые гуру ?
Не обделите вниманием smile Очень нужно решить вопрос.

Буду ОЧЕНЬ признателен.

Автор: svch 18.3.2008, 15:49
Ну в общем пришлось сделать отдельных два exe-шника и из одного запускать другой. Иначе память съедается.

Автор: Kaktusjara 11.8.2009, 10:20
старая тема, сори что поднимаю, но ради этого только зарегался.
насчет пустого msgbox, вместо содержимого страницы:

Короче мой способ прост до безобразия. В самом начале, например при форм.лоад открываем в браузере about:blank, после чего уже вызываем нужную нам страницу.
Когда вы только вызвали страницу сразу запрашивать код или содержимое бесполезно - страница не успевает загрузиться. Но раз мы загрузили бланк (чистая страница), то после вызова интересующей нас странички перед выводом msgbox'а проверить, чтобы WebBrowser1.Document.body.innerText <> "", и проверку зациклить, пока не получим содержимое страницы. 

Надеюсь кому-то это поможет.

Автор: DrBoom 11.8.2009, 10:47
Цитата(Kaktusjara @  11.8.2009,  10:20 Найти цитируемый пост)
после вызова интересующей нас странички перед выводом msgbox'а проверить, чтобы WebBrowser1.Document.body.innerText <> "", и проверку зациклить, пока не получим содержимое страницы. 

Страшный уж способ, ИМХО. DocumentComplete-событие чем не угодило?

Автор: fduck 14.8.2009, 13:19
Читал тему,тк у меня подобный вопрос.
Сделал как описывалось выше! Получилось только вывести ВЕСЬ текст в text,а как вывести отдельный текст в text?
Например,IP,на 2ip.ru.
Как быть?
 smile 

Автор: DrBoom 16.8.2009, 19:03
Цитата(fduck @  14.8.2009,  13:19 Найти цитируемый пост)
а как вывести отдельный текст в text?

Для этого нужно понимать, что вы хотите загружать и где это находится. А для этого Вам нужно понять объектную модель DOM в HTMLе. Привожу несколько примеров, а нужный выбирайте сами.

1. Если известно ID текстового поля:
Код

<input type="text" id="TextBox1" />

То получаем значения из него так:
Код

TextBoxAtForm.Text = SomeWebBrowserAtForm.document.getElementById("TextBox1").value


2. Если известно Name текстового поля:
Код

<input type="text" name="TextBox2" />

То получаем значения из него так:
Код

TextBoxAtForm.Text = SomeWebBrowserAtForm.document.getElementByName("TextBox2").value


3. Если известно Name текстового поля и ID формы:
Код

<form action="" id="Form1"><input type="text" name="TextBox3" /></form>

То получаем значения из него так:
Код

TextBoxAtForm.Text = SomeWebBrowserAtForm.document.getElementByName("Form1").TextBox3.value

ЗЫ. Если неизвестен ID формы, то можно получить её из коллекции forms для объекта document. 

4. Текстовое поле можно тж. найти в коллекции all для объекта document.
5. Другими элементами также можно манипулировать, например, с помощью свойств innerHTML,  innerTEXT, outerHTML.

Чтобы было понятнее, попробуйте загрузить какую-нибудь страницу и запустить код, а после поэкспериментировать с ним:
Код

On Error Resume Next

 Dim Tag as Variant

For Each Tag In SomeWebBrowserAtForm.document.all
 MsgBox Tag.innerHTML
Next


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)