Scrapy: извлечь словарь, сохраненный как текст в теге скрипта - PullRequest
1 голос
/ 26 января 2020

Тема: Извлечь словарь из тега скрипта.

Здравствуйте,

Я пытаюсь очистить эти данные от тега.

enter image description here

Цель состоит в том, чтобы иметь возможность извлечь словарь данных и получить значения для каждой из пар ключ-значение.

Example:
print(digitalData['page']['pageInfo']['language'])
>>> en

Я написал код ниже, и все работает, пока не перейду к шагу 3, где я пытаюсь преобразовать строку в словарь с помощью модуля ast.

Я получаю следующее сообщение об ошибке:

ValueError: malformed node or string: <_ast.Name object at 0x00000238C9100B48>

Код Scrapy

import scrapy
import re
import pprint
import ast


class OptumSpider(scrapy.Spider):
    name = 'optum'
    allowed_domains = ['optum.com']
    start_urls = ['http://optum.com/']

    def parse(self, response):


        #Step 1: remove all spaces, new lines and tabs
        #string = (re.sub('\s+','',response.xpath('//script/text()')[2].extract()))
        string = (re.sub('[\s+;]','',response.xpath('//script/text()')[2].extract()))
        print(string)


        # Step 2: convert string to dictionary. Creates a key as "digitalData"
        key, value = string.split("=")
        my_dict = {key: value}
        print(my_dict)

        # Step 3: extract dictionary 
        print(my_dict['digitalData']) # result is a dictionary stored as a string.
        print(type(my_dict['digitalData']))  # shows data type as string.
        #ast.literal_eval(my_dict['digitalData']) # convert string to dictionary.

Я получаю следующее сообщение об ошибке:

ValueError: malformed node or string: <_ast.Name object at 0x00000238C9100B48>

Пожалуйста предоставить комментарии о том, как решить. Если есть другой способ приблизиться или решить, пожалуйста, предложите.

1 Ответ

0 голосов
/ 26 января 2020

Ваша проблема в том, что в извлеченном словаре Javascript: у вас есть объекты.

{
 page: {
  pageInfo: {
   destinationURL: window.location.href,
   error: '',
   language: 'en',
   country: 'US',
   pageName: 'tangelo2',
   articlepubdate: '',
   articleenddate: '',
   pageTitle: 'HealthServicesInnovationCompany',
   pageOwner: '',
   pageTemplate: '',
   pageCampaign: '',
   tags: '',
   pageLastPublishDate: '2020-01-08T12:15:04.032-06:00',
   pageLastPublishedBy: 'admin',
   pageLastModifiedDate: '2020-01-08T10:24:36.466-06:00',
   pageLastModifiedBy: 'katrina'
  },
  recEngine: {
   title: 'Home',
   image: '',
   description: ''
  },
  category: {
   siteName: window.location.hostname.replace("www.", ""),
   version: '3.0',
   contentType: '',
   contentTopic: '',
   contentSegment: '',
   contentInitiative: '',
   contentProduct: '',
   contentProductLine: '',
   primaryCategory: 'tangelo2'
  }
 },
 event: {}
}

Обратите внимание на значения page.pageInfo.destinationURL и page.category.siteName.

В данном случае ast.literal_eval или любой другой метод, который вы можете попытаться преобразовать в этот словарь Javascript в Python, приведет к ошибке. Вам нужно будет найти способ удалить window... из my_dict['digitalData'] перед обработкой его с помощью ast, demjson или любым другим инструментом.


Возможное решение, подобное этому, использует demjson вместо ast.

import scrapy
import pprint
import demjson
import re


class OptumSpider(scrapy.Spider):
    name = 'optum'
    allowed_domains = ['optum.com']
    start_urls = ['http://optum.com/']

    def parse(self, response):


        #Step 1: remove all spaces, new lines and tabs
        string = (re.sub('[\s+;]','',response.xpath('//script/text()')[2].extract()))

        # Step 2: convert string to dictionary. Creates a key as "digitalData"
        js_dict = string.split("=")[1]
        js_dict = re.sub(r"\bwindow(.*?),\b", '"",', js_dict)

        # Step 3: extract dictionary
        my_dict = demjson.decode(js_dict)

        pprint.pprint(my_dict)
        print(type(my_dict))

При работе

scrapy runspider test.py -s LOG_ENABLED=False

Это выводит:

{'event': {},
 'page': {'category': {'contentInitiative': '',
                       'contentProduct': '',
                       'contentProductLine': '',
                       'contentSegment': '',
                       'contentTopic': '',
                       'contentType': '',
                       'primaryCategory': 'tangelo2',
                       'siteName': '',
                       'version': '3.0'},
          'pageInfo': {'articleenddate': '',
                       'articlepubdate': '',
                       'country': 'US',
                       'destinationURL': '',
                       'error': '',
                       'language': 'en',
                       'pageCampaign': '',
                       'pageLastModifiedBy': 'katrina',
                       'pageLastModifiedDate': '2020-01-08T10:24:36.466-06:00',
                       'pageLastPublishDate': '2020-01-08T12:15:04.032-06:00',
                       'pageLastPublishedBy': 'admin',
                       'pageName': 'tangelo2',
                       'pageOwner': '',
                       'pageTemplate': '',
                       'pageTitle': 'HealthServicesInnovationCompany',
                       'tags': ''},
          'recEngine': {'description': '', 'image': '', 'title': 'Home'}}}
<class 'dict'>
...