Как использовать Scrapy-Драматург для получения URL-адреса после входа в систему?Python

Программы на Python
Ответить
Anonymous
 Как использовать Scrapy-Драматург для получения URL-адреса после входа в систему?

Сообщение Anonymous »

Я пытаюсь получить доступ к защищенному паролем веб-сайту, получить определенное содержимое и вывести его в файл csv или json. У меня есть имя пользователя и пароль. Я могу использовать Scrapy-Драматург для входа в систему, грубо говоря, с помощью следующего кода.

Код: Выделить всё

import scrapy
from playwright.async_api import Page
from scrapy_playwright.page import PageMethod

async def login(page : Page) -> str:
await page.wait_for_selector(selector="button[data-automation='signin-btn']")
await page.locator("button[data-automation='signin-btn']").click()
await page.wait_for_selector("button[data-automation='sign-in-button']")
await page.locator("input[name=txtusername]").click()
await page.locator("input[name=txtusername]").fill("00000")
await page.locator("input[name=txtpassword]").click()
await page.locator("input[name=txtpassword]").fill("11111")
await page.locator(selector = "button[data-automation='sign-in-button']").click()
return page.url

class MySpider(scrapy.Spider):
name = "myspider"
custom_settings = {
"TWISTED_REACTOR": "twisted.internet.asyncioreactor.AsyncioSelectorReactor",
"DOWNLOAD_HANDLERS": {
"https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
"http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
},
"PLAYWRIGHT_PROCESS_REQUEST_HEADERS": None,
}

def start_requests(self):
yield scrapy.Request(
url="https://",
meta=dict(
#proxy = "http://localhost:8888",
playwright = True,
playwright_page_methods = [
PageMethod(login)
]),
)

def parse(self, response):
pass

Обратите внимание: мне пришлось добавить «PLAYWRIGHT_PROCESS_REQUEST_HEADERS»: None,, чтобы вход в Scrapy работал. Я мог бы, наверное, сузить круг до нужного? или, может быть, я делаю что-то не так.
Когда я доберусь до этого момента после аутентификации. Все, что мне действительно нужно сделать дальше, это перейти к нескольким URL-адресам. конкретно "/api/board/casual-board?" и получите содержимое JSON. но если я попытаюсь сделать это в своем методе parse(), я получу ошибку 401. Я могу продолжить навигацию, чтобы открыть следующую страницу, и циклически переключаться между вещами, как будто я браузер, но затем я собираюсь мне приходится анализировать html со страницы драматурга, когда у меня есть отличный json-объект всего, что я хочу, поступающего от API...
т.е. Если я изменю свой метод анализа на этот после аутентификации, я получу ошибку 401.

Код: Выделить всё

    def parse(self, response):
parsed_url = urlparse(response.url)
Path(quote(f"./original/{response.request.method}{parsed_url.path}-{parsed_url.query}")).write_bytes(response.body)

yield scrapy.Request(
"https:///api/board/casual-board?",
meta=dict(
playwright = True,
)
callback=self.navigate_to_boards,
)

def navigate_to_boards(self, response):
pass

Я попробовал повторно использовать страницу playwright_page и все равно получил ее

Код: Выделить всё

    def parse(self, response):
parsed_url = urlparse(response.url)
Path(quote(f"./original/{response.request.method}{parsed_url.path}-{parsed_url.query}")).write_bytes(response.body)
page = response.meta['playwright_page']
yield scrapy.Request(
url = "https:///api/board/casual-board?",
meta=dict(
playwright = True,
playwright_page = page
),
callback=self.navigate_to_boards,
)
Я что-то упустил?

Обновление: во второй версии вызова отсутствует токен носителя авторизации генерируется логином. Как мне получить это из входа в систему и передать его вместе со следующими запросами?
Я понял, как вызвать await page.context.storage_state(path="./auth/state. json") но как мне получить следующий запрос на его использование?

обновление 2: возможно, я нашел что-то, что подойдет мне . Размещение page.expect_response вокруг триггера на клик дает мне ответ json в качестве тела, что может быть именно тем, что я хочу. все еще не уверен, что это правильный способ сделать это.

Код: Выделить всё

    async with page.expect_response("https:///api/board/casual-board?") as response_info:
await page.get_by_text("Casual Boards").click()
response = await response_info.value
await page.wait_for_selector("[data-automation='navigation-bar-title']")
return await response.body()
обновление 3:
Нет, у меня это не сработает, в какой-то момент мне действительно нужно начать поиск и нужно получить/добавить токен доступа

обновление 4:
хорошо, прогресс.
изменив кнопку входа в систему, нажмите выше:

Код: Выделить всё

    async with page.expect_response("https:///identity/connect/token") as response_info_login:
await page.locator("button[data-automation='sign-in-button']").click()
login_response = await response_info_login.value
позволяет мне захватить токен аутентификации. но теперь попытаться получить это из Scrapy сложно. изменение возврата метода login(page: Page) на:

Код: Выделить всё

    return await login_response.body(),await board_response.body()
и в моем методе анализа помещаем:

Код: Выделить всё

        login_response = response.meta["playwright_page_methods"][0]
должен работать, но это не совсем так. а также... как мне настроить следующий запрос Scrapy, чтобы он включал правильные заголовки? Просто драматург, я пытаюсь сделать то же самое, но устанавливаю дополнительные http-заголовки в контексте и все равно получаю ответ 426. (так... не хватает некоторых заголовков?)

обновление 5.
Я был так близок... к получению вернул PageMethod, но не получил результат

Код: Выделить всё

        login_response, board_response = response.meta["playwright_page_methods"][0].result
это правильный способ получить этот ответ.
woot. теперь, чтобы выяснить правильные заголовки ..? отправить следующий запрос на решение моей проблемы с ошибкой 426

Подробнее здесь: https://stackoverflow.com/questions/791 ... logging-in
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»