Извлечение из динамического ответа JSON с помощью Scrapy

Я хочу извлечь значение «доступно» из вывода JSON, которое выглядит следующим образом.

{
    "result": {
        "code": 100,
        "message": "Command Successful"
    },
    "domains": {
        "yolotaxpayers.com": {
            "avail": false,
            "tld": "com",
            "price": "49.95",
            "premium": false,
            "backorder": true
        }
    }
}

Проблема в том, что значение ['avail'] меньше ["domains"]["domain_name"], и я не могу понять, как получить доменное имя.

У вас есть мой паук ниже. Первая часть работает нормально, а вторая нет.

import scrapy
import json
from whois.items import WhoisItem

class whoislistSpider(scrapy.Spider):
    name = "whois_list"
    start_urls = []
    f = open('test.txt', 'r')
    global lines
    lines = f.read().splitlines()
    f.close()
    def __init__(self):
        for line in lines:
            self.start_urls.append('http://www.example.com/api/domain/check/%s/com' % line)

    def parse(self, response):
        for line in lines:
            jsonresponse = json.loads(response.body_as_unicode())
            item = WhoisItem()
            domain_name = list(jsonresponse['domains'].keys())[0]
            item["avail"] = jsonresponse["domains"][domain_name]["avail"]
            item["domain"] = domain_name
            yield item

Заранее благодарим вас за ответы.


person Cristian Calin    schedule 11.07.2016    source источник


Ответы (3)


Предполагая, что вы ожидаете только один результат на ответ:

domain_name = list(jsonresponse['domains'].keys())[0]
item["avail"] = jsonresponse["domains"][domain_name]["avail"]

Это будет работать, даже если есть несоответствие между доменом в файле "test.txt" и доменом в результате.

person Dean Fenster    schedule 11.07.2016
comment
Спасибо @Dean. Работает нормально, но зацикливается. Для 17 проверенных доменов я получил 289 результатов с большим количеством дубликатов. У вас есть идеи, как выйти из этого цикла? - person Cristian Calin; 11.07.2016
comment
@CristianCalin Кажется, что в вашей функции parse вы добавляете в список доменов (а также в init), возможно, это источник бесконечного цикла. - person Dean Fenster; 11.07.2016
comment
Я переместил список доменов вверх в class и определил lines как глобальный, но все тот же цикл. - person Cristian Calin; 11.07.2016
comment
Пожалуйста, отредактируйте свой вопрос с обновленным кодом. Это может иметь какое-то отношение к тому, как scrapy проверяет наличие повторяющихся URL-адресов. - person Dean Fenster; 11.07.2016
comment
Почему вы добавляете все домены в разрешенные_домены, вы имеете в виду отправить на них сканер? Может быть, он рассматривает WhoisItem как следующий этап сканирования... - person Dean Fenster; 11.07.2016
comment
Я удалил эти строки и обновил код, но, к сожалению, у меня тот же результат. @ДинФенстер - person Cristian Calin; 11.07.2016
comment
@CristianCalin Не могли бы вы добавить код для WhoisItem, который вы используете? либо здесь, либо в дополнительном вопросе (поскольку мы уходим от темы) - person Dean Fenster; 11.07.2016
comment
Спасибо @DeanFenster. Я разместил здесь новый вопрос stackoverflow.com/questions/38315087/ - person Cristian Calin; 11.07.2016

В настоящее время он пытается получить значение по ключу "('%s.com' % line)".

Вам нужно правильно отформатировать строку:

domain_name = "%s.com" % line.strip()
item["avail"] = jsonresponse["domains"][domain_name]["avail"]
person alecxe    schedule 11.07.2016
comment
Спасибо @alecxe. Это сработало, но теперь я получаю item["avail"] = jsonresponse["domains"][domain_name]["avail"] KeyError: 'qqqqq.com' Я думаю, что это связано с цитатами, верно? - person Cristian Calin; 11.07.2016

Чтобы получить доменное имя из приведенного выше ответа json, вы можете использовать понимание списка, например:

domain_name = [x вместо x в jsonresponse.values()[0].keys()]

Чтобы получить значение «доступно», используйте тот же метод, например:

avail = [x["доступно"] для x в jsonresponse.values()[0].values(), если "доступно" в x]

чтобы получить значения в строковом формате, вы должны вызвать его по индексу 0, например:

domain_name[0] и avail[0], потому что результаты понимания списка хранятся в переменной типа списка.

Подробнее об распознавании списков

person vikas0713    schedule 11.07.2016