首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python + splinter + http: Error - httplib.ResponseNotReady

Python + splinter + http: Error - httplib.ResponseNotReady
EN

Stack Overflow用户
提问于 2017-04-25 19:10:04
回答 2查看 643关注 0票数 5

使用splinter和Python,我有两个线程正在运行,每个线程访问相同的主URL,但是访问不同的路由,例如线程一次命中:mainurl.com/threadone和线程两次命中:mainurl.com/threadtwo使用:

代码语言:javascript
复制
from splinter import Browser
browser = Browser('chrome')

但是遇到了以下错误:

代码语言:javascript
复制
Traceback (most recent call last):
  File "multi_thread_practice.py", line 299, in <module>
    main()
  File "multi_thread_practice.py", line 290, in main
    first_method(r)
  File "multi_thread_practice.py", line 195, in parser
    second_method(title, name)
  File "multi_thread_practice.py", line 208, in confirm_product
    third_method(current_url)
  File "multi_thread_practice.py", line 214, in buy_product
    browser.visit(url)
  File "/Users/joshua/anaconda/lib/python2.7/site-packages/splinter/driver/webdriver/__init__.py", line 184, in visit
    self.driver.get(url)
  File "/Users/joshua/anaconda/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 261, in get
    self.execute(Command.GET, {'url': url})
  File "/Users/joshua/anaconda/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 247, in execute
    response = self.command_executor.execute(driver_command, params)
  File "/Users/joshua/anaconda/lib/python2.7/site-packages/selenium/webdriver/remote/remote_connection.py", line 464, in execute
    return self._request(command_info[0], url, body=data)
  File "/Users/joshua/anaconda/lib/python2.7/site-packages/selenium/webdriver/remote/remote_connection.py", line 488, in _request
    resp = self._conn.getresponse()
  File "/Users/joshua/anaconda/lib/python2.7/httplib.py", line 1108, in getresponse
    raise ResponseNotReady()
httplib.ResponseNotReady

什么是错误,我应该如何处理这个问题?

事先谢谢你,一定会投票/接受答复。

代码添加了

代码语言:javascript
复制
import time
from splinter import Browser
import threading

browser = Browser('chrome')

start_time = time.time()

urlOne = 'http://www.practiceurl.com/one'
urlTwo = 'http://www.practiceurl.com/two'
baseUrl = 'http://practiceurl.com'

browser.visit(baseUrl)

def secondThread(url):
    print 'STARTING 2ND REQUEST: ' + str(time.time() - start_time)
    browser.visit(url)
    print 'END 2ND REQUEST: ' + str(time.time() - start_time)


def mainThread(url):
    print 'STARTING 1ST REQUEST: ' + str(time.time() - start_time)
    browser.visit(url)
    print 'END 1ST REQUEST: ' + str(time.time() - start_time)


def main():
    threadObj = threading.Thread(target=secondThread, args=[urlTwo])
    threadObj.daemon = True

    threadObj.start()

    mainThread(urlOne)

main()
EN

回答 2

Stack Overflow用户

发布于 2017-04-28 01:11:49

据我所知,在一个浏览器上,您要做的事情是不可能的。Splinter是在实际的浏览器上运行的,因此,同时传入许多命令会导致问题。它的作用就像人类会与浏览器交互一样(当然是自动化的)。可以打开许多浏览器窗口,但如果没有收到来自上一个请求的响应,则无法在不同的线程中发送请求。这会导致CannotSendRequest错误。因此,我建议您(如果需要使用线程)打开两个浏览器,然后使用线程通过每个浏览器发送请求。否则,这是不可能的。

这个线程在selenium上,但是信息是可传输的。Selenium多选项卡一次,这说明了你想要做的事情(我想)是不可能的。绿色勾选回答者也给出了我同样的建议。

希望这不会让你偏离轨道,并帮助你走出困境。

编辑:只是为了显示:

代码语言:javascript
复制
import time
from splinter import Browser
import threading

browser = Browser('firefox')
browser2 = Browser('firefox')

start_time = time.time()

urlOne = 'http://www.practiceurl.com/one'
urlTwo = 'http://www.practiceurl.com/two'
baseUrl = 'http://practiceurl.com'

browser.visit(baseUrl)


def secondThread(url):
    print 'STARTING 2ND REQUEST: ' + str(time.time() - start_time)
    browser2.visit(url)
    print 'END 2ND REQUEST: ' + str(time.time() - start_time)


def mainThread(url):
    print 'STARTING 1ST REQUEST: ' + str(time.time() - start_time)
    browser.visit(url)
    print 'END 1ST REQUEST: ' + str(time.time() - start_time)


def main():
    threadObj = threading.Thread(target=secondThread, args=[urlTwo])
    threadObj.daemon = True

    threadObj.start()

    mainThread(urlOne)

main()

请注意,我使用firefox是因为我没有安装chromedriver。

在浏览器打开后设置一个等待,以确保浏览器在计时器开始之前已经完全就绪,这可能是个好主意。

票数 2
EN

Stack Overflow用户

发布于 2017-04-28 09:19:59

@GenericSnake在这个问题上是正确的。为了增加一点,我强烈建议您重构代码以使用多处理库,主要是因为线程实现使用了吉尔

在CPython中,由于全局解释器锁,只有一个线程可以一次执行Python代码(尽管某些面向性能的库可能克服了这个限制)。如果您希望您的应用程序更好地利用多核计算机的计算资源,建议您使用多处理。但是,如果要同时运行多个I/O绑定任务,线程仍然是一个合适的模型。

实际上,使用多重处理的一个好处是,您可以重构代码以避免重复的方法secondThreadmainThread,例如这种方法(最后一件事,不要忘记清理您使用的资源,比如一旦完成就关闭浏览器的browser.quit() ):

代码语言:javascript
复制
import time
from splinter import Browser
from multiprocessing import Process
import os

os.environ['PATH'] = os.environ[
                         'PATH'] + "path/to/geckodriver" + "path/to/firefox/binary"

start_time = time.time()

urlOne = 'http://pythoncarsecurity.com/Support/FAQ.aspx'
urlTwo = 'http://pythoncarsecurity.com/Products/'



def url_visitor(url):
    print("url called: " + url)
    browser = Browser('firefox')
    print('STARTING  REQUEST TO: ' + url + " at "+ str(time.time() - start_time))
    browser.visit(url)
    print('END REQUEST TO: ' + url + " at "+ str(time.time() - start_time))   

def main():
    p1 = Process(target=url_visitor, args=[urlTwo])
    p2 = Process(target=url_visitor, args=[urlOne])
    p1.start()
    p2.start()
    p1.join() #join processes to the main process to see the output
    p2.join()

if __name__=="__main__":
    main()

这将给出以下输出(但时间将取决于您的系统):

代码语言:javascript
复制
url called: http://pythoncarsecurity.com/Support/FAQ.aspx
url called: http://pythoncarsecurity.com/Products/
STARTING  REQUEST TO: http://pythoncarsecurity.com/Support/FAQ.aspx at 10.763000011444092
STARTING  REQUEST TO: http://pythoncarsecurity.com/Products/ at 11.764999866485596
END REQUEST TO: http://pythoncarsecurity.com/Support/FAQ.aspx at 16.20199990272522
END REQUEST TO: http://pythoncarsecurity.com/Products/ at 16.625999927520752

编辑:多线程和Selenium的问题是浏览器实例不是线程安全的,我发现避免这个问题的唯一方法是获取url_visitor上的一个锁,但是在这种情况下,您就失去了多线程的优势。这就是为什么我认为使用多个浏览器更有益处(尽管我猜您有一些非常具体的要求),请参见下面的代码:

代码语言:javascript
复制
import time
from splinter import Browser
import threading
from threading import Lock
import os

os.environ['PATH'] = os.environ[
                         'PATH'] + "/path/to/chromedriver"

start_time = time.time()

urlOne = 'http://pythoncarsecurity.com/Support/FAQ.aspx'
urlTwo = 'http://pythoncarsecurity.com/Products/'
browser = Browser('chrome')
lock = threading.Lock()#create a lock for the url_visitor method

def init():
    browser.visit("https://www.google.fr")
    driver = browser.driver
    driver.execute_script("window.open('{0}', '_blank');") #create a new tab
    tabs = driver.window_handles


def url_visitor(url, tabs):
    with lock:
        if tabs != 0:
            browser.driver.switch_to_window(browser.driver.window_handles[tabs])
        print("url called: " + url)
        print('STARTING  REQUEST TO: ' + url + " at "+ str(time.time() - start_time))
        browser.visit(url)
        print('END REQUEST TO: ' + url + " at "+ str(time.time() - start_time))
        browser.quit()


def main():
    p1 = threading.Thread(target=url_visitor, args=[urlTwo, 0])
    p2 = threading.Thread(target=url_visitor, args=[urlOne, 1])
    p1.start()
    p2.start()

if __name__=="__main__":
    init() #create a browser with two tabs
    main()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43619022

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档