Сохраните полную веб-страницу (включая CSS, изображения), используя python / selenium - PullRequest
0 голосов
/ 11 декабря 2018

Я использую 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)

На этом этапе у меня есть страница, на которой я могу вручную нажать «Сохранить как» и получить локальный файл (с соответствующей папкойресурсы image / js), которые позволяют мне просматривать всю возвращаемую страницу локально (за исключением содержимого, которое генерируется динамически при прокрутке вниз по странице, что нормально).Я предполагал, что будет простой способ имитировать эту функцию «сохранить как» в python / selenium, но не нашел ее.Код для сохранения страницы ниже просто сохраняет html и не оставляет мне локальный файл, который выглядит как в веб-браузере, с изображениями и т. Д.

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

Я также нашел этот вопрос / ответ по SO , но принятый ответ просто вызывает поле «сохранить как» и не предоставляет способ щелкнуть по нему (как указывают два комментария)

Есть липростой способ «сохранить [полную страницу] как» с использованием Python?В идеале я бы предпочел ответ с использованием селена, поскольку селен делает процесс сканирования настолько простым, но я открыт для использования другой библиотеки, если есть лучший инструмент для этой работы.Или, может быть, мне просто нужно указать все изображения / таблицы, которые я хочу загрузить, в коде, и нет ярлыка для эмуляции щелчка правой кнопкой мыши на функции «сохранить как»?

ОБНОВЛЕНИЕ - ответьте на вопрос Джеймса'answer Итак, я запустил код Джеймса, чтобы сгенерировать page.html (и связанные с ним файлы), и сравнил его с HTML-файлом, который я получил вручную, нажав "Сохранить как".page.html, сохраненный с помощью сценария Джеймса, великолепен и имеет все, что мне нужно, но при открытии в браузере он также показывает много дополнительного форматирующего текста, который скрыт на странице сохранения вручную.См. Прикрепленный снимок экрана (страница, сохраненная вручную слева, страница, сохраненная сценарием, с дополнительным форматирующим текстом, показанным справа).enter image description here

Это особенно удивляет меня, поскольку необработанный HTML-код страницы, сохраненной сценарием Джеймса, указывает на то, что эти поля все еще должны быть скрыты.См., Например, приведенный ниже HTML-код, который в обоих файлах выглядит одинаково, но рассматриваемый текст отображается только на странице, отображаемой браузером, на странице, сохраненной сценарием Джеймса:

<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>

Любая идея, почему это такпроисходит?

Ответы [ 3 ]

0 голосов
/ 27 декабря 2018

Я посоветую вам попробовать sikulix , который представляет собой инструмент автоматизации на основе изображений для работы с любыми виджетами в ОС ПК, он поддерживает грамматику Python и работает с командной строкой и, возможно, самый простой способрешить вашу проблему.Все, что вам нужно сделать, это просто сделать скриншот, вызвать скрипт sikulix в скрипте автоматизации python (с OS.system ("xxxx") или подпроцессом ...).

0 голосов
/ 29 декабря 2018

Как вы заметили, Selenium не может взаимодействовать с контекстным меню браузера для использования Save as..., поэтому вместо этого вы можете использовать внешнюю библиотеку автоматизации, такую ​​как pyautogui.

* 1006.*

Этот код открывает окно Save as... с помощью сочетания клавиш CTRL+S, а затем сохраняет веб-страницу и ее ресурсы в месте загрузки по умолчанию, нажав клавишу ввода.Этот код также называет файл как последовательность, чтобы дать ему уникальное имя, хотя вы можете изменить это для своего варианта использования.При необходимости вы можете дополнительно изменить место загрузки с помощью дополнительных клавиш и клавиш со стрелками.

Протестировано в 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')
0 голосов
/ 25 декабря 2018

Это не идеальное решение, но оно даст вам большую часть того, что вам нужно.Вы можете повторить поведение «сохранить как полную веб-страницу (завершено)», проанализировав 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, с содержимым, которое вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...