Получение всего видимого текста с веб-страницы с использованием Selenium
Я весь день искал этот день, не найдя ответа, поэтому извиняюсь заранее, если об этом уже ответили.
Я пытаюсь получить весь видимый текст с большого количества различных сайтов. Причина в том, что я хочу обработать текст, чтобы в конечном итоге классифицировать веб-сайты.
После нескольких дней исследований я решил, что Selenium - мой лучший шанс. Я нашел способ захватить весь текст с помощью Selenium, к сожалению, один и тот же текст захватывается несколько раз:
from selenium import webdriver
import codecs
filen = codecs.open('outoput.txt', encoding='utf-8', mode='w+')
driver = webdriver.Firefox()
driver.get("http://www.examplepage.com")
allelements = driver.find_elements_by_xpath("//*")
ferdigtxt = []
for i in allelements:
if i.text in ferdigtxt:
pass
else:
ferdigtxt.append(i.text)
filen.writelines(i.text)
filen.close()
driver.quit()
Условие if
внутри цикла for
- попытка устранить проблему получения одного и того же текста несколько раз - однако, она не работает, как планировалось, на некоторых веб-страницах. (он также замедляет script A LOT)
Я предполагаю, что причиной моей проблемы является то, что при запросе внутреннего текста элемента - я также получаю внутренний текст элементов, вложенных внутри рассматриваемого элемента.
Есть ли способ обойти это? Есть ли какой-то мастер-элемент, который я получаю из внутреннего текста? Или совсем другой способ, который позволил бы мне достичь моей цели? Любая помощь будет очень признательна, поскольку у меня нет идей для этого.
Изменить: причина, по которой я использовал Selenium, а не Mechanize и Beautiful Soup, - это то, что я хотел, чтобы текст, отложенный JavaScript,
Ответы
Ответ 1
Используя lxml, вы можете попробовать что-то вроде этого:
import contextlib
import selenium.webdriver as webdriver
import lxml.html as LH
import lxml.html.clean as clean
url="http://www.yahoo.com"
ignore_tags=('script','noscript','style')
with contextlib.closing(webdriver.Firefox()) as browser:
browser.get(url) # Load page
content=browser.page_source
cleaner=clean.Cleaner()
content=cleaner.clean_html(content)
with open('/tmp/source.html','w') as f:
f.write(content.encode('utf-8'))
doc=LH.fromstring(content)
with open('/tmp/result.txt','w') as f:
for elt in doc.iterdescendants():
if elt.tag in ignore_tags: continue
text=elt.text or ''
tail=elt.tail or ''
words=' '.join((text,tail)).strip()
if words:
words=words.encode('utf-8')
f.write(words+'\n')
Это похоже на почти весь текст на www.yahoo.com, за исключением текста в изображениях и некоторого текста, который изменяется со временем (возможно, с javascript и обновлением).
Ответ 2
Здесь вариант @unutbu answer:
#!/usr/bin/env python
import sys
from contextlib import closing
import lxml.html as html # pip install 'lxml>=2.3.1'
from lxml.html.clean import Cleaner
from selenium.webdriver import Firefox # pip install selenium
from werkzeug.contrib.cache import FileSystemCache # pip install werkzeug
cache = FileSystemCache('.cachedir', threshold=100000)
url = sys.argv[1] if len(sys.argv) > 1 else "https://stackoverflow.com/q/7947579"
# get page
page_source = cache.get(url)
if page_source is None:
# use firefox to get page with javascript generated content
with closing(Firefox()) as browser:
browser.get(url)
page_source = browser.page_source
cache.set(url, page_source, timeout=60*60*24*7) # week in seconds
# extract text
root = html.document_fromstring(page_source)
# remove flash, images, <script>,<style>, etc
Cleaner(kill_tags=['noscript'], style=True)(root) # lxml >= 2.3.1
print root.text_content() # extract text
Я разделил вашу задачу на две части:
- получить страницу (включая элементы, созданные javascript)
- извлечь текст
Код подключается только через кеш. Вы можете получать страницы в одном процессе и извлекать текст в другом процессе или откладывать, чтобы сделать это позже, используя другой алгоритм.