Извлечение текста из Javascript с помощью Python

#javascript #python #beautifulsoup

#javascript #python #beautifulsoup

Вопрос:

Я рассматривал примеры того, как это сделать, но не могу в этом разобраться. Я использую beautifulsoup для очистки некоторых данных — я могу использовать его для поиска нужных мне данных, но они содержатся в следующем блоке кода. Я пытаюсь извлечь из него информацию о временных метках. У меня такое чувство, что здесь работают регулярные выражения, но, похоже, я не могу понять это — какие-либо предложения??

     <script class="code" type="text/javascript">
    $(document).ready(function(){
    line1 = [['2009-02-23 10 AM', 5203], ['2009-02-08 10 AM', 3898], ['2009-02-09 10 AM', 4923], ['2009-02-22 10 AM', 3682], ['2009-02-21 10 AM', 3238], ['2009-02-20 10 AM', 4648]];
    options1 = {
    etc other text
      }
    });
    </script>
  

Ответ №1:

Вы не можете использовать BS для получения этих данных — BS работает только с HTML / XML, а не с JavaScript.

Вы должны использовать regular expressions или стандартные строковые функции.


Редактировать:

 text = '''<script class="code" type="text/javascript">
    $(document).ready(function(){
    line1 = [['2009-02-23 10 AM', 5203], ['2009-02-08 10 AM', 3898], ['2009-02-09 10 AM', 4923], ['2009-02-22 10 AM', 3682], ['2009-02-21 10 AM', 3238], ['2009-02-20 10 AM', 4648]];
    options1 = {
    etc other text
      }
    });
    </script>'''

import re

re.findall("'([^']*)'", text)
  

Результат:

 ['2009-02-23 10 AM',
 '2009-02-08 10 AM',
 '2009-02-09 10 AM',
 '2009-02-22 10 AM',
 '2009-02-21 10 AM',
 '2009-02-20 10 AM']
  

Комментарии:

1. да, единственное, что вам поможет сделать bs4, это настроить таргетинг на этот тип данных — однако, как только вы его найдете, вам нужно проанализировать его с помощью регулярного выражения — я считаю, что использование regex ast.literal_eval хорошо работает в некоторых случаях.

2. Предоставленный код определенно работает — спасибо. В моем конкретном примере, поскольку я использую bs4 для обработки данных в первую очередь, результирующие данные представляют собой элемент bs4, который не работает с регулярным выражением. Итак, я преобразую результат в строку, но часть кода появляется после того, как отображаются временные метки. Как я могу ограничить его тем, что находится между ‘line1’ и ‘options1’ в исходном коде? Все, что я пытаюсь, дает пустой результат .. например, re.findall(«‘(?<=x)([^’]*)(?>= y)'», текст), где x=’line1′ и y=’options1′

3. если есть n , то вы можете text.split('n')[2].strip() и вы получите line1 = [...]; . Теперь вы можете использовать нарезку [8:-1] для удаления line1 = , а ; затем завершить — окончательно text.split('n')[2].strip()[8:-1]

Ответ №2:

Еще одной альтернативой использованию регулярных выражений для анализа кода javascript было бы использование анализатора JavaScript, подобного slimit . Рабочий код:

 import json

from bs4 import BeautifulSoup
from slimit import ast
from slimit.parser import Parser
from slimit.visitors import nodevisitor

data = """<script class="code" type="text/javascript">
$(document).ready(function(){
line1 = [['2009-02-23 10 AM', 5203], ['2009-02-08 10 AM', 3898], ['2009-02-09 10 AM', 4923], ['2009-02-22 10 AM', 3682], ['2009-02-21 10 AM', 3238], ['2009-02-20 10 AM', 4648]];
options1 = {};
});
</script>"""

soup = BeautifulSoup(data, "html.parser")
parser = Parser()
tree = parser.parse(soup.script.get_text())

for node in nodevisitor.visit(tree):
    if isinstance(node, ast.Assign) and getattr(node.left, 'value', '') == 'line1':
        values = json.loads(node.right.to_ecma().replace("'", '"').strip())
        print(values)
        break
  

Печатает список Python:

 [[u'2009-02-23 10 AM', 5203], [u'2009-02-08 10 AM', 3898], [u'2009-02-09 10 AM', 4923], [u'2009-02-22 10 AM', 3682], [u'2009-02-21 10 AM', 3238], [u'2009-02-20 10 AM', 4648]]