F #, преобразованный из кода R, не может удалить данные из сети - PullRequest
0 голосов
/ 19 марта 2020

Я пишу F # -программу для проверки (или сканирования) корейского фондового рынка и провожу некоторый анализ.

Чтобы получить данные, я должен получить токен от поставщика API.

Вот код R, который делает это хорошо.

library(httr)
library(rvest)
library(readr)

gen_otp_url =
  'http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx'
gen_otp_data = list(
  name = 'fileDown',
  filetype = 'csv',
  url = 'MKD/03/0303/03030103/mkd03030103',
  tp_cd = 'ALL',
  date = '20190607',
  lang = 'ko',
  pagePath = '/contents/MKD/03/0303/03030103/MKD03030103.jsp')
otp = POST(gen_otp_url, query = gen_otp_data) %>%
  read_html() %>%
  html_text()

Ссылаясь на фрагменты здесь: http://www.fssnip.net/a7/title/Send-HTTP-POST-request, я написал некоторый код на F #, чтобы проверить, действительно ли запрос работает.

open System
open System.Net
open System.IO

type KRXQuery = {
    name: String
    filetype: String
    url: String
    tp_cd: String
    date: String
    lang: String
    pagePath: String
}

[<EntryPoint>]
let main argv =
    let otpUrl = "http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx"

    let krxQuery = {
        name = "fileDown"
        filetype = "csv"
        url = "MKD/03/0303/03030103/mkd03030103"
        tp_cd = "ALL"
        date = "20190607"
        lang = "ko"
        pagePath = "/contents/MKD/03/0303/03030103/MKD03030103.jsp"
    }

    let myCallback (reader:StreamReader) url = 
        let html = reader.ReadToEnd()
        html      // return all the html

    let queryBuilder (p: KRXQuery) =
        "?" + ([ 
            "name=" + p.name
            "filetype=" + p.filetype
            "url=" + p.url
            "tp_cd=" + p.tp_cd
            "date=" + p.date
            "lang=" + p.lang
            "pagePath=" + p.pagePath
        ] |> String.concat "&")



    let fetchURL callback url query =
        let target = url + (queryBuilder query)
        printfn "%s" target
        let req = HttpWebRequest.Create(target)

        // let postBytes = Encoding.UTF8.GetBytes (queryBuilder query)
        // req.ContentType <- "application/x-www-form-urlencoded; charset=UTF-8";
        // req.ContentLength <- int64 postBytes.Length

        // //Write data to the request
        // let reqStream = req.GetRequestStream()
        // reqStream.Write(postBytes, 0, postBytes.Length);
        // reqStream.Close()

        use resp = req.GetResponse() 
        use stream = resp.GetResponseStream() 
        use reader = new StreamReader(stream)
        callback reader url

    let otp = fetchURL myCallback otpUrl krxQuery

    printfn "%A" otp

    0 // return an integer exit code

Но он не может прочитать токен OTP, возвращая пустую строку (длина содержимого http равна 0), которая хорошо работала в R. И он возвращает код состояния HTTP 200, что запрос каким-то образом сработал, но не смог прочитать токен.

Я потратил часы на отладку, но пока не получилось.

Буду очень признателен за вашу помощь!

Спасибо.

1 Ответ

0 голосов
/ 19 марта 2020

Я попробовал это, и мне удалось воспроизвести проблему. Одна проблема заключается в том, что вы не являетесь URL-адресом, кодирующим параметры, и реализация R делает это. Однако это по-прежнему не решает проблему.

Изменение параметров кодирования URL-адреса:

let queryBuilder (p: KRXQuery) =
    "?" + ([ 
        "name=" + p.name
        "filetype=" + p.filetype
        "url=" + HttpUtility.UrlEncode(p.url)
        "tp_cd=" + p.tp_cd
        "date=" + p.date
        "lang=" + p.lang
        "pagePath=" + HttpUtility.UrlEncode(p.pagePath)
    ] |> String.concat "&")

Есть ли у службы документация на Engli sh? Возможно, для этого требуются дополнительные HTTP-заголовки, которые R отправляет автоматически, а NET не ...

...