使用MechanicalSoup的API无法提交表单 - NoneType

时间:2018-04-19 20:36:22

标签: python mechanicalsoup

我正在使用一个python API,它使用MechanicalSoup来完成其大部分功能,突然之间,它将不再起作用。我觉得它正在使用的网站可能已经改变了什么。

以下是API的代码:

def trade(self, symbol, orderType, quantity, priceType="Market", price=False, duration=Duration.good_cancel):
        """
        Executes trades on the platform. See the readme.md file
        for examples on use and inputs. Returns True if the
        trade was successful. Else an exception will be
        raised.

        client.trade("GOOG", Action.buy, 10)
        client.trade("GOOG", Action.buy, 10, "Limit", 500)
        """

        br = self.br
        trade_page = self.fetch('/simulator/trade/tradestock.aspx')
        trade_form = trade_page.soup.select("form#orderForm")[0]

        # input symbol, quantity, etc.
        trade_form.select("input#symbolTextbox")[0]["value"] = symbol
        trade_form.select("input#quantityTextbox")[0]["value"] = str(quantity)

        # input transaction type
        [option.attrs.pop("selected", "") for option in trade_form.select("select#transactionTypeDropDown")[0]("option")]
        trade_form.select("select#transactionTypeDropDown")[0].find("option", {"value": str(orderType.value)})["selected"] = True

        # input price type
        [radio.attrs.pop("checked", "") for radio in trade_form("input", {"name": "Price"})]
        trade_form.find("input", {"name": "Price", "value": priceType})["checked"] = True

        # input duration type
        [option.attrs.pop("selected", "") for option in trade_form.select("select#durationTypeDropDown")[0]("option")]
        trade_form.select("select#durationTypeDropDown")[0].find("option", {"value": str(duration.value)})["selected"] = True

        # if a limit or stop order is made, we have to specify the price
        if price and priceType == "Limit":
            trade_form.select("input#limitPriceTextBox")[0]["value"] = str(price)

        elif price and priceType == "Stop":
            trade_form.select("input#stopPriceTextBox")[0]["value"] = str(price)

        prev_page = br.submit(trade_form, trade_page.url)
        prev_form = prev_page.soup.select("form", {"name": "simTradePreview"})
        br.submit(prev_form, prev_page.url)

        return True

这是我用以下代码实现的代码:

def buy(shares, ticker, client):
    client.trade(ticker,ita.Action.buy, shares)
...
if apred[0] -  arl[-1] > 0 and apred[1] - apred[0] > 0 and tickers[0] not in z:
        buy(ashr ,tickers[0], client) 

以下是错误消息:

Traceback (most recent call last):
  File "/Users/carson/mlTechnicalAnalysis/investopedia.py", line 146, in <module>
    schedule.run_pending()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/schedule/__init__.py", line 493, in run_pending
    default_scheduler.run_pending()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/schedule/__init__.py", line 78, in run_pending
    self._run_job(job)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/schedule/__init__.py", line 131, in _run_job
    ret = job.run()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/schedule/__init__.py", line 411, in run
    ret = self.job_func()
  File "/Users/carson/mlTechnicalAnalysis/investopedia.py", line 56, in main
    buy(ashr ,tickers[0], client)
  File "/Users/carson/mlTechnicalAnalysis/investopedia.py", line 16, in buy
    client.trade(ticker,ita.Action.buy, shares)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/InvestopediaApi/ita.py", line 240, in trade
    prev_form = prev_page.soup.select("form", {"name": "simTradePreview"})
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/bs4/element.py", line 1532, in select
    for candidate in _use_candidate_generator(tag):
TypeError: 'dict' object is not callable

我现在已经在墙上撞了几个小时了,我觉得要花两两秒的时间才弄明白。仅供参考,它是在Investopedia的股票交易模拟器上进行交易的API。

谢谢!

1 个答案:

答案 0 :(得分:1)

简而言之:你向.select()传递了太多的论据;您必须将单个CSS选择器作为字符串传递。

查看堆栈跟踪:

  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/InvestopediaApi/ita.py", line 240, in trade
    prev_form = prev_page.soup.select("form", {"name": "simTradePreview"})
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/bs4/element.py", line 1532, in select
    for candidate in _use_candidate_generator(tag):
TypeError: 'dict' object is not callable

看来你作为.select()的第二个参数传递的是dict({"name": "simTradePreview"})。显然它不是预期的。

从堆栈跟踪看来,问题soup是BeautifulSoup 4(bs4);其select does not seem接受第二个参数。但是the source确实有更多未记录的参数与默认的线索,特别是_candidate_generator,你可以使用它。