mechanize Documentation

repository·master·Indexed 20 days ago

https://github.com/python-mechanize/mechanize

A Python library for automating interactions with HTTP web servers through stateful programmatic web browsing. It provides a Browser class to manage sessions, navigate URLs, and interact with HTML forms via a specialized Control hierarchy. The library handles cookie management and HTTP responses but does not support JavaScript.

Tokens
4.4K
Snippets
13
Records
23
Agent score
73%

What's inside mechanize

  1. Overview of mechanize features

    master

    mechanize is a library for stateful programmatic web browsing in Python. It provides several high-level automation features:

    • mechanize.Browser: Implements the urllib2.OpenerDirector interface, allowing it to open URLs beyond just http.
    • Form Handling: Easy HTML form filling.
    • Link Navigation: Convenient parsing and following of links.
    • Browser History: Support for .back() and .reload() methods.
    • HTTP Headers: Automatic and optional handling of the Referer header.
    • Compliance: Automatic observance of robots.txt and automatic handling of HTTP-Equiv and Refresh headers.
  2. Understand the HTML Forms API hierarchy

    master
    In mechanize, HTML forms are represented by the mechanize.HTMLForm class. A form is treated as a collection of individual controls. These controls are organized in a class hierarchy where mechanize.Control serves as the base class for all specific input types. When interacting with a form, you manipulate these controls to simulate user input (like typing text, selecting checkboxes, or uploading files) before submitting the form.
  3. Handle websites that require JavaScript

    master

    mechanize does not support JavaScript. If the site you are automating relies on JavaScript for content creation, form submission, or cookie setting, consider these strategies:

    1. Emulate the logic: Determine what the JavaScript is doing and replicate it in Python. For example, if it sets a cookie, use mechanize.Browser.set_simple_cookie() to set it manually.
    2. Manual Request Emulation: Use browser developer tools to inspect the exact HTTP requests sent by a real browser, then use mechanize.Request to recreate those requests and open them with mechanize.Browser.open().
    3. Use a Browser Automation Framework: As a last resort, use a library that drives a headless browser (like Selenium or Playwright) which can execute JavaScript, though these are slower and more resource-intensive than mechanize.
  4. Manage cookies correctly with mechanize

    master

    When using mechanize.urlopen() or OpenerDirector.open(), the module automatically handles cookie extraction and addition. Do not manually call .extract_cookies() or .add_cookie_header() on a cookie object if you are using these high-level functions, as it can lead to errors.

    Persisting cookies with ignore_discard

    When using .save() to write cookies to a file, or .load()/.revert() to read them, single-session cookies will expire unless you explicitly set the ignore_discard argument to True. If you find cookies disappearing after a save/load cycle, ensure this argument is used.

    JavaScript limitations

    Mechanize does not support cookies set via JavaScript.

    import mechanize
    
    cj = mechanize.LWPCookieJar()
    opener = mechanize.build_opener(mechanize.HTTPCookieProcessor(cj))
    mechanize.install_opener(opener)
    
    r = mechanize.urlopen("http://foobar.com/")
    # Use ignore_discard and ignore_expires to prevent session cookies from being lost
    cj.save("/some/file", ignore_discard=True, ignore_expires=True)
  5. Handle thread safety with mechanize Browser instances

    master

    While the global mechanize.urlopen() and mechanize.urlretrieve() functions are thread-safe, individual mechanize.Browser instances are not thread-safe.

    To use a browser instance across multiple threads, you must clone it using copy.copy(browser_object). The clone will share the same thread-safe cookie jar and the same settings/handlers as the original, but all other state is not shared, making the clone safe for use in a separate thread.

    import copy
    # Assuming 'browser' is an existing mechanize.Browser instance
    thread_safe_browser = copy.copy(browser)
  6. Quickstart with mechanize

    master

    To perform stateful web browsing, instantiate a mechanize.Browser() object. You can navigate to URLs, follow links using regular expressions or link objects, select HTML forms, and fill them using dictionary-like syntax before submitting. The browser maintains a history, allowing you to use .back() and .reload() to navigate through previous responses.

    import re
    import mechanize
    
    br = mechanize.Browser()
    br.open("http://www.example.com/")
    # follow second link with element text matching regular expression
    response1 = br.follow_link(text_regex=r"cheese\s*shop", nr=1)
    print(br.title())
    print(response1.geturl())
    print(response1.info())  # headers
    print(response1.read())  # body
    
    br.select_form(name="order")
    # Browser passes through unknown attributes (including methods)
    # to the selected HTMLForm.
    br["cheeses"] = ["mozzarella", "caerphilly"]
    # Submit current form. Browser calls .close() on the current response on navigation
    response2 = br.submit()
    
    # print currently selected form (don't call .submit() on this, use br.submit())
    print(br.form)
    
    response3 = br.back()  # back to cheese shop (same data as response1)
    # the history mechanism returns cached response objects
    # we can still use the response, even though it was .close()d
    response3.get_data()  # like .seek(0) followed by .read()
    response4 = br.reload()  # fetches from server
    
    for form in br.forms():
        print(form)
    # .links() optionally accepts the keyword args of .follow_/.find_link()
    for link in br.links(url_regex="python.org"):
        print(link)
        br.follow_link(link)  # takes EITHER Link instance OR keyword args
        br.back()
  7. Inspect and interact with HTML forms

    master

    To identify control names and values in a form, you can use print(form) or inspect the HTMLForm.items attribute of a mechanize.HTMLForm instance.

    For interacting with controls using human-readable labels instead of technical names, use the by_label arguments in various methods, or use .get_value_by_label() and .set_value_by_label() on ListControl objects.

  8. Configure Browser policies and proxies

    master

    You can customize the behavior of mechanize.Browser by configuring proxies, authentication, and request headers.

    • Proxies: Use set_proxies() to define HTTP/FTP proxy mappings. Use add_proxy_password() for proxy authentication.
    • Authentication: Use add_password() to provide credentials for specific website URLs.
    • Headers: Use finalize_request_headers (a lambda or function) to inject or modify headers on all outgoing requests.
    • Security: Use set_ca_data() with an unverified SSL context to bypass SSL certificate verification.
    import mechanize
    import ssl
    
    br = mechanize.Browser()
    # Explicitly configure proxies
    br.set_proxies({"http": "joe:password@myproxy.example.com:3128",
                    "ftp": "proxy.example.com",
                    })
    # Add HTTP Basic/Digest auth username and password for HTTP proxy access.
    br.add_proxy_password("joe", "password")
    # Add HTTP Basic/Digest auth username and password for website access.
    br.add_password("http://example.com/protected/", "joe", "password")
    # Add an extra header to all outgoing requests
    br.finalize_request_headers = lambda request, headers: headers.__setitem__(
      'My-Custom-Header', 'Something')
    # Do not verify SSL certificates
    br.set_ca_data(context=ssl._create_unverified_context(cert_reqs=ssl.CERT_NONE))
  9. Enable logging for mechanize

    master

    To debug mechanize behavior, you can enable logging to stdout. You can control the granularity of the logs by targeting specific logger names:

    • "mechanize": Enables all logging.
    • "mechanize.cookies": Logs why cookies are accepted, rejected, or returned (requires DEBUG level).
    • "mechanize.http_responses": Logs HTTP response body data.
    • "mechanize.http_redirects": Logs HTTP redirect information.
    import sys, logging
    
    logger = logging.getLogger("mechanize")
    logger.addHandler(logging.StreamHandler(sys.stdout))
    logger.setLevel(logging.DEBUG)
  10. Install mechanize

    master

    You can install mechanize for normal usage via pip3. For development purposes, you can install it in editable mode from the source repository.

    # Normal usage
    pip3 install mechanize
    
    # Development usage
    git clone https://github.com/python-mechanize/mechanize.git
    cd mechanize
    pip3 install -e .
  11. Prevent HTTP response truncation

    master
    In mechanize.Browser, response data is fetched lazily. If you navigate to a new URL before the current response data has been fully consumed, the data may be truncated. To ensure you have the full response, call response.get_data() before performing any subsequent navigation.