Kodi-vStream / venom-xbmc-addons

Addon de Streaming français pour Xbmc
GNU General Public License v3.0
496 stars 275 forks source link

[TUTO] Contourner cloudflare avec selenium sur Vstream #2948

Closed Ovni-crea closed 2 years ago

Ovni-crea commented 4 years ago

Inspiré de ce tuto: https://docs.j7k6.org/bypass-cloudflare-protection-webscraping-python-selenium/

Merci à @TmpName de nous avoir partagé cette solution

Compatibilité Os:

Windows : Oui
Linux : Oui (Voir tout en bas avant partie bonus) Mac : Non testé
Android : Non
Ios : Non
Xbox : Aucune info dessus donc j'en déduit que non

Compatibilité Navigateur:

Chrome: Oui Firefox: Oui (21/06/2020) (Voir tout en bas avant partie bonus) IE : Non testé Edge : Non testé Safari : Non testé Opera : Non testé

Etapes 1 : Les programmes nécessaires

Ils vous faut le module selenium pour kodi : https://github.com/Ovni-crea/seleniumzip/raw/master/script.module.selenium/script.module.selenium-3.141.0.zip (Update : Il contient geckodriver pour firefox)

Ils vous faut un navigateur compatible ci dessus et à jour important

Ils vous faut un des OS qui est compatible écrit au dessus

Ils vous faut notepad ++ soit visual studio code ou éclipse (Personnellement j'utilise éclipse plus pratique avec le tutoriel de @sizanic

Etapes 2 : La préparation

Il faut importer le module dans addon.xml en faisant les touches Windows + R téléchargement

Et écrire dans la barre qui apparait

Pour Kodi normal : %APPDATA%\Kodi\

Pour Kodi version Windows 10 : %LOCALAPPDATA%\Packages\XBMCFoundation.Kodi_4n2hpmxwrvr6p\LocalCache\Roaming\Kodi\

Capture

Ensuite vous allez dans le dossier addon puis le dossier plugin.video.vstream

Capture2

Capture3

Et vous ouvrez le fichier addon.xml avec notepad ++ ou autre éditeur en ajoutant ceci

<import addon="script.module.selenium"/>

Capture4

Etapes 3 : Utilisation du module pour Vstream (Vous pouvez vous arrêter ici si c'est juste pour l'installation du module sinon vous pouvez continuer)

Pour utiliser le module ils vous faut importer la librairie de selenium donc vous prenez le site que vous voulez en allant dans le dossier de vstream comme tout à l'heure puis dans le dossier resources puis sites comme ceci Capture 5 Capture 6

Et ensuite vous prenez le site que vous voulez modifier qui utilise cloudflare en .py important Et ouvrez le avec un éditeur python (je déconseille worldpad et bloc note) Et vous ajoutez les lignes import time from selenium import webdriver from selenium.webdriver.common.driver_utils import get_driver_path

Capture 7

Et ensuite copiez ce morceau de code juste avant la fonction def load()

https://github.com/Ovni-crea/Source-vstream/blob/master/exemple%20selenium.py

Lien pour le code (Update : Il corrige le problème avec l'encodage ascii)

https://github.com/Ovni-crea/Source-vstream/blob/master/exemple%20selenium%20linux.py

Lien pour la version linux (Veuillez noter que la ligne 4 est à modifier en replaçant USERNAME par le nom d'utilisateur de votre machine et aussi il faut utiliser Chrome et non Chromium )

Lien pour Firefox: https://github.com/Ovni-crea/Source-vstream/tree/master/firefox%20selenium

(Veuillez noter que le code est à remplacer en remplaçant USERNAME par le nom d'utilisateur de votre machine et importer les modules qui sont tout en haut de votre fichier important )

Capture 8

Voilà le tuto est terminé pour le tester il faut désactiver les fonctions oRequestHandler et modifier sHtmlContent en remplaçant oRequestHandler.request() par bypass_cloudflare(sUrl) sUrl est le nom de la fonction qui a l'url du site donc ça peut être différent dans certains cas

Capture 11

N'hésitez pas à faire un VSlog() pour voir si il récupère le contenu html du site

Partie explication sur l'après du tuto pour les appareils non pris en charge :

Pour Android , Xbox, apple Tv, et Ios non ça ne change pas Beaucoup trop compliqué à mettre en place et quasiment impossible de le faire fonctionner pour un utilisateur lambda Pour Mac Il y a pas grand chose de différence le seul truc qui me coince c'est la place qu'il faut dans le module du coup je vous donnerait plusieurs lien(en dessous ) pour faire démarrer selenium sans trop de problème sur votre Mac si vous êtes assez courageux (Par contre va falloir modifier vous même j'ai pas de mac pour testé )
Pour les autres navigateur je mettrais aussi quelque lien(en dessous) pour les utiliser

Partie Bonus : Explication de la fonction

driverPath = get_driver_path('chromedriver') : l'endroit où est stocker l'exécutable de chromedriver Normalement ce n'est pas comme ça mais le module de selenium a une petite touche personnalisé options = webdriver.ChromeOptions() : On appelle les fonctions pour Chrome options.add_argument("user-data-dir=C:\cookie") : On ajoute une options pour Chrome là par exemple c'est pour enregistrer les données comme le cache ,formulaire , cookie etc... (Update: Pas Obligatoire mais intéressant pour gagner du temps ) (Important car sinon cloudflare peut devenir très embêtant voir même provoquer des bugs donc désolé pour ceux qui tiennent à la confidentialité ) driver = webdriver.Chrome(driverPath, chrome_options=options) : Là on dit à l'exécutable de prendre en compte les options options.headless = False : Là c'est pour dire si vous voulez voir le navigateur ou pas False = oui True = non driver.get(url) : Il ouvre l'url que vous avez donné time.sleep(10) : C'est le temps qui correspond avant de fermer le navigateur en seconde là par exemple c'est 10 secondes page_source = (driver.page_source).encode('utf-8', errors='replace') : Il garde en mémoire le site en UTF-8 et remplace par un point d'interrogation en cas d'erreur (Sinon problème avec l'ascii ) driver.close() : Il ferme le navigateur et l'exécutable chromedriver print(page_source) : Il enregistre dans le presse papier le site sHtmlContent = page_source : sHtmlContent contient la copie du site return sHtmlContent : On sort le résultat de la fonction pour l'utiliser

Merci à @nkvoronov pour le module original https://github.com/nkvoronov/script.module.selenium Merci à la communauté de Vstream de continuer le développement

J'espère que le tutoriel reste facile à comprendre et que ça ne soit pas trop compliqué encore une fois je suis désolé pour les fautes d'orthographe il est très tard donc je ne fais pas trop attention à mes fautes

PS: Ceux qui veulent tester pour contourner Recaptcha malheureusement impossible Recaptcha est très intelligent donc il détecte que c'est un programme automatique donc pour l'instant aucune solution (Hcaptcha non testé par contre) PS-2 : Le module est modifié de l'original il y a la dernière version de selenium + chromedriver PS-3 : Techniquement selenium est compatible python 3 mais la touche personnalisé non donc je déconseille de le tester sur kodi 19 (la touche personnalisé ne vient pas de moi mais de l'auteur original )

Si vous avez des questions ou des problèmes n'hésitez pas à me le dire

TmpName commented 4 years ago

Loool Put1 mais vous allez faire un concours de tuto avec @sizanic ?

Pour le coup, j'ai toujours pas ma machine pr tester, mais ca fait bien avancer ^^.

Et ce serait quoi le mieux

Ovni-crea commented 4 years ago

@TmpName Je sais pas c'est comme tu veux si c'est juste pour cloudflare et les cookies tu peux choisir la deuxième options ou si tu veux carrément te servir pour récupérer la page complète tu choisis la première options (sachant que oRequesthandler ne servira plus à rien )

razorex commented 4 years ago

@TmpName au moins @sizanic corrigera ces fautes d'orthographes.... Mais beau travail. Il reste juste juste à porté ça sur tout les OS. Bah oui j'ai une box android...sniff

Ovni-crea commented 4 years ago

@razorex Merci de me le rappeler j'avais oublié de corrigé mes fautes pour android je vais me renseigner je pense pas que ça doit pas être compliqué (enfin j'espère )

Edit: Je viens de me renseigner on ne peut pas sur android et ios à cause de l'architecture et le fonctionnement

TmpName commented 4 years ago

Ha mince, ca ca va en faire crier ! C'est la lib qui passe pas ou chrome ?

Arias800 commented 4 years ago

C'est pas possible a cause du sandboxing entre les applications. En gros Kodi ne peut pas contrôler le navigateur.

Ovni-crea commented 4 years ago

@Arias800 C'est exactement ça du coup impossible de l'utiliser

Ovni-crea commented 4 years ago

Bon j'ai testé du coté de linux chrome fonctionne bien mais le problème c'est à print il y a une erreur ascii je suis sur ubuntu 20 en émulation si quelqu'un à une idée du pourquoi je le remercie

milkibreizh commented 4 years ago

@Ovni-crea même issu j'ai été obligé d'encoder driver.page_source pour que la fonction marche

Ovni-crea commented 4 years ago

@milkibreizh Merci j'ai réglé le souci maintenant

milkibreizh commented 4 years ago

bonjours oui dans l'exemple cité plus haut cela (peu) générer un défaut car page_source = (driver.page_source).encode('utf-8') va lever une exception car la valeur de le fonction réelle est encode('utf-8','strict' )-valeur par defaut

on peu utiliser "replace" "backslashreplace" "ignore" qui ne lève pas d'exception mais qui va modifier le vrai string d'origine ou procéder en 2 étapes décoder pour encoder par la ensuite pour être sûr de garder les données d'origine...

Ovni-crea commented 4 years ago

@milkibreizh merci j'ai choisi "replace" il m'a l'air d'être le plus convaincant

milkibreizh commented 4 years ago

@Ovni-crea re bonjour j'ai un problème pour faire la dernière requête car elle est est de type réfère avec post data je n'ai pas vu d'implantation du web drivers tu n'aurais pas une petite idée ?

sinon faire comme le disais TmpName prendre les cookies à la première page puis utiliser la fonction classique cRequestHandler mais je ne sais pas comment faire pour les cookies?

merci

TmpName commented 4 years ago

Pour les cookies, il y a une fonction driver.manage()

driver.manage().getCookies();   // Return The List of all Cookies
driver.manage().getCookieNamed(arg0);  //Return specific cookie according to name
driver.manage().addCookie(arg0);   //Create and add the cookie
driver.manage().deleteCookie(arg0);  // Delete specific cookie
driver.manage().deleteCookieNamed(arg0); // Delete specific cookie according Name
driver.manage().deleteAllCookies();  // Delete all cookies

Par contre pour les requetes POST ca a l'air plus tendu, il y en a meme qui utilse une surcouche pour ca, tellement c'est la mort https://pypi.org/project/selenium-requests/

Ovni-crea commented 4 years ago

@milkibreizh bah le problème c'est qu'on ne peut pas le mettre dans cRequesthandler Ios et Android ne supporte pas du tout selenium (impossible de mettre en place ) Il y a qu'une seule solution c'est de proposer un choix dans les paramètres de Vstream comme par exemple utiliser selenium oui ou non (d'ou le fait que le module est externe )

milkibreizh commented 4 years ago

@TmpName et @Ovni-crea ok merci pour les infos

Ovni-crea commented 4 years ago

@milkibreizh De rien d'ailleurs j'arrive pas à utiliser leurs gestion de cookies j'ai bien copié les cookies pour l'enregistrer mais il y a l'ancien module cloudscraper qui charge en même temps Edit : Ah oui j'ai oublié le post data ça par contre c'est un peu chiant

milkibreizh commented 4 years ago

@ j'aurais bien voulu t'aider mais là je suis incompétent

essaye tout de mème de passer un bon weekend car moi maintenant quand je vais dans mon navigateur et que je vois cloudfare cela me donne des vertiges :smile:

TmpName commented 4 years ago

Je viens de regarder la lib selenium-requests ne fait q'un fichier, donc facilement integrable dans Vstream. Elle permet ca

from seleniumrequests import Firefox

webdriver = Firefox()
response = webdriver.request('POST', 'url here', data={"param1": "value1"})
print(response)

Le code a plusieurs année, mais le mec bosse encore dessus.

Ovni-crea commented 4 years ago

@TmpName ok finalement ce n'est pas trop compliqué @milkibreizh oh ne t'inquiète pas moi aussi je ne suis pas doué c'est juste que selenium est un peu simple à comprendre

noway80 commented 4 years ago

Requirements idna==2.1 py==1.4.31 pytest==3.0.3 requests==2.11.1 requests-file==1.4.1 selenium==3.0.1 selenium-requests==1.3 six==1.10.0 tldextract==2.0.2

Ovni-crea commented 4 years ago

@noway80 merci je viens de voir qu'il faut importer pas mal de module perso j'arrête ce soir j'attendrais son avis à @TmpName si je dois continuer quand même

TmpName commented 4 years ago

Arf, je les avais pas vu:

tldextract > remplacable idna > pas vu

Six > Six is a Python 2 and 3 compatibility library. It provides utility functions for smoothing over the differences between the Python versions with the goal of writing Python code that is compatible on both Python versions

Apparement c'est juste une lib qui facilite les transitions python2 / python 3, amon avis c'est remplacable aussi

requests==2.11.1 selenium==3.0.1 selenium-requests==1.3 Celles la ca doit etre bon.

Les autres pas encore vues.

Cet apres midi, j'essais un test de sa lib allegé.

TmpName commented 4 years ago

Alors essayes avec ce fichier https://github.com/TmpName/Fichier_en_vrac/blob/master/SeleniuumRequestLight.py

J'ai viré pas mal de dependance et ca marche avec 1 seul fichier. Exactemant les memes commande que pour la lib python Request.

Pour tester tu mets ce fichier au meme endroit qu'un autre contenant


from SeleniuumRequestLight import Firefox

webdriver = Firefox()
response = webdriver.request('GET', 'https://www.google.com/?hl=fr')
print(response.text)

Maintenant les mauvaises nouvelles

noway80 commented 4 years ago

pour chrome options = webdriver.ChromeOptions() options.headless = False browser = webdriver.Chrome("chromedriver", options=options) headless a True pour silent mode mais je laisse a false pour telecharger dlc par exemple

pour fire options = Options() options.headless = True browser = webdriver.Firefox(options=options)

Ovni-crea commented 4 years ago

@TmpName C'est normal qu'il ne trouve pas le module request ?

milkibreizh commented 4 years ago

@TmpName j'ai pas de souci la lib est bien reconnu par kodi(et non pas eclipse)
import requests

r = requests.get('https://github.com/') VSlog("ok if code=200 result="+str(r.status_code)) result ok if code=200 result=200

TmpName commented 4 years ago

@Ovni-crea non c'est pas normal, c'est une lib standard qui est deja sur kodi aussi (ou alors je l'ai installé sans me souvenir, mais on s'en sert deja pour la vielle version de cloudflare)

milkibreizh commented 4 years ago

@TmpName non tu as raison pour la lib de cloudflare mais j'ai surtout oublié de te demander si tu faisais tes testes qu'avec eclipse (et donc importer lib request+selenium sans kodi))

ou directement avec vstream les lib de kodi 18 tu n'as pas de résultats avec r = requests.get (urlvalide) other request(s)? Autrement dans kodi tu as les propriétés de dépendances de vstream information /dependencies où tu as la version de la lib request

si tu utilises kodi je crois que tu est obligé de modifier le fichier SeleniumRequestLight.py pour 2.7 par exemple headers = requests.structures.CaseInsensitiveDict(self.headers) #P3 headers = requests.structures.CaseInsensitiveDict(self.headers.dict) #P2 trouverles fonctions urlparse équivalentes utilisées pour pyhton3 import urllib.parse as urlparse #P3 =>? import urllib.quote

autrement si je dis des sottises cela est fort probable et je m'en excuse à l'avance

milkibreizh commented 4 years ago

oups @Ovni-crea

cela fais deux fois que je me trompe avec @TmpName

milkibreizh commented 4 years ago

@TmpName je viens d'essayer et je n'ai pas réussi a faire fonctionner ton module light tu n'aurais pas un exemple de requête simple class Chrome(RequestsSessionMixin, _Chrome): pass

c'est quoi une sorte d'interface pour sélectionner le driver il faut implémenter ? je suis trop débutant pour comprendre merci

milkibreizh commented 4 years ago

@TmpName désolé de polluer l'issue maintenant je viens de comprendre l’intérêt des classe vides bonne nuit

Ovni-crea commented 4 years ago

@milkibreizh ça fait rien au moins tu essayes de comprendre Pour revenir à la question le problème c'est quand j'écris response = webdriver.request Dans le log c'est écrit qui ne reconnais pas le module request et du coup je suis bloqué à cette étapes je me demande si c'est pas à cause de la fameuse touche personnalisé qui provoque le soucis ou kodi lui même car dans le fichier de @TmpName il importe correctement requests

TmpName commented 4 years ago

Oui y a du taff pr adapter cette fonction a kodi (qui tourne sous P2).

Sinon la je comprend pas le bug, dans mon exemple

from SeleniuumRequestLight import Firefox
webdriver = Firefox()
response = webdriver.request('GET', 'https://www.google.com/?hl=fr')

Dans le fichier SeleniuumRequestLight

class Firefox(RequestsSessionMixin, _Firefox):
    pass

Et j'ai bien

def request(self, method, url, **kwargs):

ligne 157 dans la classe "class RequestsSessionMixin(object):"

Mais la, je suis pas sur de pouvoir y jeter un oeil avant ce WE.

TmpName commented 4 years ago

En python 3 > from urllib.parse import urlparse En python 2 > from urlparse import urlparse

self.wfile.write(''.encode()) #P3 self.wfile.write('') #P2 (non testé)

milkibreizh commented 4 years ago

@TmpName ok merci pour le urlparse http://python3porting.com/stdlib.html

razorex commented 4 years ago

@Ovni-crea c'est une erreur de frappe??? une fois tu met requests et une autre request!! Dsl j'ai vu que @TmpName t'avais répondu

Ovni-crea commented 4 years ago

@razorex c'est pas grave ^^

shmoxy75 commented 4 years ago

J'ai trouvé ça si ça peut vous intéresser, je ne m'y connais pas en python mais si j'ai bien compris ça marche même sous Android:

http://appium.io/

TmpName commented 4 years ago

Ben tu peux lancer un navigateur avec , mais je sais pas si tu peux recuperer le code html apres.

Ovni-crea commented 4 years ago

@TmpName @shmoxy75 Vous pouvez pas je me suis déjà renseigné dessus il faut exécuté des commandes adb donc tu auras besoin toujours d'un pc pour exécuter le code donc ce n'est pas totalement autonomes malheureusement PS: En plus il faut coder en java pour android ou kotlin pour ios

milkibreizh commented 4 years ago

@Ovni-crea tu as résolu ton problème ? je n'ai pas de bug (sur win 10) sauf que j'ai passé le path +option avec la lib selenium pour initialisé Chrome() avec des paramètres

webdriver =Chrome(driverPath, chrome_options=options) response = webdriver.request('GET', 'https://ww1.valide.url')

pas de problème constaté avec le request implanté dans RequestsSessionMixin

Ovni-crea commented 4 years ago

@milkibreizh Non mon problème n'est toujours pas réglé j'en suis sûr c'est un truc tout con ^^ j'envoie des screens 4 3 2 1

milkibreizh commented 4 years ago

@Ovni-crea pourquoi importe tu deux foix Chrome je n'ai pas importé chrome de la lib de sélénium si ton progamme instancie webdriver.Chrome() bah c'est pas bon :-(

car request a besoin d' une instance chrome () de selenium request light pas de selenium import selenium.webdriver import chrome est de trop

et là je peux pas tester

noway80 commented 4 years ago

from selenium.webdriver.support.ui import WebDriverWait from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By

url = "https://www.extreme-download.video/films-new-hdlight/new-hdlight-720p/"

options = webdriver.ChromeOptions() options.headless = True browser = webdriver.Chrome("chromedriver", options=options) browser.get(url)

delai attente cloudeflare limite a 10 s

element = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.NAME, "description")))

dict cookies

print({cookie['name']:cookie['value'] for cookie in browser.get_cookies()})

si t'as selenium

milkibreizh commented 4 years ago

@Ovni-crea oups et j'avais pas vu aussi driver = Chrome(driverPath, chrome_options=options) response = driver.request('GET', 'https://www et non response=driver.webdriver

le webdriver importé de selenium ne sert que pour le path et les options qui sert a initialiser le driver chrome de selenium request light bah du coup c'est peu être cela le bug bonne chance !

Ovni-crea commented 4 years ago

@milkibreizh c'est bon j'ai enfin réussi à le faire fonctionnait mais tu me conseille de faire quoi d'autre sur la fonction car j'ai une erreur 503 avec POST pour tirexo 5

Arias800 commented 4 years ago

Alors deja, mettre un time.sleep fixe c'est une erreur car le temps que demande Cloudflare est variable.

Ovni-crea commented 4 years ago

@Arias800 Je sais mais c'est une moyenne en général ça prend 10 seconde pour passer la protection et charger la page correctement

noway80 commented 4 years ago

element = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.NAME, "description"))) Pour ça driverwait , est max à 10s dans l exemple