簡體   English   中英

使用 python/selenium 保存完整的網頁(包括 css,圖像)

[英]Save complete web page (incl css, images) using python/selenium

我正在使用 Python/Selenium 將基因序列提交到在線數據庫,並希望保存我返回的整頁結果。 下面是讓我得到我想要的結果的代碼:

from selenium import webdriver

URL = 'https://blast.ncbi.nlm.nih.gov/Blast.cgi?PROGRAM=blastx&PAGE_TYPE=BlastSearch&LINK_LOC=blasthome'
SEQUENCE = 'CCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACA' #'GAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGA'
CHROME_WEBDRIVER_LOCATION = '/home/max/Downloads/chromedriver' # update this for your machine

# open page with selenium
# (first need to download Chrome webdriver, or a firefox webdriver, etc)
driver = webdriver.Chrome(executable_path=CHROME_WEBDRIVER_LOCATION)
driver.get(URL)
time.sleep(5)

# enter sequence into the query field and hit 'blast' button to search
seq_query_field = driver.find_element_by_id("seq")
seq_query_field.send_keys(SEQUENCE)

blast_button = driver.find_element_by_id("b1")
blast_button.click()
time.sleep(60)

那時我有一個頁面,我可以手動單擊“另存為”並獲取一個本地文件(帶有相應的圖像/js 資產文件夾),讓我可以在本地查看整個返回的頁面(減去從動態生成的內容)向下滾動頁面,這很好)。 我以為會有一種簡單的方法來模仿 python/selenium 中的這種“另存為”功能,但還沒有找到。 下面保存頁面的代碼只是保存了 html,並沒有給我留下一個看起來像在網絡瀏覽器中一樣的本地文件,帶有圖像等。

content = driver.page_source
with open('webpage.html', 'w') as f:
    f.write(content)

我還在SO 上找到了這個問題/答案,但是接受的答案只是彈出了“另存為”框,並且沒有提供點擊它的方法(正如兩位評論者指出的那樣)

有沒有一種使用 python 將 [整頁] 另存為的簡單方法? 理想情況下,我更喜歡使用 selenium 的答案,因為 selenium 使爬行部分變得如此簡單,但如果有更好的工具來完成這項工作,我願意使用另一個庫。 或者也許我只需要在代碼中指定我想下載的所有圖像/表格,並且沒有模擬右鍵單擊“另存為”功能的快捷方式?

更新 - 跟進 James 回答的問題 所以我運行 James 的代碼來生成page.html (和相關文件)並將其與我通過手動單擊另存為獲得的 html 文件進行比較。 通過 James 的腳本保存的page.html很棒並且擁有我需要的一切,但在瀏覽器中打開時它還會顯示許多隱藏在手動保存頁面中的額外格式文本。 請參閱隨附的屏幕截圖(左側為手動保存的頁面,右側顯示帶有額外格式文本的腳本保存頁面)。 在此處輸入圖像描述

這讓我感到特別驚訝,因為 James 腳本保存的頁面的原始 html 似乎表明這些字段仍應隱藏。 請參見下面的 html,它在兩個文件中顯示相同,但有問題的文本僅出現在 James 腳本保存的瀏覽器呈現頁面中:

<p class="helpbox ui-ncbitoggler-slave ui-ncbitoggler" id="hlp1" aria-hidden="true">
These options control formatting of alignments in results pages. The
default is HTML, but other formats (including plain text) are available.
PSSM and PssmWithParameters are representations of Position Specific Scoring Matrices and are only available for PSI-BLAST. 
The Advanced view option allows the database descriptions to be sorted by various indices in a table.
</p>

知道為什么會這樣嗎?

正如您所指出的,Selenium 無法與瀏覽器的上下文菜單交互以使用Save as... ,因此您可以使用外部自動化庫(如pyautogui

pyautogui.hotkey('ctrl', 's')
time.sleep(1)
pyautogui.typewrite(SEQUENCE + '.html')
pyautogui.hotkey('enter')

此代碼通過其鍵盤快捷鍵CTRL+S打開Save as...窗口,然后通過按 Enter 將網頁及其資產保存到默認下載位置。 此代碼還將文件命名為序列,以便為其提供唯一名稱,但您可以根據您的用例更改此名稱。 如果需要,您還可以通過使用 Tab 鍵和箭頭鍵進行一些額外操作來更改下載位置。

在 Ubuntu 18.10 上測試; 根據您的操作系統,您可能需要修改發送的組合鍵。


完整代碼,其中我還添加了條件等待以提高速度:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import visibility_of_element_located
from selenium.webdriver.support.ui import WebDriverWait
import pyautogui

URL = 'https://blast.ncbi.nlm.nih.gov/Blast.cgi?PROGRAM=blastx&PAGE_TYPE=BlastSearch&LINK_LOC=blasthome'
SEQUENCE = 'CCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACA' #'GAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGAGAAGA'

# open page with selenium
# (first need to download Chrome webdriver, or a firefox webdriver, etc)
driver = webdriver.Chrome()
driver.get(URL)

# enter sequence into the query field and hit 'blast' button to search
seq_query_field = driver.find_element_by_id("seq")
seq_query_field.send_keys(SEQUENCE)

blast_button = driver.find_element_by_id("b1")
blast_button.click()

# wait until results are loaded
WebDriverWait(driver, 60).until(visibility_of_element_located((By.ID, 'grView')))

# open 'Save as...' to save html and assets
pyautogui.hotkey('ctrl', 's')
time.sleep(1)
pyautogui.typewrite(SEQUENCE + '.html')
pyautogui.hotkey('enter')

這不是一個完美的解決方案,但它可以滿足您的大部分需求。 您可以通過解析 html 並將任何加載的文件(圖像、css、js 等)下載到它們相同的相對路徑來復制“另存為完整網頁(完整)”的行為。

由於跨源請求阻塞,大多數 javascript 將無法工作。 但是內容看起來(大部分)是一樣的。

這使用requests來保存加載的文件,使用lxml來解析 html,使用os來處理路徑。

from selenium import webdriver
import chromedriver_binary
from lxml import html
import requests
import os

driver = webdriver.Chrome()
URL = 'https://blast.ncbi.nlm.nih.gov/Blast.cgi?PROGRAM=blastx&PAGE_TYPE=BlastSearch&LINK_LOC=blasthome'
SEQUENCE = 'CCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACAGCTCAAACACAAAGTTACCTAAACTATAGAAGGACA' 
base = 'https://blast.ncbi.nlm.nih.gov/'

driver.get(URL)
seq_query_field = driver.find_element_by_id("seq")
seq_query_field.send_keys(SEQUENCE)
blast_button = driver.find_element_by_id("b1")
blast_button.click()

content = driver.page_source
# write the page content
os.mkdir('page')
with open('page/page.html', 'w') as fp:
    fp.write(content)

# download the referenced files to the same path as in the html
sess = requests.Session()
sess.get(base)            # sets cookies

# parse html
h = html.fromstring(content)
# get css/js files loaded in the head
for hr in h.xpath('head//@href'):
    if not hr.startswith('http'):
        local_path = 'page/' + hr
        hr = base + hr
    res = sess.get(hr)
    if not os.path.exists(os.path.dirname(local_path)):
        os.makedirs(os.path.dirname(local_path))
    with open(local_path, 'wb') as fp:
        fp.write(res.content)

# get image/js files from the body.  skip anything loaded from outside sources
for src in h.xpath('//@src'):
    if not src or src.startswith('http'):
        continue
    local_path = 'page/' + src
    print(local_path)
    src = base + src
    res = sess.get(hr)
    if not os.path.exists(os.path.dirname(local_path)):
        os.makedirs(os.path.dirname(local_path))
    with open(local_path, 'wb') as fp:
        fp.write(res.content)  

您應該有一個名為page的文件夾,其中包含一個名為page.html的文件,其中包含您想要的內容。

受上面 FThompson 的回答的啟發,我想出了以下工具,可以為給定的頁面 url 下載完整/完整的 html(參見: https ://github.com/markfront/SinglePageFullHtml)

更新 - 跟進 Max 的建議,以下是使用該工具的步驟:

  1. 克隆項目,然后運行 maven 來構建:
$> git clone https://github.com/markfront/SinglePageFullHtml.git

$> cd ~/git/SinglePageFullHtml
$> mvn clean compile package
  1. 在目標文件夾中找到生成的 jar 文件:SinglePageFullHtml-1.0-SNAPSHOT-jar-with-dependencies.jar

  2. 在命令行中運行 jar,例如:

$> java -jar .target/SinglePageFullHtml-1.0-SNAPSHOT-jar-with-dependencies.jar <page_url>
  1. 結果文件名將有一個前綴“FP”,后跟頁面 url 的哈希碼,文件擴展名為“.html”。它可以在任一文件夾“/tmp”中找到(您可以通過 System.getProperty(" java.io.tmp")。如果沒有,請嘗試在您的主目錄或 Java 中的 System.getProperty("user.home") 中找到它)。

  2. 結果文件將是一個大而獨立的 html 文件,其中包含原始 html 源引用的所有內容(css、javascript、圖像等)。

我會建議您嘗試使用sikulix ,這是一個基於圖像的自動化工具,用於在 PC 操作系統中操作任何小部件,它支持 python 語法並使用命令行運行,這可能是解決您問題的最簡單方法。 您需要做的只是給它一個屏幕截圖,在您的 python 自動化腳本中調用 sikulix 腳本(使用 OS.system("xxxx") 或子進程...)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM