使用splinter和Python,我有两个线程正在运行,每个线程访问相同的主URL,但是访问不同的路由,例如线程一次命中:mainurl.com/threadone和线程两次命中:mainurl.com/threadtwo使用:
from splinter import Browser
browser = Browser('chrome')但是遇到了以下错误:
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什么是错误,我应该如何处理这个问题?
事先谢谢你,一定会投票/接受答复。
代码添加了
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()发布于 2017-04-28 01:11:49
据我所知,在一个浏览器上,您要做的事情是不可能的。Splinter是在实际的浏览器上运行的,因此,同时传入许多命令会导致问题。它的作用就像人类会与浏览器交互一样(当然是自动化的)。可以打开许多浏览器窗口,但如果没有收到来自上一个请求的响应,则无法在不同的线程中发送请求。这会导致CannotSendRequest错误。因此,我建议您(如果需要使用线程)打开两个浏览器,然后使用线程通过每个浏览器发送请求。否则,这是不可能的。
这个线程在selenium上,但是信息是可传输的。Selenium多选项卡一次,这说明了你想要做的事情(我想)是不可能的。绿色勾选回答者也给出了我同样的建议。
希望这不会让你偏离轨道,并帮助你走出困境。
编辑:只是为了显示:
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。
在浏览器打开后设置一个等待,以确保浏览器在计时器开始之前已经完全就绪,这可能是个好主意。
发布于 2017-04-28 09:19:59
@GenericSnake在这个问题上是正确的。为了增加一点,我强烈建议您重构代码以使用多处理库,主要是因为线程实现使用了吉尔。
在CPython中,由于全局解释器锁,只有一个线程可以一次执行Python代码(尽管某些面向性能的库可能克服了这个限制)。如果您希望您的应用程序更好地利用多核计算机的计算资源,建议您使用多处理。但是,如果要同时运行多个I/O绑定任务,线程仍然是一个合适的模型。
实际上,使用多重处理的一个好处是,您可以重构代码以避免重复的方法secondThread和mainThread,例如这种方法(最后一件事,不要忘记清理您使用的资源,比如一旦完成就关闭浏览器的browser.quit() ):
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()这将给出以下输出(但时间将取决于您的系统):
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上的一个锁,但是在这种情况下,您就失去了多线程的优势。这就是为什么我认为使用多个浏览器更有益处(尽管我猜您有一些非常具体的要求),请参见下面的代码:
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()https://stackoverflow.com/questions/43619022
复制相似问题