none
請問用 HttpWebRequest 與 HttpWebResponse 取回的資料, 為何會被截掉 ? RRS feed

  • 問題

  • 以下是我的 code, 寫在一個 MVC 的 CONTROLLER 的 action 內, 按下一個按鈕後會執行到 .

    url = "http://mops.twse.com.tw/mops/web/autoAction?keyword=1102";
    
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
    //request.Method = "GET";
    request.Method = "POST";
    request.Timeout = 40000;
    
    request.ContentType = "text/plain ; charset=utf-8";
    
    string responseJSON = "";
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
           using (StreamReader sr = new StreamReader(response.GetResponseStream()))
           {
               responseJSON = sr.ReadToEnd();
           }
    }

    取回的 responseJSON 中,

    與在網頁 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 用 F12 看到的 HTML 中,

    <form name='fm1' id='fm1' ..> 後面的 html 都不見了

    請問這是怎麼回事 ?  如何才能取回完整的 HTML ? 謝謝

    2018年7月23日 上午 09:08

解答

  • 不知道你有沒有注意到

    你的網址點進去時是先到你給的位置

    然後網址就會導到http://mops.twse.com.tw/mops/web/t146sb05

    其實點進去時這網站會先丟給你http://mops.twse.com.tw/mops/web/t146sb05

    這頁的html

    然後再幫你做查詢後才會再丟回 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 的結果

    他查詢是用ajax更新下面區塊的

    如果你要一樣的結果可能要研究一下他ajax的過程中傳了什麼

    然後跟他做一模一樣的動作

    • 已編輯 Homura Lin 2018年7月23日 上午 09:54
    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月23日 上午 09:47
  • 你沒特別需求的話,用 WebClient 去抓,會封鎖執行緒等到資料回傳回來後解鎖。

    用到 Stream 的,要用迴圈去讀資料。

    也就是說,當你執行 sr.ReadToEnd 時,你電腦也就只收到這些資料,所以要一直用迴圈讀。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月23日 下午 02:40
  • 如果是動態產生的網頁, 傳統的做法無法取回網頁內容, 不過可以搭配Selenium套件來取得, 請參考:

    Example of Scraping with Selenium WebDriver in C#

    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月24日 上午 12:31
  • 應該說他丟回來還不是結果

    他丟回來後還會在前端執行一段ajax得到查詢結果

    我剛剛看了一下他跑了下面這段

    <form name='fm1' id='fm1' action='/mops/web/t146sb05' method='post' onsubmit='return false;'>
    <input type='hidden' name='step' id='step' value='1' />
    <input type='hidden' name='run' id='run' value='' />
    <input type='hidden' name='firstin' id='firstin' value = '1'>
    <input type='hidden' name='co_id' id='co_id' value='1102'>
    </form>
    <script>
     setChip($$system_name,'co_id','1102');
     document.fm1.submit(); 
    </script>

    這段才是查詢後的結果

    你可以嘗試換丟這個位置

    然後丟出跟他一樣的東西看看會不會取回查詢後的結果

    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月24日 上午 02:06
  • 如果是動態網頁, 透過動態技術取得的內容和生成的HTML元素通常都不會出現在您直接取得的結果中
    • 已標示為解答 MIS110 2018年7月25日 上午 09:15
    2018年7月24日 上午 03:48
  • 如果是動態網頁, 透過動態技術取得的內容和生成的HTML元素通常都不會出現在您直接取得的結果中

    通常來說是這樣沒錯

    但是他丟回來時Ajax做完

    確實整頁又被倒到另外一頁

    所以我覺得他會丟回整頁Html

    為了確定我的假設沒錯

    我寫了程式碼確定這個假設

    以下程式碼

                var url = "http://mops.twse.com.tw/mops/web/t146sb05";
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                request.Method = "POST";
                request.Timeout = 40000;
                NameValueCollection postParams = System.Web.HttpUtility.ParseQueryString(string.Empty);
                postParams.Add("step", "1");
                postParams.Add("run", "");
                postParams.Add("firstin", "1");
                postParams.Add("co_id", "1102");
                byte[] byteArray = Encoding.UTF8.GetBytes(postParams.ToString());
                request.ContentType = "text/plain ; charset=utf-8";
    
                using (Stream reqStream = request.GetRequestStream())
                {
                    reqStream.Write(byteArray, 0, byteArray.Length);
                }
    
                string responseJSON = "";
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                    {
                        responseJSON = sr.ReadToEnd();
                    }
                }
    

    驗證的結果跟我想得是一樣的

    他會丟回完整的一頁Html


    • 已編輯 Homura Lin 2018年7月24日 上午 06:12
    • 已標示為解答 MIS110 2018年7月25日 上午 09:15
    2018年7月24日 上午 06:10
  • Homura Lin 的方法確實可以取到完整的 html. 感謝您撥空協助測試

    但想再請教, 您是如何確定 丟回來後還會在前端執行一段ajax得到查詢結果 ?

    我用 http://mops.twse.com.tw/mops/web/t146sb05 不輸入任何值去看,

    跟我輸入完 "1102" 或使用 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 作為 url

    確實 <form> element 的個數會不同, 但請問要如何確定是哪一個 <form> 是還會在前端執行的ajax ?

    謝謝

    跟我第2次回復的那段js有關

    <script>
     setChip($$system_name,'co_id','1102');
     document.fm1.submit(); 
    </script>

    document.fm1.submit()這段

    造成一進去就提交form了

    這邊要修正一下應該只是單純form提交

    沒用到ajax

    手動查詢時才有用到

    要確定哪個form的話

    使用F12開發者工具去看

    Ctrl+shift+c 指到搜尋那個區塊

    最近那個form就是



    • 已編輯 Homura Lin 2018年7月24日 上午 08:59 修正
    • 已標示為解答 MIS110 2018年7月25日 上午 09:17
    2018年7月24日 上午 08:45
  • 原因可參考這篇:

    [.Net] 資料接收的常識

    程式碼可直接看 MSDN 的範例:

    https://msdn.microsoft.com/zh-tw/library/system.net.httpwebresponse.getresponsestream.aspx

    舉例:

    假設對方10秒回傳 10MB 的資料量,當你在 0.1 秒執行到 sr.ReadToEnd 時,這時只收到了 100kb 的內容,你讀完就關閉 Stream ,剩下的 9.9 MB 就沒了。

    ReadToEnd 是該 Stream 當時的 End ,而非 10 秒後未知長度的 End 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 MIS110 2018年7月25日 上午 09:17
    2018年7月24日 下午 03:21

所有回覆

  • 不知道你有沒有注意到

    你的網址點進去時是先到你給的位置

    然後網址就會導到http://mops.twse.com.tw/mops/web/t146sb05

    其實點進去時這網站會先丟給你http://mops.twse.com.tw/mops/web/t146sb05

    這頁的html

    然後再幫你做查詢後才會再丟回 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 的結果

    他查詢是用ajax更新下面區塊的

    如果你要一樣的結果可能要研究一下他ajax的過程中傳了什麼

    然後跟他做一模一樣的動作

    • 已編輯 Homura Lin 2018年7月23日 上午 09:54
    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月23日 上午 09:47
  • 你沒特別需求的話,用 WebClient 去抓,會封鎖執行緒等到資料回傳回來後解鎖。

    用到 Stream 的,要用迴圈去讀資料。

    也就是說,當你執行 sr.ReadToEnd 時,你電腦也就只收到這些資料,所以要一直用迴圈讀。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月23日 下午 02:40
  • 如果是動態產生的網頁, 傳統的做法無法取回網頁內容, 不過可以搭配Selenium套件來取得, 請參考:

    Example of Scraping with Selenium WebDriver in C#

    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月24日 上午 12:31
  • 不知道你有沒有注意到

    你的網址點進去時是先到你給的位置

    然後網址就會導到http://mops.twse.com.tw/mops/web/t146sb05

    其實點進去時這網站會先丟給你http://mops.twse.com.tw/mops/web/t146sb05

    這頁的html

    然後再幫你做查詢後才會再丟回 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 的結果

    他查詢是用ajax更新下面區塊的

    如果你要一樣的結果可能要研究一下他ajax的過程中傳了什麼

    然後跟他做一模一樣的動作

     感謝您的回覆, 不過, 我有一點疑問的是, 既然丟回來的已經是結果的網頁, 如果我直接取結果網頁的內容, 還是會被截掉嗎 ? 謝謝
    2018年7月24日 上午 01:20
  • 應該說他丟回來還不是結果

    他丟回來後還會在前端執行一段ajax得到查詢結果

    我剛剛看了一下他跑了下面這段

    <form name='fm1' id='fm1' action='/mops/web/t146sb05' method='post' onsubmit='return false;'>
    <input type='hidden' name='step' id='step' value='1' />
    <input type='hidden' name='run' id='run' value='' />
    <input type='hidden' name='firstin' id='firstin' value = '1'>
    <input type='hidden' name='co_id' id='co_id' value='1102'>
    </form>
    <script>
     setChip($$system_name,'co_id','1102');
     document.fm1.submit(); 
    </script>

    這段才是查詢後的結果

    你可以嘗試換丟這個位置

    然後丟出跟他一樣的東西看看會不會取回查詢後的結果

    • 已標示為解答 MIS110 2018年7月25日 上午 09:16
    2018年7月24日 上午 02:06
  • 如果是動態生成的網頁, 您取到的可能是下載到瀏覽器的內容, 而這這些己下載的內容包含的程式碼另外取得的內容通常都取不到, 要用另外的技巧
    2018年7月24日 上午 03:47
  • 如果是動態網頁, 透過動態技術取得的內容和生成的HTML元素通常都不會出現在您直接取得的結果中
    • 已標示為解答 MIS110 2018年7月25日 上午 09:15
    2018年7月24日 上午 03:48
  • 如果是動態網頁, 透過動態技術取得的內容和生成的HTML元素通常都不會出現在您直接取得的結果中

    通常來說是這樣沒錯

    但是他丟回來時Ajax做完

    確實整頁又被倒到另外一頁

    所以我覺得他會丟回整頁Html

    為了確定我的假設沒錯

    我寫了程式碼確定這個假設

    以下程式碼

                var url = "http://mops.twse.com.tw/mops/web/t146sb05";
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                request.Method = "POST";
                request.Timeout = 40000;
                NameValueCollection postParams = System.Web.HttpUtility.ParseQueryString(string.Empty);
                postParams.Add("step", "1");
                postParams.Add("run", "");
                postParams.Add("firstin", "1");
                postParams.Add("co_id", "1102");
                byte[] byteArray = Encoding.UTF8.GetBytes(postParams.ToString());
                request.ContentType = "text/plain ; charset=utf-8";
    
                using (Stream reqStream = request.GetRequestStream())
                {
                    reqStream.Write(byteArray, 0, byteArray.Length);
                }
    
                string responseJSON = "";
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                    {
                        responseJSON = sr.ReadToEnd();
                    }
                }
    

    驗證的結果跟我想得是一樣的

    他會丟回完整的一頁Html


    • 已編輯 Homura Lin 2018年7月24日 上午 06:12
    • 已標示為解答 MIS110 2018年7月25日 上午 09:15
    2018年7月24日 上午 06:10
  • Homura Lin 的方法確實可以取到完整的 html. 感謝您撥空協助測試

    但想再請教, 您是如何確定 丟回來後還會在前端執行一段ajax得到查詢結果 ?

    我用 http://mops.twse.com.tw/mops/web/t146sb05 不輸入任何值去看,

    跟我輸入完 "1102" 或使用 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 作為 url

    確實 <form> element 的個數會不同, 但請問要如何確定是哪一個 <form> 是還會在前端執行的ajax ?

    謝謝

    2018年7月24日 上午 08:03
  • 如果是動態產生的網頁, 傳統的做法無法取回網頁內容, 不過可以搭配Selenium套件來取得, 請參考:

    Example of Scraping with Selenium WebDriver in C#

    感謝您提供的資訊, 這個套件還蠻好用的,

    可以取到動態產生網頁的Text資料, 但是好像取不到後來動態產生網頁的html 碼?

    我有去 https://groups.google.com/forum/#!topic/selenium-users 問如何取得 html ,

    但取回的 html 還是無法包含動態產生網頁的部分

    奇怪的是可以取到動態產生網頁的部分的 Text 值

    2018年7月24日 上午 08:09
  • 你沒特別需求的話,用 WebClient 去抓,會封鎖執行緒等到資料回傳回來後解鎖。

    用到 Stream 的,要用迴圈去讀資料。

    也就是說,當你執行 sr.ReadToEnd 時,你電腦也就只收到這些資料,所以要一直用迴圈讀。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?


    想請教, 我是不能用 sr.ReadToEnd 去讀, 那請問要用 StreamReader 的什麼方法在迴圈中去讀 ? 謝謝
    2018年7月24日 上午 08:11
  • Homura Lin 的方法確實可以取到完整的 html. 感謝您撥空協助測試

    但想再請教, 您是如何確定 丟回來後還會在前端執行一段ajax得到查詢結果 ?

    我用 http://mops.twse.com.tw/mops/web/t146sb05 不輸入任何值去看,

    跟我輸入完 "1102" 或使用 http://mops.twse.com.tw/mops/web/autoAction?keyword=1102 作為 url

    確實 <form> element 的個數會不同, 但請問要如何確定是哪一個 <form> 是還會在前端執行的ajax ?

    謝謝

    跟我第2次回復的那段js有關

    <script>
     setChip($$system_name,'co_id','1102');
     document.fm1.submit(); 
    </script>

    document.fm1.submit()這段

    造成一進去就提交form了

    這邊要修正一下應該只是單純form提交

    沒用到ajax

    手動查詢時才有用到

    要確定哪個form的話

    使用F12開發者工具去看

    Ctrl+shift+c 指到搜尋那個區塊

    最近那個form就是



    • 已編輯 Homura Lin 2018年7月24日 上午 08:59 修正
    • 已標示為解答 MIS110 2018年7月25日 上午 09:17
    2018年7月24日 上午 08:45
  • 原因可參考這篇:

    [.Net] 資料接收的常識

    程式碼可直接看 MSDN 的範例:

    https://msdn.microsoft.com/zh-tw/library/system.net.httpwebresponse.getresponsestream.aspx

    舉例:

    假設對方10秒回傳 10MB 的資料量,當你在 0.1 秒執行到 sr.ReadToEnd 時,這時只收到了 100kb 的內容,你讀完就關閉 Stream ,剩下的 9.9 MB 就沒了。

    ReadToEnd 是該 Stream 當時的 End ,而非 10 秒後未知長度的 End 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 MIS110 2018年7月25日 上午 09:17
    2018年7月24日 下午 03:21
  • 感謝各位不吝回覆說明指教, 跟各位學了很多技巧與觀念, 謝謝大家
    2018年7月25日 上午 09:18