如何从 Ktor 运行 Python 脚本 (Scrapy)

How to Run Python Script (Scrapy) From Ktor

我想做什么:

  1. Android 应用程序 (ADMIN) 从用户那里获取职位并使用 Scrapy (Python) 获取所有与之相关的职位,这些职位通过 API.

  2. Android 通过API.

    从数据库中获取所有数据的应用程序(客户端)

问题: 我一直在思考如何将我的 python 脚本与 Ktor 连接。

一些代码更清晰:

import spiders.Linkedin as linkedinSpider

linkedinSpider.main(numberOfPages=1, keywords="ios developer", location="US")

这段代码工作正常,帮助我获取数据并将其存储到数据库中,returns True 如果保存成功,否则 False。我只需要调用这个函数,所有的工作都为我完成了。

同样,

这就是我使用 KTOR 通过 API 从管理员端获取用户数据的方式。这也很好用。

            // Fetchs New Jobs.
            get("/fetch") {
                val numberOfPages = call.request.queryParameters["pages"]?.toInt() ?: 1
                val keyword = call.request.queryParameters["keyword"]
                val location = call.request.queryParameters["location"]

                if (numberOfPages < 1) {
                    call.respond(
                        status = HttpStatusCode.BadRequest,
                        message = Message(message = "Incorrect Page Number.")
                    )
                } else {
                    call.respond(
                        status = HttpStatusCode.PK,
                        message = Message(message = "Process Completed.")
                    )
                }
            }

这就是我希望代码在逻辑上工作的方式。

      // Fetch New Jobs.
            get("/fetch") {
                val numberOfPages = call.request.queryParameters["pages"]?.toInt() ?: 1
                val keyword = call.request.queryParameters["keyword"]
                val location = call.request.queryParameters["location"]

                if (numberOfPages < 1) {
                    call.respond(
                        status = HttpStatusCode.BadRequest,
                        message = Message(message = "Incorrect Page Number.")
                    )
                } else {

                    // TODO: Call Python Function Here and Check the Return Type. Something Like This.
                    if(linkedinSpider.main(numberOfPages=numberOfPages, keywords=keyword, location=location)) {
                        call.respond(
                            status = HttpStatusCode.OK,
                            message = Message(message = "Process Completed.")
                        )
                    } else {
                        call.respond(
                            status = HttpStatusCode.InternalServerError,
                            message = Message(message = "Something Went Wrong.")
                        )
                    }
                }
            }

这也是两个不同的独立项目。我是否需要合并它们或其他东西,因为当我尝试时它说在 intelliJ 中找不到 python 解释器,我将其用作 IDE for [=74] =]Ktor 开发。我还尝试配置 python 解释器,但它似乎没有用,因为它无法引用变量或 python 文件。

编辑 1

这是我试过的

    val processBuilder = ProcessBuilder(
        "python3", "main.py"
    )

    val exitCode = processBuilder.start().waitFor()

    if (exitCode == 0) {
        println("Process Completed.")
    } else {
        println("Something Went Wrong.")
    }
}

我得到的退出代码是 2。但是当我 运行 下面的代码与 exitCode 0.

一起工作时
ProcessBuilder("python3", "--version")

编辑 2

在此之后代码可以运行但不会终止,我没有输出

这是我为了模拟问题制作的kotlin文件

package com.bhardwaj.routes

import java.io.File


fun main() {
    val processBuilder = ProcessBuilder(
        "python3", "main.py", "1", "android", "india"
    )
    processBuilder.directory(File("src/main/kotlin/com/bhardwaj/"))
    val process = processBuilder.start()
    val exitCode = process.waitFor()

    if (exitCode == 0) {
        val output = String(process.inputStream.readBytes())
        print("Process Completed -> $output")
    } else {
        val output = String(process.errorStream.readBytes())
        print("Something went wrong -> $output")
    }
}

如果我 运行 在终端中使用相同的命令,它就可以工作。

python3 src/main/kotlin/com/bhardwaj/main.py 1 "android" "india"

在终端中执行 运行 相同命令后,输出为 ->

编辑 3

当我停止默认的 Scrapy 日志记录时,代码可以正常工作。 Process Builder 中的输出流似乎有一些限制。这是我所做的。

def __init__(self, number_of_pages=1, keywords="", location="", **kwargs):
        super().__init__(**kwargs)
        logging.getLogger('scrapy').setLevel(logging.WARNING)

这在开发模式下完美运行。但是我还有一些事情想讨论。 当我在 Heroku 上部署相同的内容并发出获取请求时,30-40 秒后给我 503 服务不可用。但又过了 20-30 秒后,我将数据存入数据库。这似乎很令人困惑,为什么会这样。

为了程序的流程和清晰度- 当我向 ktor 发出获取请求时,它请求 scrapy(一个 python 程序)抓取数据并将其存储在 JSON 文件。完成所有过程后,它向另一个端点发出请求,将所有数据存储到数据库中,然后 returns 并使用 call.respondktor.

问题是由于python程序向端点发出的另一个请求还是与我们一次只能处理一个进程的heroku有关。因为开发模式没有问题,即localhost url

当我停止默认的 Scrapy 日志记录时,代码有效。 Process Builder 中的输出流似乎有一些限制。这是我所做的。

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    logging.getLogger('scrapy').setLevel(logging.WARNING)