4

the purpose of this script is to use python to login on a website with login and pass

launching the script with login and pass as parameters.

[vegasus@Ph3NyX:~]$python3 grabbit.py mylogin mypass

Traceback (most recent call last):
  File "/Users/vegasus/PycharmProjects/Lesson_Python/grabbit.py", line 102, in <module>
    WebLogin('mylogin', 'mypass')
  File "/Users/vegasus/PycharmProjects/Lesson_Python/grabbit.py", line 61, in __init__
    response = self.login()
  File "/Users/vegasus/PycharmProjects/Lesson_Python/grabbit.py", line 82, in login
    response = self.opener.open(login_url.encode(), login_data.encode())
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 444, in open
    req.data = data
AttributeError: 'bytes' object has no attribute 'data'

here is the script :

import urllib, urllib.request, urllib.parse
import http.cookiejar
import sys

class WebLogin(object):

    def __init__(self, username, password):

        # url for website we want to log in to
        self.base_url = 'https://www.mywebsite.com'
        # login action we want to post data to
        # could be /login or /account/login or something similar
        self.login_action = '/en/login'
        # file for storing cookies
        self.cookie_file = 'login.cookies'

        # user provided username and password
        self.username = username
        self.password = password

        # set up a cookie jar to store cookies
        self.cj = http.cookiejar.MozillaCookieJar(self.cookie_file)

        # set up opener to handle cookies, redirects etc
        self.opener = urllib.request.build_opener(
            urllib.request.HTTPRedirectHandler(),
            urllib.request.HTTPHandler(debuglevel=0),
            urllib.request.HTTPSHandler(debuglevel=0),
            urllib.request.HTTPCookieProcessor(self.cj)
        )

        # pretend we're a web browser and not a python script
        self.opener.addheaders = [('User-agent',
            ('Mozilla/4.0 (compatible; MSIE 6.0; '
            'Windows NT 5.2; .NET CLR 1.1.4322)'))
        ]

        # open the front page of the website to set and save initial cookies
        response = self.opener.open(self.base_url)
        self.cj.save()

        # try and log in to the site
        response = self.login()

        print (response.read())

    # method to do login
    def login(self):

        # parameters for login action
        # may be different for different websites
        # check html source of website for specifics
        login_data = urllib.parse.urlencode({
            'username' : self.username,
            'password' : self.password,
            'remember_me' : True
        })

        # construct the url
        login_url = self.base_url + self.login_action
        # then open it
        response = self.opener.open(login_url.encode(), login_data.encode())
        # save the cookies and return the response
        self.cj.save()
        return response


if __name__ == "__main__":

    args = sys.argv

    # check for username and password
    if len(args) != 3:
        print ("Incorrect number of arguments")
        print ("Argument pattern: username password")
        exit(1)

    username = args[1]
    password = args[2]

    # initialise and login to the website
    WebLogin('mylogin', 'mypass')

1 Answer 1

2

The problem is that self.opener.open expects its first argument to be of type str. So when calling that function, don't call str.encode on that argument, just pass it as type str.

Note: the reason for this error is because self.opener.open does an isinstance check to see if it is a string, and if it is then it converts them to the required data type. Otherwise, it assumes that it is already the required type (which has a field data).


Edit: The above previously described both arguments as needing to be of type str, that is false. The first argument has to be an str while the second argument has to either None or bytes.

Sign up to request clarification or add additional context in comments.

6 Comments

hello, when I passed a str I got this : response = self.opener.open(login_url, login_data) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 453, in open req = meth(req) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/request.py", line 1120, in do_request_ raise TypeError(msg) TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
It's like a snake eating its own tail. :-(
@ClarkKenty Sorry for the confusion, see my edit to clear that up.
this response = self.opener.open(login_url, login_data.encode()) works !! thanks a lot!!!!!!! I understand now.
sorry again. I noticed that my response.read() is <class 'bytes'> : looks like -> "b'<!DOCTYPE html>\r\n\r\n<html ..." So how to get str instead of a bytes ? thanks .
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.