最近、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】 ロケーター戦略 | セレン