Scrapy + Python, Ошибка при поиске ссылок с сайта - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь найти URL-адреса всех событий на этой странице:

https://www.eventshigh.com/delhi/food?src=exp

Но я вижу URL-адрес только в формате JSON:

 {
    "@context":"http://schema.org",
    "@type":"Event",
    "name":"DANDIYA NIGHT 2018",
    "image":"https://storage.googleapis.com/ehimages/2018/9/4/img_b719545523ac467c4ad206c3a6e76b65_1536053337882_resized_1000.jpg",
    "url":"https://www.eventshigh.com/detail/Delhi/5b30d4b8462a552a5ce4a5ebcbefcf47-dandiya-night-2018",
    "eventStatus": "EventScheduled",

    "startDate":"2018-10-14T18:30:00+05:30",
    "doorTime":"2018-10-14T18:30:00+05:30",

      "endDate":"2018-10-14T22:30:00+05:30",

    "description" : "Dress code : TRADITIONAL (mandatory)\u00A0 \r\n Dandiya sticks will be available at the venue ( paid)\u00A0 \r\n Lip smacking food, professional dandiya Dj , media coverage , lucky draw \u00A0, Dandiya Garba Raas , Shopping and Games .\u00A0 \r\n \u00A0 \r\n Winners\u00A0 \r\n \u00A0 \r\n Best dress ( all",
    "location":{
      "@type":"Place",


          "name":"K And L Community Hall (senior Citizen Complex )",


          "address":"80 TO 49, Pocket K, Sarita Vihar, New Delhi, Delhi 110076, India"



    },

Вот оноis:

"url":"https://www.eventshigh.com/detail/Delhi/5b30d4b8462a552a5ce4a5ebcbefcf47-dandiya-night-2018"

Но я не могу найти какой-либо другой тег HTML / XML, который содержит ссылки.Также я не могу найти соответствующий файл JSON, который содержит ссылки.Не могли бы вы помочь мне почистить ссылки на все события этой страницы:

https://www.eventshigh.com/delhi/food?src=exp

1 Ответ

0 голосов
/ 20 сентября 2018

Сбор информации со страницы на 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и вы узнаете, как продолжить.

.
Как всегда, ответственно ползите и держите в сети хорошее место.Я не поддерживаю какое-либо незаконное поведение.
Оценка своих прав или получение разрешения на доступ к указанному целевому ресурсу является его собственной ответственностью.

...