@itsLegend

Почему сайт не видит form data?

Есть сайт snaptik.app/ru, проверил, что если отправить ему ссылку, то происходит запрос на сайт https://snaptik.app/action_2021.php?lang=ru передает он туда form data "url".
Решил написать отправку через requests, сделал так:
_url_parse = 'https://snaptik.app/action_2021.php?lang=ru'
        
        s = requests.Session()
        headers = {
            'accept': '*/*',
            'accept-language': 'ru,en;q=0.9',
            'content-length': '263',
            'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryWAubJkiU77iGCuEI',
            'origin': 'https://snaptik.app',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 YaBrowser/21.2.2.101 Yowser/2.5 Safari/537.36'
        }
        data = {
            'url': 'https://www.tiktok.com/@lisaandlena/video/6926975884846992645'
        }
        r = s.post(_url_parse, data=data, headers=headers)
        print(r.content)

Но ответом получаю
b'\nerror_url'


Будто url вовсе не передается, хотя делаю все правильно, в чем может быть ошибка?
  • Вопрос задан
  • 590 просмотров
Решения вопроса 1
MinTnt
@MinTnt
Как видно ещё в самих headers запрос не правильно построен с data.
boundary=----WebKitFormBoundaryWAubJkiU77iGCuEI'
Значит в запросе присутствует WebKitFormBoundary, (в принципе в гугле есть решения)

И полная data выглядит вот так:
------WebKitFormBoundarywbDAEub66BAoxeVG
Content-Disposition: form-data; name="url"

https://www.tiktok.com/@lisaandlena/video/6926975884846992645
------WebKitFormBoundarywbDAEub66BAoxeVG--


Решение:
import requests
from requests_toolbelt import MultipartEncoder

#Задаём headers в начале, так как в следующих двух запросах они идентичны
head = {'User-Agent': 'Mozilla/5.0', 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7CwxCXhJ7UIYYnji', 'Cookie': 'PHPSESSID=sf89oogdslb85de7ec42j4mgl3; current_language=ru'}
#Этот запрос ниже, отправляется для того, чтоб можно сказать дать жизнь токену, на какое-то время
requests.post('https://snaptik.app/check_token.php', headers = head,  data = MultipartEncoder(fields={}, boundary = '----WebKitFormBoundary7CwxCXhJ7UIYYnji'))

#А это уже сама инфа, что подгружается скриптом. Обычно я для просмотра подобной инфы использую open('log.html', 'w', encoding='utf-8').write(post.text), чтоб в созданом файле посмотреть что мне пригодиться
dat = MultipartEncoder(fields={'url': 'https://www.tiktok.com/@lisaandlena/video/6926975884846992645'}, boundary = '----WebKitFormBoundary7CwxCXhJ7UIYYnji')
post = requests.post('https://snaptik.app/action_2021.php', headers = head, data = dat)
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
SoreMix
@SoreMix Куратор тега Python
yellow
Потому что там content-type multipart/form-data, а вы передаете application/x-www-form-urlencoded

Ну и в куках есть куки от клаудфлары, поэтому запросы могут заворачиваться со временем.

multipart отправляется как-то так (в случае, если данные не являются файлом):
import requests

headers = {
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36',
    'cookie': '__cfduid=df460642f2af00ab8032064816028d4d81615715323; PHPSESSID=v927e4hlvij4adb1t82h820mba; __cflb=0H28vNadMLAyXKUf23mqg1oQcXXk66XXzAorU7peK4w; current_language=ru',
}

data = {'url': (None, 'https://www.tiktok.com/@lisaandlena/video/6926975884846992645')}

r = requests.post('https://snaptik.app/action_2021.php', headers=headers, files=data)


Ну и заголовок content-type (как и content-length) устанавливать не надо, requests сама формирует нужные заголовки в зависимости от вашего конструктора

Для тех, кому интересно, что за кортеж в files

В этом словаре:
data = {'url': (None, 'https://www.tiktok.com/@lisaandlena/video/6926975884846992645')}

ключ url - имя самого поля.
Первый элемент кортежа - имя файла. У нас файла нет, поэтому передаем None
Второй - сам контент.

Если создаим сырой запрос:
raw_request = requests.Request('POST', 'https://httpbin.org/post', files={'url': (None, 'https://www.tiktok.com/@lisaandlena/video/6926975884846992645')})
prepared_request = raw_request.prepare()

print(prepared_request.body)

# b'--0548e3f8652931495a692616ea2f819e\r\nContent-Disposition: form-data; name="url"\r\n\r\nhttps://www.tiktok.com/@lisaandlena/video/6926975884846992645\r\n--0548e3f8652931495a692616ea2f819e--\r\n'


Если вместо None будет имя файла - оно будет отправлено в запросе, все просто

raw_request = requests.Request('POST', 'https://httpbin.org/post', files={'url': ('filename.txt', 'https://www.tiktok.com/@lisaandlena/video/6926975884846992645')})
prepared_request = raw_request.prepare()

print(prepared_request.body)

#b'--6e5a4f0c3cc63461b6b613f86f17b22f\r\nContent-Disposition: form-data; name="url"; filename="filename.txt"\r\n\r\nhttps://www.tiktok.com/@lisaandlena/video/6926975884846992645\r\n--6e5a4f0c3cc63461b6b613f86f17b22f--\r\n'

Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы