Python は Web ページ Flex によってレンダリングされた動的コンテンツをクロールします

最近、Python を使用して Web ページのコンテンツをクロールしたとき、Flex によってレンダリングされた動的なページ (下図のコース カタログのタイトルなど) に遭遇しました.このとき、マウスの右ボタンをクリックしましたが、コピーするオプションはありませんでしたメニューのリンク。

目的: 各ビデオのタイトルとリンクを取得します。

F12 を押して開発者モードに入り、Web ページを分析します。複数の flex タグがあることがわかります。この種の flex によって動的にレンダリングされる Web ページのように、ビデオ リンクは JS コードに隠され、手動でクリックして計算する必要があります。通常のリクエスト ライブラリの get を直接取得することはできません。

そこで、気が変わって、セレンの Web ドライバーを使ってブラウザーを開いて Web ページを開き、find_element の By を使用してキーワード「video」を検索し、「video」の要素を見つけられるかどうかを確認しました。

from selenium import webdriver
from selenium.webdriver.common.by import By
options = webdriver.ChromeOptions()
# 关掉密码弹窗
options.add_experimental_option("prefs", prefs)
# 关闭提示“您的连接不是私密连接”
options.add_argument("--ignore-certificate-errors")
# 关闭提示“Chrome受自动控制提示”
options.add_experimental_option('useAutomationExtension', False) 
# 关闭提示“Chrome受自动控制提示”
options.add_experimental_option('excludeSwitches', ['enable-automation']) 
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(options=options)

driver.get('......') # 打开网页url

l1=driver.find_element(By.PARTIAL_LINK_TEXT,'视频')
l2=driver.find_element(By.LINK_TEXT,'视频')

その結果、l1 であろうと l2 であろうと、エラーが報告されます。

セレンのロケートなど、別の方法を試してください。

from selenium.webdriver.support.relative_locator import locate_with, with_tag_name

l3=locate_with(By.LINK_TEXT, '视频')
l3.click()

行 l3=locate_with(...) はパスしましたが、次の文 l3.click() はエラーを報告し、click() の属性がないことを示しています。

もう一度考えて、次のように変更します。

l4=driver.find_element(l3)
l4.click()

しかし、同じエラー: selenium.common.exceptions.NoSuchElementException: Message: Cannot locate relative element with: {'link text': 'video'}

上記のすべては By.LINK_TEXT を使用して検索するキーワードを検索し、正確に検索することを望んでいますが、Flex によってレンダリングされたページでは検索できません。

find_element を By.CLASS_NAME に変更できますか?

l5=driver.find_element(By.CLASS_NAME,'item-title')
print(l5.text)

良い!今回はエラーなし。その結果、返される l5 の値は文字列です: 「テクニカル指標を理解するためのチャート (オン)」

次にクリックコマンドを送信し、うまくいけばdriver.current_urlから動画ページへのリンクを取得します。

while 1 ループを使用してトラバースし、検索でエラーが報告されてループから飛び出すまで、すべてのクラス「item-title」を検索します。

links=[]
# 参考来源:https://blog.csdn.net/saber_sss/article/details/103460706
new_location=WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME,'item-title')))

while 1:    
    try:
        # 查询窗口总数,返回一个包含所有窗口句柄handles的列表
        handles=driver.window_handles 
        title=new_location.text # 获取视频标题
        new_location.click()
        # 对比一开始获取的窗口总数,确认新窗口出现了再去切换
        WebDriverWait(driver,5).until(EC.new_window_is_opened(handles))
        # 切换到新窗口
        handles=driver.window_handles #再次获取窗口句柄handles
        #执行切换窗口操作
        driver.switch_to.window(handles[-1])
        links.append([title, driver.current_url])
        # 关闭当前窗口
        driver.close()
        # 记得还要再切换去原来的窗口
        driver.switch_to.window(handles[0])
        last_location=new_location
        # 查找下一行
        new_location=driver.find_element(locate_with(By.CLASS_NAME,'item-title').below(last_location))
    except Exception:
        break

for i in links: print(i)

操作結果:

成功したようです。ただし、元の Web ページのビデオ タイトルと比較すると、得られる結果は半分以下になります find_element コードは、1 行おきに毎回取得されます。近すぎませんか?

その後、seleniumの公式サイトでロケーターの使い方を調べてみたところ、次の行を探す下に加えて「近く」検索もあったので、下を近くに変更したところ、動画タイトルの1行目、2行目、1行目、2行目。. . だから循環。

この問題を解決するには、奇数行と偶数行を連続して検索し、最後に奇数行と偶数行の結果をマージして並べ替えます。

links=[]
l1=WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME,'item-title')))
l2=driver.find_element(locate_with(By.CLASS_NAME,'item-title').near(l1))
index=0
for locator in (l1,l2):
    while 1:    
        try:
            # 查询窗口总数,返回一个包含所有窗口句柄handles的列表
            handles=driver.window_handles 
            title=locator.text
            locator.click()
            # 对比一开始获取的窗口总数,确认新窗口出现了再去切换
            WebDriverWait(driver,5).until(EC.new_window_is_opened(handles))
            # 再次获取窗口句柄handles
            handles=driver.window_handles 
            # 新老句柄列表可以看出,新出现的句柄在列表里面排在后面
            # 执行切换窗口操作
            driver.switch_to.window(handles[-1])
            print(index, title, driver.current_url)
            links.append([index, title, driver.current_url])
            driver.close()
            # 记得还要切换回原来的窗口
            driver.switch_to.window(handles[0])
            locator=driver.find_element(locate_with(By.CLASS_NAME,'item-title').below(locator))
            # 为解决隔行,index加2
            index+=2
        except Exception:
            # 查找不到再多的元素就退出循环
            break
    # 然后处理偶数行,index设为1
    index=1
# 把结果重新排序
links=sorted(links)
for i in links: print(i)
driver.quit()

実行結果のスクリーンショット:

非常に素晴らしい!ただし、まだバグがあります。実行結果の 2 番目と 3 番目の項目が繰り返されます。これは、selenium の配置要素のエラーが原因であると推定されます。

参考元:

[1] クローラーの例 (5) ウェブページの動的コンテンツの認識

[2] selenium4_the-ruffian のブログ - CSDN blog_selenium 相対ポジショニング メソッドの新機能の相対的なポジショニングについて話す

[3]  Python+selenium ウィンドウ切り替え3つの操作_saber_sssのブログ - CSDNブログ_python wd切り替えウィンドウ

【4】 ロケーター戦略 | セレン

おすすめ

転載: blog.csdn.net/Scott0902/article/details/128863570