95088


以下のコードでStreamlit上にrequests-htmlを用いたスクレイピング結果を表示したいのですが、エラーが表示されます。

Python及びスクレイピング等初心者で、どうやらStreamlit上で非同期処理を動かす上での問題であるように思われますが、解決の糸口が見えていない状態です。

最終的には、動的サイトのスクレイピング結果をStreamlit上に表示することを目指しており、可能であればrequests-
htmlライブラリを使用して進めたいと考えています。  
解決に向けた方法等ご教示いただければ幸いです。

**エラーメッセージ:**

[code]

    File "C:\Users\...\venv\lib\site-packages\streamlit\runtime\scriptrunner\script_runner.py", line 565, in _run_script
        exec(code, module.__dict__)
    File "C:\Users\...\test_pyppeteer.py", line 30, in <module>
        main()
    File "C:\Users\...\test_pyppeteer.py", line 15, in main
        response.html.render()
    File "C:\Users\...\venv\lib\site-packages\requests_html.py", line 586, in render
        self.browser = self.session.browser  # Automatically create a event loop and browser
    File "C:\Users\...\venv\lib\site-packages\requests_html.py", line 727, in browser
        self.loop = asyncio.get_event_loop()
    File "C:\Users\...\Python\Python310\lib\asyncio\events.py", line 656, in get_event_loop
        raise RuntimeError('There is no current event loop in thread %r.'
    
[/code]

**現状のコード:**

[code]

    import streamlit as st
    from requests_html import HTMLSession
    from bs4 import BeautifulSoup
    
    def main():
        st.title('Web Scraping App')
    
        url = st.text_input('Enter URL')
        if url:
            if st.button('Get HTML'):
                st.write(f"Start fetching HTML from {url}...")
                
                session = HTMLSession()
                response = session.get(url)
                response.html.render()
                html = response.text
    
                soup = BeautifulSoup(html, 'html.parser')
                st.write(f'Site Title: {soup.title.string}') 
    
                paragraphs = soup.find_all('p')
                for paragraph in paragraphs:
                    st.write(paragraph.text)
    
    
    if __name__ == '__main__':
        main()
    
[/code]


CC BY-SA 4.0
2023-06-01T07:34:37.293
95058
2023-06-03T10:26:01.610
2023-06-01T11:49:54.040
3060
58549
question
python web-scraping
Streamlit上でrequests-htmlを用いたスクレイピングができない


[Requests-HTML](https://requests.readthedocs.io/projects/requests-
html/en/latest/) が内部で使用している(らしい) pyppeteer

  * (元の)Puppeteer は Chromium をヘッドレスモード動かし, アプリから操作するパッケージで
  * [Requests](https://requests.readthedocs.io/en/latest/) などと異なり JavaScriptを動かせる

ですがその仕組み上, Chromium とのプロセス間通信(と思しきものと), Streamlit で衝突が起きてる模様

非同期処理で行えば, (本来なら)大丈夫だと思われます  
(Streamlit 使わず Pythonから実行できれば, Streamlit 移行も可能なはず)

[code]

    import asyncio
    # import streamlit as st
    # from requests_html import HTMLSession
    from requests_html import AsyncHTMLSession
    from bs4 import BeautifulSoup
    
    async def main():
        print('Web Scraping App')
        url = input('Enter URL')
        if url:
            if True:    # st.button('Get HTML'):
                print(f"Start fetching HTML from {url}...")
    
                with AsyncHTMLSession() as session:
                    r = await session.get(url)
                    await r.html.arender(sleep=1, keep_page=True)
                    html = r.text
                    r.close()
    
                soup = BeautifulSoup(html, 'html.parser')
                print(f'Site Title: {soup.title.string}')
    
                paragraphs = soup.find_all('p')
                for paragraph in paragraphs:
                    print(paragraph.text)
    
    if __name__ == '__main__':
        asyncio.run(main())    # main()
    
[/code]

けれど, 終了時に問題が発生します (たぶんこれだと思われ)  
[atexit printing SystemExit exception and traceback
#103512](https://github.com/python/cpython/issues/103512)

* * *

手段？として考えられるのは

  * `render()` を諦める
  * 上記問題の解決を待ち, Streamlit へ移行する
  * Requests + [pyppeteer](https://github.com/pyppeteer/pyppeteer) を独自に扱う 
    * pyppeteer は長くメンテされてなさそうなので [Playwright](https://playwright.dev/) を利用する

などです


CC BY-SA 4.0
2023-06-03T10:26:01.610
95088
2023-06-03T10:26:01.610
43025
95058
answer