主頁 > 軟體設計 > 嘗試從影像URL下載影像,但我得到的是HTML

嘗試從影像URL下載影像,但我得到的是HTML

2022-02-28 16:50:32 軟體設計

我有https://art42.tumblr.com/random一個顯示一些影像的網頁的 URL。我想從該頁面下載主影像。

如果我在 Firefox(或任何其他瀏覽器)中右鍵單擊影像并選擇“在新選項卡中打開影像”,我會得到影像 (jpg)。但是,如果我嘗試使用下面的代碼下載影像,我會得到一個 HTML 檔案。

我猜這個問題與Referer有關。我嘗試將"Referer"引數設定為頁面的 URL 以及影像的 URL,但我仍然得到 HTML 而不是 JPG。

為什么我可以在 Firefox 中下載影像,但不能在我的代碼中下載?

function DownloadFile(CONST Url, Referer: String; OUT Data: TBytes; PostData: String= ''; SSL: Boolean = FALSE): Boolean;   { TESTED OK }
VAR
  Buffer     : array[0..High(Word)*4] of Byte; { Buffer of 260KB }
  TempBytes  : TBytes;
  sMethod    : string;
  BytesRead  : Cardinal;
  pSession   : HINTERNET;
  pConnection: HINTERNET;
  pRequest   : HINTERNET;
  Resource   : string;
  Root       : string;
  port       : Integer;
  flags      : DWord;
  Header     : string;
begin
  Result := FALSE;
  SetLength(Data, 0);
  pSession := InternetOpen(nil {USER_AGENT}, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

  if Assigned(pSession) then
  TRY
    { Autodetect port }
    port:= UrlExtractPort(URL);
    if port = 0 then
      if SSL
      then Port := INTERNET_DEFAULT_HTTPS_PORT
      else Port := INTERNET_DEFAULT_HTTP_PORT;

    { Root }
    Root:= UrlExtractDomainRelaxed(Url);
    pConnection := InternetConnect(pSession, PWideChar(Root), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0); { The second parameter of InternetConnect should contain only the name of the server, not the entire URL of the server-side script. }

    if Assigned(pConnection) then
    TRY
      if (PostData = '')
      then sMethod := 'GET'
      else sMethod := 'POST';

      if SSL
      then flags := INTERNET_FLAG_SECURE  OR INTERNET_FLAG_KEEP_CONNECTION
      else flags := INTERNET_SERVICE_HTTP OR INTERNET_FLAG_RELOAD; // INTERNET_FLAG_RELOAD= Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.;

      Resource := UrlExtractResourceParams(Url);  
      pRequest := HTTPOpenRequest(pConnection, PWideChar(sMethod), PWideChar(Resource), nil, nil, nil, flags, 0);  { The third parameter of HttpOpenRequest is the file name (URL) of the script }

      if Assigned(pRequest) then
        TRY
           Header:= '';
           if Referer > ''
           then Header:= Header  'Referer: '   Referer   sLineBreak;
           Header:= Header  'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0' SLineBreak;
         //Header:= Header  'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59' SLineBreak;  //  Microsoft Edge UA string
           Header:= Header  'Accept: text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8' SLineBreak;
           Header:= Header  'Accept-Language: en-us,en;q=0.5'   SLineBreak;
           Header:= Header  'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7' SLineBreak;
           Header:= Header  'Keep-Alive: 70'  SLineBreak; { In windows, default is 60 sec }
           Header:= Header  'Connection: keep-alive'  SlineBreak SLineBreak;

           HttpAddRequestHeaders(pRequest, PWideChar(Header), Length(Header), HTTP_ADDREQ_FLAG_ADD);

           Result:= HTTPSendRequest(pRequest, NIL, 0, Pointer(PostData), Length(PostData));     { The actual POST data is the forth parameter }
           if Result then
             REPEAT
              ZeroMemory(@Buffer, SizeOf(Buffer));   

              { Download bytes }
              InternetReadFile(pRequest, @Buffer, SizeOf(Buffer), BytesRead);

              { We stop? }
              if BytesRead= 0 then break;

              { Convert static array to dynamic array }
              SetLength(TempBytes, BytesRead);
              Move(Buffer[0], TempBytes[0], BytesRead);

              { Merge arrays }
              Data:= Data  TempBytes;
             UNTIL BytesRead= 0;
        FINALLY
          InternetCloseHandle(pRequest);
        END
      else
        RaiseLastOSError;

    finally
      InternetCloseHandle(pConnection);
    end;
  finally
    InternetCloseHandle(pSession);
  end;
end;

uj5u.com熱心網友回復:

在您的“接受”標題中,您沒有指定任何圖形格式。

正確配置的 Web 服務器應該以您接受的格式之一向您發送資源表示。

嘗試查看從瀏覽器發送的請求標頭(使用開發者工具 - 請參閱瀏覽器的幫助以了解如何訪問它們)。它將接受圖形格式和文本。

uj5u.com熱心網友回復:

它按預期作業:

  1. 您要求GET https://art42.tumblr.com/randomHTTP 302 Found.

  2. 該回應意味著答案中必須有一個標題Location,它指向我們應該查詢的新 URL。在我的情況下,整個標題是:

    Location: https://art42.tumblr.com/post/158825454869#_=_

  3. 該 URL 是一個新GET請求,最終以HTTP 200 OK.

  4. 該回應主要意味著我們有一些有效負載,并且標頭Content-Type應該幫助我們以正確的方式處理它。在我的情況下,整個標題是:

    Content-Type: text/html; charset=UTF-8

    這意味著它是一個包含 HTML 內容的文本檔案,以 UTF-8 編碼。這很好 - 需要決議 PDF 或 EXE 將不那么簡單。

  5. 就是這樣:一切都按預期作業。它仍然是一個網站——你甚至可以從周圍的所有文字中看到這一點。僅僅因為嵌入了一張圖片,它并不會使整個有效載荷也成為一張圖片。

如果您無法從圖片中區分網站,那么您在學習之前還有很長的路要走。Web 瀏覽器可以顯示各種媒體:將 HTML 決議為呈現的網站、各種格式的視頻和圖片、文本檔案,現在甚至是 PDF……圖片的 URL 是,當然可以在 HTML 中找到。如果您可以右鍵單擊圖片進行保存,您還可以在新選項卡中顯示它 - 該選項卡的顯示方式與您當前正在查看的網站的嵌入位置不同。https://64.media.tumblr.com/0b37315236ee5da6cb4d191ea6a14ccb/tumblr_on2uab8Anw1vb29w2o1_500.jpg

是的:您應該決議整個 HTML,注意所有遇到的情況<img src=",然后檢查這是否是您想要的圖片。幸運的是,它更容易:只需搜索<meta name="twitter:image" content="然后復制所有內容,直到" />獲得您的實際圖片 URL。


編輯:為了(不)重現 OP 的問題,此代碼已優化為按原樣運行并自動加載圖片。請注意,許多有問題的自定義已被洗掉,尤其是標題和參考者,并且格式更加一致:

uses
  wininet, jpeg;

function DownloadFile(Data: TMemoryStream): Boolean;
var
  Buffer: Array[0.. High(Word)* 4] of Byte;
  Resource, Root, sMethod: AnsiString;
  BytesRead, flags: Cardinal;
  pSession, pConnection, pRequest: HINTERNET;
  port: Word;
begin
  Result:= FALSE;
  Data.Clear;
  pSession:= InternetOpenA(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

  if Assigned(pSession) then
  try
    port:= 443;

    Root:= '64.media.tumblr.com';
    pConnection:= InternetConnectA(pSession, PAnsiChar(Root), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);

    if Assigned(pConnection) then
    try
      sMethod:= 'GET';
      flags:= INTERNET_FLAG_SECURE or INTERNET_FLAG_KEEP_CONNECTION;

      Resource:= '/0b37315236ee5da6cb4d191ea6a14ccb/tumblr_on2uab8Anw1vb29w2o1_500.jpg';
      pRequest:= HTTPOpenRequestA(pConnection, PAnsiChar(sMethod), PAnsiChar(Resource), nil, nil, nil, flags, 0);

      if Assigned(pRequest) then
      try
        Result:= HTTPSendRequestA(pRequest, nil, 0, nil, 0);
        if Result then
        repeat
          InternetReadFile(pRequest, @Buffer, SizeOf(Buffer), BytesRead);
          if BytesRead= 0 then break;
          Data.Write(Buffer[0], BytesRead);
        until FALSE;
      finally
        InternetCloseHandle(pRequest);
      end
      else RaiseLastOSError;
    finally
      InternetCloseHandle(pConnection);
    end;
  finally
    InternetCloseHandle(pSession);
  end;
end;

// Actually executing it: just add one TImage to your form
procedure TForm1.Button1Click(Sender: TObject);
var
  Data: TMemoryStream;
  j: TJpegImage;
  Head: AnsiString;
begin
  Data:= TMemoryStream.Create;
  DownloadFile(Data);
  if Data.Size> 3 then begin  // Reasonable size for picture
    Data.Position:= 0;
    SetLength(Head, 3);
    Data.Read(Head[1], 3);
    if Head= #$ff#$d8#$ff then  // Is it JFIF (aka JPG)?
    begin
      Data.Position:= 0;
      j:= TJpegImage.Create;
      try
        j.LoadFromStream(Data);
        Image1.AutoSize:= TRUE;
        Image1.Picture.Assign(j);
      except
        // Might be corrupt or its (sub) format is not supported
      end;
      j.Free;
    end;
  end;
  Data.Free;
end;

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/433774.html

標籤:德尔福 下载 http头 葡萄酒网

上一篇:Delphi-RadStudio-Android-在運行時創建一些按鈕并使用屬性值

下一篇:如何創建具有功能取消按鈕和具有默認值的能力的輸入框

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more