Вот так сохраняются отображённые в браузере рисунки

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 04.05.2009 (Пн) 20:25

Нигде в интернете я не смог найти такой код (пришлось анализировать по частям из разных источников), чтобы вот так скопировал-вставил и работает.

Всё, что необходимо для успешного выполнения приложения:
Элементы: форма(Form1), кнопка(Button1), рисунок(PictureBox1), браузер(WebBrowser1)
Project/Properties/References: помимо имеющихся нужно добавить: Microsoft.mshtml.dll и Interop.SHDocVw.dll

Код: Выделить всё
Imports System
Imports System.IO
Imports System.Windows
Imports System.Windows.Forms
Imports System.Drawing.Graphics
Imports System.Runtime.InteropServices
Imports SHDocVw
Imports mshtml

Public Class Form1
    Private Class GDI32
        Public Const SRCCOPY As Integer = &HCC0020
        ' BitBlt dwRop parameter
        <DllImport("gdi32.dll")> _
        Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, _
        ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
        End Function
    End Class

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        PictureBox1.Visible = False
        Button1.Text = "Загрузить полностью сайт и сохранить все рисунки на диск, не загружая их заново"
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' загружаем сайт (полностью)
        WebBrowser1.Navigate("http://www.techdays.ru/Registration.aspx")
        While Not WebBrowser1.ReadyState = WebBrowserReadyState.Complete
            Me.Text = "Загружаем сайт.. " & WebBrowser1.ReadyState.ToString
            Application.DoEvents()
        End While
        MsgBox("Страница загружена. Сейчас будем сохранять все отображённые рисунки...", MsgBoxStyle.Information, "")
        Dim allPictures As System.Windows.Forms.HtmlElementCollection = WebBrowser1.Document.GetElementsByTagName("img")
        Dim oneImage As System.Windows.Forms.HtmlElement
        Dim i As Integer = 0
        For Each oneImage In allPictures
            i += 1
            Me.Text = "Обрабатываем рисунок " & i & " из " & allPictures.Count
            ImageToFile(oneImage.DomElement, CStr(i))
            pause(100000)
        Next
        PictureBox1.Visible = False
        MsgBox("Всего сохранено: " & i & " рисунков", MsgBoxStyle.Information, "")
        Me.Text = "Всего обработано рисунков: " & allPictures.Count
    End Sub

    Sub ImageToFile(ByVal element As mshtml.IHTMLElement, ByVal nameIndex As String)
        Dim i As Integer
        Dim render As mshtml.IHTMLElementRender = element
        Dim rendElem As ScreenGrab.IHTMLElementRender = element
        Dim graphics As Graphics
        Dim hdcDestination, hdcMemory, bitmap, hOld As IntPtr
        Dim ImageFileName As String
        PictureBox1.Visible = True
        Dim tempPicBox As New PictureBox
        tempPicBox = PictureBox1
        tempPicBox.Show()
        For i = 1 To 2 'одного раза мало - не всегда сразу дорисовываются картинки с меньшего размера в больший
            tempPicBox.Width = element.clientwidth
            tempPicBox.Height = element.clientheight
            If Not (render Is Nothing) Then
                graphics = tempPicBox.CreateGraphics
                graphics.Clear(Color.White) ' стираем в один цвет - прозрачные картинки накладываются друг на друга
                Try
                    hdcDestination = graphics.GetHdc
                    rendElem.DrawToDC(hdcDestination)
                    hdcMemory = GDI32.CreateCompatibleDC(hdcDestination)
                    bitmap = GDI32.CreateCompatibleBitmap(hdcDestination, element.clientwidth, element.clientheight)
                    If Not (bitmap = IntPtr.Zero) Then
                        hOld = CType(GDI32.SelectObject(hdcMemory, bitmap), IntPtr)
                        GDI32.BitBlt(hdcMemory, 0, 0, element.clientwidth, element.clientheight, hdcDestination, 0, 0, CType(GDI32.SRCCOPY, Integer))
                        GDI32.SelectObject(hdcMemory, hOld)
                        GDI32.DeleteDC(hdcMemory)
                        graphics.ReleaseHdc(hdcDestination)
                        tempPicBox.Image = Image.FromHbitmap(bitmap)
                    End If
                Finally
                    CType(graphics, IDisposable).Dispose()
                End Try
            End If
            ImageFileName = element.nameProp
        Next
        ImageFileName = "Image" & nameIndex & ".emf"
        Dim host As String = WebBrowser1.Document.Url.Host
        Dim path As String = "c:\temp\savedImages\" & host & "\"
        If Not Directory.Exists(path) Then Directory.CreateDirectory(path)
        tempPicBox.Image.Save(path & ImageFileName, System.Drawing.Imaging.ImageFormat.Emf)
    End Sub

    Sub pause(ByVal count As Integer)
        For i = 0 To count
            Application.DoEvents()
        Next
    End Sub

End Class


Namespace ScreenGrab
    <Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown), ComVisible(True), ComImport()> _
    Interface IHTMLElementRender
        Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
        Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
    End Interface
    Public Class IEElementCapture
        Private webBrowser As IWebBrowser2 = Nothing
        Public Sub New(ByVal webBrowser As IWebBrowser2)
            Me.webBrowser = webBrowser
        End Sub
        Public Function Capture(ByRef g As Graphics) As Boolean
            If webBrowser Is Nothing Then
                Return False
            End If
            Dim htmlDocument As IHTMLDocument2 = DirectCast(webBrowser.Document, IHTMLDocument2)
            If htmlDocument IsNot Nothing Then
                Dim bodyElement As IHTMLElement = DirectCast(htmlDocument.body, IHTMLElement)
                If bodyElement IsNot Nothing Then
                    Dim render As IHTMLElementRender = DirectCast(bodyElement, IHTMLElementRender)
                    If render IsNot Nothing Then
                        Dim memDC As IntPtr = g.GetHdc()
                        render.DrawToDC(memDC)
                        Return True
                    End If
                End If
            End If
            Return False
        End Function
    End Class
End Namespace


Проверив всё сохранённое можно убедиться, что никаких дополнительных загрузок из интернета не происходит (например сохранённый рисунок защитного кода captcha абсолютно идентичен имеющемуся в браузере). Также рисунки не копируются из кэша. Всё снимается из окна браузера.

Блок "примитивной" паузы сделан для возможности визуального слежения за процессом переноса рисунков из браузера в PictureBox1.

Всё работает прекрасно с элементом WebBrowser. Однако он не поддерживает многопоточность и поэтому я пытаюсь переключиться на элемент, который поддерживает многопоточность - это myBrowser As New SHDocVw.InternetExplorer

Возлагаю большие надежды на Nord777, который никогда не оставлял мои вопросы без внимания и всегда профессионально на них отвечал.
Вот переделанный выше код под новый браузер, но не так всё гладко. Что нужно поменять, чтобы заработало?
Код: Выделить всё
Imports System
Imports System.IO
Imports System.Windows
Imports System.Windows.Forms
Imports System.Drawing.Graphics
Imports System.Runtime.InteropServices
Imports SHDocVw
Imports mshtml

Public Class Form1
    Private Class GDI32
        Public Const SRCCOPY As Integer = &HCC0020
        ' BitBlt dwRop parameter
        <DllImport("gdi32.dll")> _
        Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, _
        ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
        End Function
    End Class

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        PictureBox1.Visible = False
        Button1.Text = "Загрузить полностью сайт и сохранить все рисунки на диск, не загружая их заново"
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' загружаем сайт (полностью)
        Dim myBrowser As New SHDocVw.InternetExplorer
        myBrowser.Visible = True
        myBrowser.Navigate("http://www.techdays.ru/Registration.aspx")
        While Not myBrowser.ReadyState = WebBrowserReadyState.Complete
            Me.Text = "Загружаем сайт.. " & myBrowser.ReadyState.ToString
            Application.DoEvents()
        End While
        MsgBox("Страница загружена. Сейчас будем сохранять все отображённые рисунки...", MsgBoxStyle.Information, "")
        Dim doc As mshtml.IHTMLDocument = myBrowser.Document
        Dim allPictures As mshtml.IHTMLElementCollection = doc.getElementsByTagName("img")
        Dim oneImage As mshtml.IHTMLElement
        Dim i As Integer = 0
        For Each oneImage In allPictures
            i += 1
            Me.Text = "Обрабатываем рисунок " & i & " из " & allPictures.length
            ImageToFile(oneImage, CStr(i))
            pause(100000)
        Next
        PictureBox1.Visible = False
        MsgBox("Всего сохранено: " & i & " рисунков", MsgBoxStyle.Information, "")
        Me.Text = "Всего обработано рисунков: " & allPictures.length
    End Sub

    Sub ImageToFile(ByVal element As mshtml.IHTMLElement, ByVal nameIndex As String)
        Dim i As Integer
        Dim render As mshtml.IHTMLElementRender = element
        Dim rendElem As ScreenGrab.IHTMLElementRender = element
        Dim graphics As Graphics
        Dim hdcDestination, hdcMemory, bitmap, hOld As IntPtr
        Dim ImageFileName As String
        PictureBox1.Visible = True
        Dim tempPicBox As New PictureBox
        tempPicBox = PictureBox1
        tempPicBox.Show()
        For i = 1 To 2 'одного раза мало - не всегда сразу дорисовываются картинки с меньшего размера в больший
            tempPicBox.Width = element.clientwidth
            tempPicBox.Height = element.clientheight
            If Not (render Is Nothing) Then
                graphics = tempPicBox.CreateGraphics
                graphics.Clear(Color.White)
                Try
                    hdcDestination = graphics.GetHdc
                    rendElem.DrawToDC(hdcDestination)
                    hdcMemory = GDI32.CreateCompatibleDC(hdcDestination)
                    bitmap = GDI32.CreateCompatibleBitmap(hdcDestination, element.clientwidth, element.clientheight)
                    If Not (bitmap = IntPtr.Zero) Then
                        hOld = CType(GDI32.SelectObject(hdcMemory, bitmap), IntPtr)
                        GDI32.BitBlt(hdcMemory, 0, 0, element.clientwidth, element.clientheight, hdcDestination, 0, 0, CType(GDI32.SRCCOPY, Integer))
                        GDI32.SelectObject(hdcMemory, hOld)
                        GDI32.DeleteDC(hdcMemory)
                        graphics.ReleaseHdc(hdcDestination)
                        tempPicBox.Image = Image.FromHbitmap(bitmap)
                    End If
                Finally
                    CType(graphics, IDisposable).Dispose()
                End Try
            End If
            ImageFileName = element.nameProp
        Next
        ImageFileName = "Image" & nameIndex & ".emf"
        Dim host As String = WebBrowser1.Document.Url.Host
        Dim path As String = "c:\temp\savedImages\" & host & "\"
        If Not Directory.Exists(path) Then Directory.CreateDirectory(path)
        tempPicBox.Image.Save(path & ImageFileName, System.Drawing.Imaging.ImageFormat.Emf)
    End Sub

    Sub pause(ByVal count As Integer)
        For i = 0 To count
            Application.DoEvents()
        Next
    End Sub

End Class


Namespace ScreenGrab
    <Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown), ComVisible(True), ComImport()> _
    Interface IHTMLElementRender
        Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
        Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
    End Interface
    Public Class IEElementCapture
        Private webBrowser As IWebBrowser2 = Nothing
        Public Sub New(ByVal webBrowser As IWebBrowser2)
            Me.webBrowser = webBrowser
        End Sub
        Public Function Capture(ByRef g As Graphics) As Boolean
            If webBrowser Is Nothing Then
                Return False
            End If
            Dim htmlDocument As IHTMLDocument2 = DirectCast(webBrowser.Document, IHTMLDocument2)
            If htmlDocument IsNot Nothing Then
                Dim bodyElement As IHTMLElement = DirectCast(htmlDocument.body, IHTMLElement)
                If bodyElement IsNot Nothing Then
                    Dim render As IHTMLElementRender = DirectCast(bodyElement, IHTMLElementRender)
                    If render IsNot Nothing Then
                        Dim memDC As IntPtr = g.GetHdc()
                        render.DrawToDC(memDC)
                        Return True
                    End If
                End If
            End If
            Return False
        End Function
    End Class
End Namespace


В следующем блоке выскакивает ошибка:
Sub ImageToFile(ByVal element As mshtml.IHTMLElement, ByVal nameIndex As String)
Dim i As Integer
Dim render As mshtml.IHTMLElementRender = element
Dim rendElem As ScreenGrab.IHTMLElementRender = element
Dim graphics As Graphics
...
Unable to cast COM object of type 'mshtml.HTMLImgClass' to interface type 'mshtml.IHTMLElementRender'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{3050F669-98B5-11CF-BB82-00AA00BDCE0B}' failed due to the following error: Интерфейс не поддерживается (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
Последний раз редактировалось euroflock 05.05.2009 (Вт) 9:39, всего редактировалось 1 раз.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 04.05.2009 (Пн) 23:47

Что нужно поменять, чтобы заработало?
Систему :D
У меня твой код работает.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 05.05.2009 (Вт) 9:20

euroflock я тебя обманул, код действительно не работает.
Оказывается я скопировал первый участок кода вместо второго.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 05.05.2009 (Вт) 9:28

Nord777 писал(а):
Что нужно поменять, чтобы заработало?
Систему :D
У меня твой код работает.

Да, первый код - полностью рабочий.
Второй код выдаёт ошибку...

(я уже крутил-мутил и так и эдак, но пока ничего не получается, может что-то нужно поменять в моём Namespace ScreenGrab, на Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b") которого указывает ошибка)

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 05.05.2009 (Вт) 12:43

А конечная цель какая? Быстро загружать картинки с нескольких сайтов?
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 05.05.2009 (Вт) 14:00

Nord777 писал(а):А конечная цель какая? Быстро загружать картинки с нескольких сайтов?

Касательно этого приложения у каждого может быть своя цель (т.е. применить можно куда угодно). Главная задача - не загружать заново уже загруженные и отображённые в браузере рисунки при необходимости их сохранения. Также, касательно прикладных задач, целью может быть однозначная идентификация рисунка captcha (который не помещается ни в кэш ни в резервное хранилище) для текущей сессии. Ещё одно из возможных применений - сохранение понравившейся страницы на диск полностью, но без дополнительных закачек из сети и т.п.

Вопросов относительно поставленной задачи в сети задаётся очень много и на разных языках, но нигде нет на эти вопросы удовлетворительных ответов (одни предлагают заново выкачивать из сети разными способами, другие предлагают сохранять скриншот всего содержимого, совсем не обращая внимания на поставленный вопрос относительно сохранения конкретного рисунка, который, как например captcha, при очередной загрузке из сети меняется). Также встречается море вопросов по поводу программной реализации эмуляции правого клика на рисунке в браузере с целью осуществить команду "сохранить рисунок как...", но лично я не нашёл ни одного ответа (кроме реализации возможности сохранения всей страницы, с рисунками, скриптами и новыми закачками из сети). Почему-то разработчики скрывают это от большинства из нас, или мы просто не умеем пользоваться MSDN.

Я же привожу полностью работоспособный код, работающий во встроенном WebBrowser-e. А лично моя цель (во всяком случае сейчас) - это добиться выполнения главной задачи в мультипоточном режиме, который не поддерживает WebBrowser.

myBrowser As New SHDocVw.InternetExplorer очень привлекательная вещь, почти полностью управляема, но без реализации главной задачи она будет для меня бесполезна.
Последний раз редактировалось euroflock 05.05.2009 (Вт) 14:14, всего редактировалось 1 раз.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 05.05.2009 (Вт) 14:13

Я не знаю, как решить твою задачу теми методами, которые используешь ты.

это добиться выполнения главной задачи в мультипоточном режиме
А какая тебе разница: асинхронность или мультипоточность?
Посмотри пример.
Вложения
webBrowser.zip
(94.66 Кб) Скачиваний: 198
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 05.05.2009 (Вт) 14:49

Nord777 писал(а):Я не знаю, как решить твою задачу теми методами, которые используешь ты.

Очень жаль. Я всё же недеялся, что получится...

Nord777 писал(а):А какая тебе разница: асинхронность или мультипоточность?

Асинхронная последовательность или синхронная параллельность при выполнении например очередных 20 задач из общего списка в 10 тысяч. Что мне стоит выбрать? Конечно, если не получится реализовать задачу в независимой мультипоточности, то буду смотреть на асинхронность.. но смотреть буду "искоса".

Nord777 писал(а):Посмотри пример.

Пример как всегда - супер! Я и не сомневался. Тааакое обрезание (даже без API), и всё работает - большое спасибо. Никак не пойму зачем, почему и когда применяются DirectCast, TryCast и т.п., но дело не в этом... может ещё не всё потеряно? Я могу ещё хоть немного надеяться?

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 05.05.2009 (Вт) 15:33

Nord777 писал(а):А какая тебе разница: асинхронность или мультипоточность?

Только что сделал по примеру 20 браузеров с разными адресами... (от первого до двадцатого, запустил с указанием номера браузера)
Все браузеры запустились "асинхронно": т.е. изо всех двадцати запущенных браузеров 19-ть ждут завершения работы 20-го, затем 18-ть ждут конца работы 19-го и т.д. до первого.

Какой смысл в такой асинхронности? А что будут делать десять ожидающих браузеров, если одиннадцатый вследствие разных причин так и не сможет вернуть приложению ReadyState.Complete (или, что аналогично, Browser.DocumentCompleted)? Они так и не дождутся своей очереди быть выполненными... В этом случае больше подойдёт псевдо-многопоточность. Вот почему я занялся поиском мультипоточного (многозадачного) браузерного приложения.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 05.05.2009 (Вт) 16:54

Только что сделал по примеру 20 браузеров с разными адресами...
Ну так правильно. В обработчике события нет асинхронных действий.
Пока пишутся файлы - остальные события не обрабатываются.
Я бы ещё попробовал сделать сохранение файлов в отдельном потоке.
К примеру, при запуске приложения создаётся отдельный поток, ожидающий некоторого события(мутекса).
Этим событием будет загрузка браузером страницы.
В событии DocumentCompleted записываешь в стек имена файлов для записи на диск и сигнализируешь ожидающему потоку.
Он вытаскивает из стека очередной файл и пишет на диск. Вот как то так.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 05.05.2009 (Вт) 18:30

Nord777 писал(а):Вот как то так.
Я более склонен немного подождать с асинхронностью...
А никак нельзя хотябы программный правый клик мышки на рисунке организовать для её сохранения путём эмуляции контекстного меню "сохранить рисунок как..."? Это должно работать с многопоточным вариантом...

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 06.05.2009 (Ср) 12:57

Я более склонен немного подождать с асинхронностью...
Ждёшь пока созреет? :)
Ты пытаешься выдрать гланды через ж..., вырезав по пути апендицит. Это криво, это франкенштейн.
Ты уже неделю(или две?) паришься с этой затеей, но с каждым днем результат всё хуже и хуже.
Причем у меня содалось мнение, что ты либо чего то не вкуриваешь, либо недоговариешь.

Только что сделал по примеру 20 браузеров с разными адресами... (от первого до двадцатого, запустил с указанием номера браузера)
Все браузеры запустились "асинхронно": т.е. изо всех двадцати запущенных браузеров 19-ть ждут завершения работы 20-го, затем 18-ть ждут конца работы 19-го и т.д. до первого.
Я не запускал 20. Всего 4, но содержание лога говорит само за себя.
Посмотри внимательно на порядок следования запросов и ответов:
Код: Выделить всё
Request to http://www.microsoft.com - 01:29:05.640
Request to http://google.com - 01:29:05.656
Request to http://www.ya.ru - 01:29:05.656
Request to http://www.techdays.ru/Registration.aspx - 01:29:05.656

DocumentCompleted from www.ya.ru - 01:29:06.203
Images - 1

Saved - c:\temp\savedImages\www.ya.ru\Image1.png   01:29:06.234

DocumentCompleted from www.google.ru - 01:29:07.515
Images - 4

Saved - c:\temp\savedImages\www.google.ru\Image1.png   01:29:07.531
Saved - c:\temp\savedImages\www.google.ru\Image2.png   01:29:07.546
Saved - c:\temp\savedImages\www.google.ru\Image3.png   01:29:07.546
Saved - c:\temp\savedImages\www.google.ru\Image4.png   01:29:07.562

DocumentCompleted from www.techdays.ru - 01:29:07.968
Images - 34

Saved - c:\temp\savedImages\www.techdays.ru\Image1.png   01:29:07.984
Saved - c:\temp\savedImages\www.techdays.ru\Image2.png   01:29:08.000
Saved - c:\temp\savedImages\www.techdays.ru\Image3.png   01:29:08.015

DocumentCompleted from www.microsoft.com - 01:29:08.015

Saved - c:\temp\savedImages\www.techdays.ru\Image4.png   01:29:08.015

Images - 17

Saved - c:\temp\savedImages\www.techdays.ru\Image5.png   01:29:08.015
.....
Saved - c:\temp\savedImages\www.techdays.ru\Image34.png   01:29:08.296
Saved - c:\temp\savedImages\www.microsoft.com\Image1.png   01:29:08.312
.....
Saved - c:\temp\savedImages\www.microsoft.com\Image13.png   01:29:08.515
А это всего лишь ЗаДвадцатьМинутСделанный довесок, сохраняющий файлы в отдельном потоке.
Да, ещё одно. При попытке приведения экземпляра класса HtmlElement к интерфесу IHTMLElementRender в отдельном потоке, выбрасывается исключение, гласящее:
Unable to cast COM object of type 'xxxxx.yyyy' to interface type 'xxxx.IHTMLElementRender'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{3050F669-98B5-11CF-BB82-00AA00BDCE0B}' failed due to the following error: Интерфейс не поддерживается (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
В основном потоке - всё ок.
Так что думай сам....
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 06.05.2009 (Ср) 13:48

Nord777 писал(а):
Причем у меня содалось мнение, что ты либо чего то не вкуриваешь, либо недоговариваешь.

Вероятно скорее первое. Вроде не "недоговорил" ничего. Нужна простая реализация сохранения текущего рисунка каптчи (captcha) в локальную папку, чтобы затем показать этот рисунок пользователю вместе с текстовым полем для ручного ввода этого кода (без отображения всего содержимого заполняемой на странице формы - делаю программу рассылки объявлений на бесплатные доски объявлений).

Работа в основном потоке у меня уже давно реализована и работает, но бяка началась действительно пару недель назад, кода начал "внедрять" многопоточность.

Дело в том, что можно было бы использовать HttpWebRequest/Response, и я это также уже пробовал, но, получив из сети контент (html), пропарсив текст и загрузив нужные рисунки (captcha), я всё же не могу получить правильную реакцию страницы на тот или иной выбор "от имени пользователя", вследствии невозможности обработки скриптов. Например, загружается форма, на странице выводится только список "выберите раздел", после выбора пункта меню через ява-скрипт появляются дополнительные элементы формы, причём не всегда одинаковые, и так далее. При работе с браузером (встроенным или внешним) всё функционирует правильно, а с запросами нет. С запросами я могу только "зафиксировать" и сэмулировать аналогичную отправку, но получить необходимые правильные данные для отправки при каждом конкретном случае заполнения формы разными данными не могу.

Также пробовал (с многопоточным внешним браузером) делать остановку выполнения операций в потоке для ввода кода с отображением окна браузера, куда нужно ввести этот код, но всё становится очёнь некрасиво, когда постоянно вылазят по 20 штук отдельных окон, в которых ещё нужно найти поле ввода кода, заполнить его, да к тому же ещё умудриться не нажать на кнопку "отправить" на форме ввода, а перейти на приложение и нажать там на кнопку "продолжить", чтобы приложение само нажало на ту кнопку и отследило результат обработки...

Как делают разработчики других программ (подобных), картинки с кодами из разных браузеров (с разных потоков) собираются в отдельном окошке с полем ввода возле каждого из них, затем пользователь вводит конкретный код и приложение само передаёт данные в ждущий браузер (поток), удаляя введенную картинку с полем ввода из отдельного окошка. Это я всё сделал, при пресвдо-многопоточности всё так и происходит, но нужна реальная многопоточность.

Даже пробовал подключать Mozilla.ActiveX - не выходит.

... есть мысли, или опять я что-то недоговорил?
Последний раз редактировалось euroflock 06.05.2009 (Ср) 18:03, всего редактировалось 1 раз.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение FireFenix » 06.05.2009 (Ср) 16:52

Через парсинг страниц всё прекрасно работет, если сайты без регистрации
Для сайтов с регистрацией и т.д. - нужно ковырять куки и логиниться
Так же если сайт замудрёный, то картинка может формироваться яваскриптом, тогда нужно обрабатывать яваскрипт, и парсить результат

Я не работал с контролом веббраузера, но если он отдаёт обработанный контент, то загрузившись в него до каптчи, можно парсить наздоровье
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 06.05.2009 (Ср) 17:32

FireFenix писал(а):Так же если сайт замудрёный, то картинка может формироваться яваскриптом, тогда нужно обрабатывать яваскрипт, и парсить результат


Каким способом можно обработать ява-скрипт, не используя браузер (или ява-движок)? Как раз из-за этого (из-за невозможности обработать ява-скрипт без обработчика) и неполучается заполнять запросами "замудрёные" доски объявлений, которых ("замудрёных") в последнее время появляется всё больше и больше.


FireFenix писал(а):Я не работал с контролом веббраузера, но если он отдаёт обработанный контент, то загрузившись в него до каптчи, можно парсить наздоровье


Неужели существует доселе неведомый мне способ загрузить в браузер всё, кроме одного конкретного рисунка (или просто до этого рисунка, а затем отдельным запросом рисунок + сохранить его в локал, и только потом всё остальное)? Контрол веббраузера - это клон окна InternetExplorer 6.0, который обрабатывает все скрипты точно так же. Как в InternetExplorer загрузить не всю страницу? Точно так же, как и осуществить GET запрос с целью получить только часть ответного контента - никак.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение FireFenix » 06.05.2009 (Ср) 17:48

Ну, если всё так запущено, то как вариант разобрать нужные сайты по кусочкам и парсить нужныt части скрипта на создание линка на картинку, а не писать двиг
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 06.05.2009 (Ср) 18:31

FireFenix писал(а):Ну, если всё так запущено, то как вариант разобрать нужные сайты по кусочкам и парсить нужныt части скрипта на создание линка на картинку, а не писать двиг


Именно так поступают программы наподобие ОллСубмиттера, однако они обрабатывают только те "мудрёные" сайты, процесс обработки которых прописан в программе (например, ОллСубмиттер, настроенный для работы с форумами ПХПББ, не сможет запостить свой спам на "мудрёную" бесплатную доску объявлений, хотябы только потому, что он не настроен для её парсинга; также он не сможет запостить свой спам на другой ПХПББ форум, если его настройки отличаются от установленных по умолчанию).

Моя программа полностью имитирует поведение пользователя (человека) в реальном времени на любом сайте - вот почему мне необходима многопоточность (ну и браузер, чтобы не париться с куками, сессиями, скриптами и т.п.).

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 06.05.2009 (Ср) 22:43

Что ты можешь сказать о приведённом мною логе в предыдущем сообщении?
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 07.05.2009 (Чт) 9:24

Nord777 писал(а):Что ты можешь сказать о приведённом мною логе в предыдущем сообщении?

В логе асинхронность уже более-менее, но более детально смогу сказать, когда сам протестирую хотябы на одной двадцатке...

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 07.05.2009 (Чт) 9:47

В логе асинхронность уже более-менее
А я бы сказал, что это результат работы многопоточного приложения.
Я к чему подвожу то....
Асинхронность и многопоточность - это как слова-синонимы, звучат по разному, но означают одно и тоже.
Контрол способен выполнять асинхронные действия. Что это значит?
Это значит, что при выполнении каких то действий он не блокирует основной поток.
Если он не блокирует основной поток, в каком потоке он делает действия? Правильно, в другом.
Но при наступлении каких то событий, он сигнализирует в основной поток.
В этом он делает за тебя часть грязной работы(сам следит за потоками: cам создает, сам убивает, сам вызывает callback в нужном потоке)

но более детально смогу сказать, когда сам протестирую хотябы на одной двадцатке
Ты в курсе, что приложение с четырьмя экземплярами webbrowser откушывает около 80мб памяти и создаёт около 26 потоков?
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 07.05.2009 (Чт) 11:06

Nord777 писал(а):
Я к чему подвожу то....

Наверное мне уже давно пора сказать всем спасибо. Как всегда, придётся и дальше разбираться самостоятельно...(я сюда приходил не для пустых разговоров)

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

Асинхронность и синхронность никак нельзя ставить в один ряд с понятием многопоточности, так как они (асинхронность и синхронность) могут проявляться лишь в виде свойств многопоточности.

Если не получается слёту "приручить" многопоточный по сути клон браузера (SHdocVw), это совсем не утверждает невозможность этого. Также не справедливо упрекать в намерениях "вырвать гланды через..." (что по сути является утверждением невозможности), предлагая при этом один и тот же однопоточный (асинхронный) вариант браузера, как единственно правильный в любых случаях выход для решения проблемы "главной задачи".
Последний раз редактировалось euroflock 07.05.2009 (Чт) 14:17, всего редактировалось 1 раз.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 07.05.2009 (Чт) 14:06

Как всегда, придётся и дальше разбираться самостоятельно...
Ну чтож, это дело полезное :D
(я сюда приходил не для пустых разговоров)
Разве тут были пустые разговоры?
Тебе давали разные советы, но ты избрал для себя самый кривой способ достижения цели.
Ты изначально хотел заставить работать webbrowser в разных потоках. Тебе сказали,
что он не работает в разных потоках. Ты не поверил. Дня через 4 ты понял, что да, это действительно так.
Дальше ты начал создавать ЕЩЁ один компонент(SHDocVw.InternetExplorer),
на этот раз пытаясь уже его заставить работать в разных потоках. Тебе сказали, что это криво.
Тебе сказали и наглядно показали, что webbrowser создаёт внутри себя потоки, не тормозя при этом главный поток.
Ты ведь этого хотел? Чтобы работа нескольких экземпляров этого компонента выполнялась параллельно?
Выполняется. Запросы к сайтам идут из других потоков. Чего ещё то?
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 07.05.2009 (Чт) 14:29

Nord777 писал(а):Дальше ты начал создавать ЕЩЁ один компонент(SHDocVw.InternetExplorer),
на этот раз пытаясь уже его заставить работать в разных потоках. Тебе сказали, что это криво.


Ничего я не пытался заставлять - он сам по себе работает в разных потоках, и даже не зная моих намерений по необходимости сохранения рисунков из браузера НИКТО не смог мне даже намекнуть о его существовании как полноценного многопоточного браузера, всё время "ткнули носом" в необходимость использования именно асинхронного WebBrowser. Интересно почему? Никак не пойму слова "криво". Это неправильно или типа так никто не делает? Если бы всё задуманное сразу же заработало, то и никакой темы тут не было бы... Неужели не заметно, что эта тема не в разделе "Только для Профессионалов".

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение Nord777 » 07.05.2009 (Чт) 15:00

в необходимость использования именно асинхронного WebBrowser. Интересно почему?
Ну лично я - потому, что ты так и не смог убедить меня в необходимости использования его в разных потоках. А раз так, то незачем изобретать велосипед.
И поощрять твои(неправильные с моей точки зрения) действия мне совсем не хочется.
Никак не пойму слова "криво". Это неправильно или типа так никто не делает?
Это как тебе больше нравится.
Если прога может состоять из 100 строк, а ты пишешь 1000 - это криво.
Если прога может занимать 1мб памяти, а занимает 100мб - это криво.
Если незачем плодить лишние потоки, а ты плодишь - это криво.
Если можно обойтись встроенными методами, а ты вовсю используешь API - это криво.
Список расширяемый.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

euroflock
Обычный пользователь
Обычный пользователь
 
Сообщения: 68
Зарегистрирован: 26.02.2009 (Чт) 12:54

Re: Вот так сохраняются отображённые в браузере рисунки

Сообщение euroflock » 07.05.2009 (Чт) 23:13

Вопреки всяким разным мнениям, задача полностью решена с помощью
Код: Выделить всё
Dim myBr As AxSHDocVw.AxWebBrowser
который и многопоточность поддерживает и позволяет копировать рисунки (несмотря на то, что потрачено было достаточно много времени и целый огород кривого текста).

Тема закрыта.


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

    TopList  
cron