#python #web-scraping #beautifulsoup #python-requests
Вопрос:
Я пытался использовать веб-скребок на веб-сайте, используя запросы и библиотеки python Beautifulsoup. Проблема в том, что я получаю html-данные веб-страницы, но содержимое тега тела пусто, в то время как на панели проверки на веб-сайте этого нет. Кто-нибудь может объяснить, почему это происходит и что я могу сделать, чтобы получить содержимое тела?
Вот мой код:
from bs4 import BeautifulSoup
import requests
source = requests.get('https://webaccess-il.rexail.com/?s_jwe=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gKfb7AnqhUiIMIn0PGb35g.SUsLS70gBec9GBgraaV5BK8hKyqm-VvMSNjP3nIumtcrj9h19zOkYjaBHrW4SDL10DjeIcwQcz9ul1p8umMHKxPPC-QZpCyJbk7JQkUSqFM._d_sGsiSyPF_Xqs2hmLN5A#/store-products-shopping-non-customers').text
soup = BeautifulSoup(source, 'lxml')
print(soup)
Вот панель проверки веб — сайта:
И вот результат моего кода:
Спасибо вам 🙂
Ответ №1:
Есть две причины, по которым ваш код не может работать. Первый из них заключается в том, что веб-сайт действительно требует дополнительной header
информации или cookie
информации, которую вы можете попытаться найти с помощью инструмента Проверки браузера и добавить с помощью
requests.get(url, headers=headers, cookies=cookies)
где headers
и cookies
находятся словари.
Другая причина, в которую я верю, заключается в том, что контент динамически загружается через Javascript
после сборки, и то, что вы получаете, — это изначально загруженный веб-сайт.
Чтобы также предоставить вам решение, я приведу пример с использованием Selenium, который имитирует весь браузер, который обслуживает весь веб-сайт, однако у selenium есть некоторые накладные расходы на настройку, которые вы можете легко погуглить.
from time import sleep
from selenium import webdriver
from bs4 import BeautifulSoup
url = 'https://webaccess-il.rexail.com/?s_jwe=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gKfb7AnqhUiIMIn0PGb35g.SUsLS70gBec9GBgraaV5BK8hKyqm-VvMSNjP3nIumtcrj9h19zOkYjaBHrW4SDL10DjeIcwQcz9ul1p8umMHKxPPC-QZpCyJbk7JQkUSqFM._d_sGsiSyPF_Xqs2hmLN5A#/store-products-shopping-non-customers'
driver = webdriver.Firefox()
driver.get(url)
sleep(10)
content = driver.page_source
soup = BeautifulSoup(content)
Если вы хотите, чтобы моделирование браузера не было видно, вы можете добавить
from selenium.webdriver.firefox.options import Options
options = Options()
options.headless = True
driver = webdriver.Firefox(options=options)
что заставит его работать в фоновом режиме.
В качестве альтернативы Firefox вы можете использовать практически любой браузер, используя соответствующий драйвер.
Пример установки на базе Linux можно найти здесь Ссылка
Ответ №2:
Несмотря на то, что я нахожу использование Селена более легким для начинающих, этот сайт беспокоил меня, поэтому я придумал чистый requests
способ, которым я также хочу поделиться.
Процесс: Когда вы просматриваете сетевой трафик после загрузки веб-сайта, вы обнаруживаете множество исходящих запросов get. Предполагая, что вас интересуют загруженные продукты, я обнаружил вызов прямо над изображениями продуктов, загружаемых с Amazon S3, на
https://client-il.rexail.com/client/public/public-catalog?s_jwe=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gKfb7AnqhUiIMIn0PGb35g.SUsLS70gBec9GBgraaV5BK8hKyqm-VvMSNjP3nIumtcrj9h19zOkYjaBHrW4SDL10DjeIcwQcz9ul1p8umMHKxPPC-QZpCyJbk7JQkUSqFM._d_sGsiSyPF_Xqs2hmLN5A
важно
https://client-il.rexail.com/client/public/public-catalog?s_jwe=[...]
Нажав на URL-адрес, я обнаружил, что это действительно JSON продуктов. Однако s_jwe
токен является динамическим, и без него JSON не загружается.
Теперь, изучив URL-адрес начальной загрузки и выполнив поиск s_jwe
, вы найдете
<script>
window.customerStore = {store: angular.fromJson({"id":26,"name":"u05deu05e9u05e7 u05d4u05e8 u05e4u05e8u05d7u05d9u05dd","imagePath":"images/stores/26/88aa6827bcf05f9484b0dafaedf22b0a.png","secondaryImagePath":"images/stores/4d5d1f54038b217244956071ca62312d.png","thirdImagePath":"images/stores/26/2f9294180e7d656ba7280540379869ee.png","fourthImagePath":"images/stores/26/bd2861565b18613497a6ce66903bf9eb.png","externalWebTrackingAccounts":"[{"accountType":"googleAnalytics","identifier":"UA-130110792-1","primaryDomain":"ecomeshek.co.il"},{"accountType":"facebookPixel","identifier":"3958210627568899"}]","worksWithStoreCoupons":false,"performSellingUnitsEstimationLearning":false}), s_jwe: "eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gKfb7AnqhUiIMIn0PGb35g.SUsLS70gBec9GBgraaV5BK8hKyqm-VvMSNjP3nIumtcrj9h19zOkYjaBHrW4SDL10DjeIcwQcz9ul1p8umMHKxPPC-QZpCyJbk7JQkUSqFM._d_sGsiSyPF_Xqs2hmLN5A"};
const externalWebTrackingAccounts = angular.fromJson(customerStore.store.externalWebTrackingAccounts);
</script>
содержащий
s_jwe: "eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gKfb7AnqhUiIMIn0PGb35g.SUsLS70gBec9GBgraaV5BK8hKyqm-VvMSNjP3nIumtcrj9h19zOkYjaBHrW4SDL10DjeIcwQcz9ul1p8umMHKxPPC-QZpCyJbk7JQkUSqFM._d_sGsiSyPF_Xqs2hmLN5A"
Итак, подводя итог, хотя начальная страница не содержит продуктов, она содержит маркер и URL-адрес продукта.
Теперь вы можете извлечь эти два и вызвать каталог продукции напрямую как таковой:
ОКОНЧАТЕЛЬНЫЙ КОД:
import requests
import re
import json
s = requests.Session()
initial_url = 'https://webaccess-il.rexail.com/?s_jwe=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gKfb7AnqhUiIMIn0PGb35g.SUsLS70gBec9GBgraaV5BK8hKyqm-VvMSNjP3nIumtcrj9h19zOkYjaBHrW4SDL10DjeIcwQcz9ul1p8umMHKxPPC-QZpCyJbk7JQkUSqFM._d_sGsiSyPF_Xqs2hmLN5A#/store-products-shopping-non-customers'
initial_site = s.get(url= initial_url).content.decode('utf-8')
jwe = re.findall(r's_jwe:.*"(.*)"', initial_site)
product_url = "https://client-il.rexail.com/client/public/public-catalog?s_jwe=" jwe[0]
products_site = s.get(url= product_url).content.decode('utf-8')
products = json.loads(products_site)["data"]
print(products[0])
При декодировании требуется небольшая доработка, но я уверен, что вы справитесь с этим. 😉
Это, конечно, более простой способ очистки этого веб-сайта, но, как я надеюсь, показал, очистка всегда немного похожа на игру в Шерлока Холмса.
Любые вопросы, рад помочь.
Комментарии:
1. Спасибо вам за отличные ответы! Я попробую это сделать 🙂