iT邦幫忙

0

請教一下關於python中的playwright這是什麼原因會報錯?瀏覽器已被關閉?

  • 分享至 

  • xImage

先上代碼.
代碼1沒問題可以正常運行
代碼2如果用到browser.close()就會報錯
playwright._impl._errors.Error: Event loop is closed! Is Playwright already stopped?
我觀察Windows進程代碼2中的chromium在還沒執行到browser.close()時就真的已經被關閉了
這是為什麼呢?
代碼1

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()

    page.goto('https://tw.yahoo.com/')
    print("Page title:", page.title())
    input("..")
    browser.close()
    if not browser.is_connected():
        print("浏览器已经关闭")
    else:
        print("浏览器仍然打开")

代碼2

import time
from playwright.sync_api import sync_playwright
mode = 1  # 1.爬取主題列表 2.爬取封面.發帖時間.磁力連結
with sync_playwright() as p:
    #browser = p.chromium.launch(headless=False)
    browser = p.chromium.launch()#不顯示瀏覽器
    page = browser.new_page()
    if mode == 1:
        print("模式1.爬取每一頁主題列表")
        w_row = 0  # 統計總共寫入行數
        repeat = 0  # 統計本次請求共有幾個重複的主題
        for s, i in enumerate(range(2, 1, -1)):  # 從第幾頁爬到第幾頁每次頁數減1
            print(f"開始請求第{i}頁")
            page.goto('https://tw.yahoo.com/')
            page.wait_for_load_state("load")
            time.sleep(3)
            response = page.content()
            print(response)
            time.sleep(3)
input(".....")
browser.close()
if not browser.is_connected():
    print("浏览器已经关闭")
else:
    print("浏览器仍然打开")
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
froce
iT邦大師 1 級 ‧ 2024-03-07 08:34:51
最佳解答
with sync_playwright() as p:
    ...

with是python的內容管理器,當變數離開with保有的區塊後,會自動關閉。
https://blog.gtwang.org/programming/python-with-context-manager-tutorial/

離開with區塊後,p已經關閉了,browser這個依照p建立的物件當然也不存在了。

看更多先前的回應...收起先前的回應...
fdfanmo iT邦新手 5 級 ‧ 2024-03-07 09:22:42 檢舉

感謝froce大大第一時間出來幫忙我解答.
實在太感謝您了.
這個代碼其實是chatgtp幫我寫的
原來是這樣.
所以第一個代碼沒問題是因為他把browser.close()寫在P裡面
所以沒生發錯誤.
那我還想請教如果是這樣那是否只要寫with sync_playwright() as p
browser.close()根本不用下這個命令
這樣子會有什麼不同嗎?
因為瀏覽器一樣是會被關閉掉.
只是一個是由python的任務管理器關閉
一個是用browser.close()命令關閉
這樣會有差異嗎?

froce iT邦大師 1 級 ‧ 2024-03-07 09:33:49 檢舉

在這個例子應該不會有啥差異。

但一些沒去實作 enterexit 方法的物件,這樣用就會有差了,因為沒得調用正常的資源分配,這要看code去做處理。

fdfanmo iT邦新手 5 級 ‧ 2024-03-07 11:02:38 檢舉

感謝froce大師的幫忙解答.這樣我懂了
另外請問是不是我只要是在with sync_playwright() as p:
內的程式碼都不應該使用到time.sleep(5)而是應該是應該使用page.wait_for_timeout()來實現等待.
我的意思是假如
with sync_playwright() as p:
所有操作瀏覽器動作中如果需要等待當然使用
page.wait_for_timeout(3000)
但是如果在這裡面有一些操作excel的循環操作需要等待時間
這個時候應該用time.sleep(5)還是要用page.wait_for_timeout(5000)呢?

froce iT邦大師 1 級 ‧ 2024-03-07 12:03:21 檢舉

我不是大師,大師這頭銜在這只是聊的時間比較多,我也不在意頭銜。

time.sleep(5)還是要用page.wait_for_timeout(5000)

打個簡單的比喻,你覺得原廠套件通常問題比較少,還是第三方套件?

time.sleep在python中只能用於同步(sync)程式的狀況下,對於異步(async)的話要用專用的asyncio.sleep去取代,現在寫這種網路爬蟲,為了效率基本上離不開異步程序了,這種框架尤其如此(畢竟bench mark丟出來就很難看了)。
所以通常框架會想辦法自己包去符合需求。

另外,我會對所有的初學者都說這句話。
寫程式請你等到你有點sense了以後,再用GPT,有問題先去google、去看 stack overflow、去看官方文件、甚至學著看原始碼,要不然你不會進步。

fdfanmo iT邦新手 5 級 ‧ 2024-03-07 13:53:48 檢舉

謝謝froce大師.對我來說你懂得這麼多就是大師了.
程式本身對我來說難度真的很高.
尤其是本身工作外沒有太多時間去做這方面的實踐.
你說到的部分我會繼續去多看一些教學充實自己的知識的.

我要發表回答

立即登入回答