Сбор информации со страницы на JavaScript, как эта, на первый взгляд может показаться утомительным;но на самом деле часто может быть более продуктивным, поскольку вся информация находится в одном месте, а не разбросана по множеству дорогостоящих поисков HTTP-запросов.
Поэтому, когда страница дает вам JSON-данные, подобные этим, выможете поблагодарить их за то, что вы хорошо относитесь к серверу и используете его! :)
Если вы потратите немного времени на "анализ исходного вида", который вы уже собрали, это также будет более эффективным, чемпытаясь получить информацию через (дорогой) Selenium / Splash / ect.-renderpipe.
Инструмент, который неоценим для этого, - XPath .Иногда от нашего друга может потребоваться небольшая дополнительная помощь regex
.
Если вы успешно загрузили страницу и у вас есть объект Scrapy response
(или у вас есть Parsel.Selector()
поверхв противном случае получено тело ответа), вы сможете получить доступ к методу xpath()
как response.xpath
или selector.xpath
:
>>> response.status
200
Вы определили, что данные существуют в виде простого текста (json), поэтомунам нужно детализировать, где он скрывается, чтобы в конечном итоге извлечь необработанный контент JSON.После этого преобразование его в Python dict для дальнейшего использования будет тривиальным.В этом случае это внутри контейнерного узла <script type="application/ld+json">
.Наш XPath для этого может выглядеть так:
>>> response.xpath('//script[@type="application/ld+json"]')
[<Selector xpath='//script[@type="application/ld+json"]' data='<script type="application/ld+json">\n{\n '>,
<Selector xpath='//script[@type="application/ld+json"]' data='<script type="application/ld+json">\n{\n '>,
<Selector xpath='//script[@type="application/ld+json"]' data='<script type="application/ld+json">\n '>]
Это найдет каждый "скрипт" узел на странице XML, который имеет атрибут типа "type"со значением "application / ld + json".По-видимому, это недостаточно конкретно, поскольку мы находим три узла (Selector
-обернутые в нашем возвращенном списке).
Из вашего анализа мы знаем, что наш JSON должен содержать "@type":"Event"
, поэтому пусть наш xpath сделаетнебольшой поиск по подстроке для этого:
>>> response.xpath("""//script[@type="application/ld+json"]/self::node()[contains(text(), '"@type":"Event"')]""")
[<Selector xpath='//script[@type="application/ld+json"]/self::node()[contains(text(), \'"@type":"Event"\')]' data='<script type="application/ld+json">\n '>]
Здесь мы добавили второй квалификатор, который говорит, что наш script
узел должен содержать данный текст .
(Self :: node () 'показывает некоторую магию осей XPath для ссылки на наш текущий script
узел в этой точке - вместо его потомков. Хотя мы упростим это.)
Теперь наш список возврата содержитодин узел / селектор.Как мы видим из строки data=
, если бы мы extract()
это, мы бы сейчас получили некоторую строку, такую как <script type="application/ld+json">[...]</script>
.Так как мы заботимся о содержимом узла, но не о самом узле, у нас есть еще один шаг:
>>> response.xpath("""//script[@type="application/ld+json"][contains(text(), '"@type":"Event"')]/text()""")
[<Selector xpath='//script[@type="application/ld+json"][contains(text(), \'"@type":"Event"\')]/text()' data='\n [\n \n \n '>]
И это возвращает (SelectorList
of) нашу цель text()
.Как вы можете видеть, мы могли бы покончить с самоотверженностью.Теперь xpath()
всегда возвращает SelectorList
, но у нас есть небольшой помощник для этого: response.xpath().extract_first()
будет захватывать первый элемент списка - проверка, если он существует - перед его обработкой.Мы можем поместить этот результат в переменную data
, после чего просто json.loads(data)
это поместить в словарь Python и посмотреть наши значения:
>>> events = json.loads(data)
>>> [item['url'] for item in events]
['<url>',
'<url>',
'<url>',
'<url>']
Теперь вы можете превратить их в scrapy.Request(url)
sи вы узнаете, как продолжить.
.
Как всегда, ответственно ползите и держите в сети хорошее место.Я не поддерживаю какое-либо незаконное поведение.
Оценка своих прав или получение разрешения на доступ к указанному целевому ресурсу является его собственной ответственностью.