关于python:爬虫系列穿越网页表单与登录窗口进行采集二

8次阅读

共计 5589 个字符,预计需要花费 14 分钟才能阅读完成。

上一期咱们解说了 Python Requests 库、提交一个根本表单、HTML 相干控件等内容。

本篇文章咱们接着上一期文章介绍通过 Python Requests 提交文件和图像、解决登录 cookie、HTTP 根本接入认证以及其余表单相干问题。

提交文件和图像

尽管上传文件在网络上很广泛,然而对于网络数据采集其实不太罕用。然而,如果你想为本人网站的文件上传一个测试实例,也能够通过 Python Requests 库实现。不管怎么说,把握工作原理总是有用的。

上面是一个文件上传的源代码示例:

<label class="UploadPicture-wrapper">
    <input type="file" accept="image/png,image/jpeg" class="UploadPicture-input">
    <button type="button" class="Button UserCoverEditor-simpleEditButton DynamicColorButton DynamicColorButton--dark">
        <span style="display: inline-flex; align-items: center;">​</span> 编辑封面图片
    </button>
</label>

文件上传表单除了 <input> 标签里有一个 type 属性是 file,看起来和上一篇文章中的文字字段并没有什么两样。其实,Python Requests 库对这种表单的解决形式和之前十分类似:

import requests


def upload_image():
    files = {'uploadFile': open('files/2fe7243c7c113fad443b375a021801eb6277169d.png', 'rb')}
    r = requests.post("http://pythonscraping.com/pages/processing2.php", files=files)
    print(r.text)


if __name__ == '__main__':
    upload_image()

须要留神,这里提交给表单字段 uploadFile 的值不肯定是一个简略的字符串,而是一个应用 open 函数关上的 Python 文件对象。在这个例子当中,咱们提交了一个保留在咱们电脑上的图像文件,文件门路是绝对于这个 Python 程序所在的地位。

解决登录和 cookie

到此为止,咱们介绍过的大多数表单都容许你向网站提交信息,或者让你在提交表单后立刻看到想要的页面信息。那么,那些表单和登录表单(当你浏览网站时让你放弃“已登录“状态)有什么不同?

大多数的古代网站应用的是 cookie 跟踪用户是否已登录的状态信息。一旦网站验证了你的登录权证,他就会将它们保留在你浏览器的 cookie 中,外面通常蕴含一个服务器生成的令牌,登录无效时限和登录状态追踪信息。网站会把这个 cookie 当作信息验证的凭据,在你浏览网站的每个页面时出示给服务器。在 20 世纪 90 年代中期宽泛应用 cookie 之前,保障用户平安验证并追踪用户是网站上的一大问题。

尽管 cookie 为网络开发者解决了大问题,但同时却为网络爬虫带来了大问题。你能够一整天只提交一次登录表单,然而如果你没有始终关注表单后回传给你的那个 cookie,那么一段时间当前再次拜访新页面时,你的登录状态就会失落,须要从新登录。

当初咱们有一个博客的治理后盾,咱们须要登录能力公布文章和上传图片,上面咱们通过应用 Python Requests 模仿登录,并追踪 cookie,上面是代码示例:

import requests
from bs4 import BeautifulSoup
from requests import Session, exceptions

from utils import connection_util

class GetCookie(object):
    def __init__(self):
        self._session = Session()
        self._init_connection = connection_util.ProcessConnection()

    def get_cookie_by_login(self):
        # 另外一个 session 中
        get_token=self.request_verification_token()
        if get_token:
            params = {'__RequestVerificationToken': get_token, 'Email': 'abc@pdf-lib.org',
                    'Password': 'hhgu##$dfe__e',
                    'RememberMe': True}
            r = self._session.post('https://pdf-lib.org/account/admin', params)
            # 如果应用 request_verification_token 此处会呈现 500 谬误
            if r.status_code == 500:
                print(r.content.decode('utf-8'))
            print('Cookie is set  to:')
            print(r.cookies.get_dict())
            print('--------------------------------')
            print('Going to post article page..')
            r = self._session.get('https://pdf-lib.org/Manage/ArticleList', cookies=r.cookies)
            print(r.text)

    def request_verification_token(self):
        # 此处依然会获取所须要的内容
        get_content = self._init_connection.init_connection('https://pdf-lib.org/account/admin')
        if get_content:
            try:
                get_token = get_content.find("input", {"name": "__RequestVerificationToken"}).get("value")
            except Exception as e:
                print(f"ot unhandled exception {e}")
                return False
            return get_token


if __name__ == '__main__':
    get_cookie = GetCookie()
    get_cookie.get_cookie_by_login()

下面的代码咱们向登录页面发送相干参数,作用就是模仿咱们输出用户名与明码登录页面。而后咱们从申请中获取 cookie,打印登录后果。

对于简略的页面咱们能够这样解决没有问题,然而如果网站比较复杂,他常常会暗自调整 cookie,或者如果咱们一开始都不想应用 cookie,应该怎么解决呢?Requests 库的 session 函数能够完满的解决这些问题:

import requests
from bs4 import BeautifulSoup
from requests import Session, exceptions

from utils import connection_util

class GetCookie(object):
    def __init__(self):
        self._session = Session()
        self._init_connection = connection_util.ProcessConnection()

    def get_cookie_by_login(self):
        # 另外一个 session 中
        get_token=self.get_request_verification_token()
        if get_token:
            params = {'__RequestVerificationToken': get_token, 'Email': 'abc@pdf-lib.org',
                    'Password': 'hhgu##$dfe__e',
                    'RememberMe': True}
            r = self._session.post('https://pdf-lib.org/account/admin', params)
            # 如果应用 request_verification_token 此处会呈现 500 谬误
            if r.status_code == 500:
                print(r.content.decode('utf-8'))
            print('Cookie is set  to:')
            print(r.cookies.get_dict())
            print('--------------------------------')
            print('Going to post article page..')
            r = self._session.get('https://pdf-lib.org/Manage/ArticleList', cookies=r.cookies)
            print(r.text)

    def get_request_verification_token(self):
        # 连贯网站
        try:
            headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"}
            html = self._session.get("https://pdf-lib.org/Account/Login", headers=headers)
        except (exceptions.ConnectionError, exceptions.HTTPError, exceptions.Timeout) as e:
            return False
        try:
            bsObj = BeautifulSoup(html.text, features='html.parser')
        except AttributeError as e:
            return False
        if bsObj:
            try:
                get_token = bsObj.find("input", {"name": "__RequestVerificationToken"}).get("value")
            except Exception as e:
                print(f"ot unhandled exception {e}")
                return False
            return get_token


if __name__ == '__main__':
    get_cookie = GetCookie()
    get_cookie.get_cookie_by_login()

在这个例子当中,会话(session)对象(调用 requests.Session() 获取)会持续跟踪会话信息,像 cookie,header,甚至是包含运行 HTTP 协定的信息,比方 HTTPAdapter(为 HTTP 和 HTTPS 的链接会话提供对立接口)。

Requests 是一个十分给力的库,程序员齐全不用费脑子,也不必写代码,可能只是逊色于 Selenium,尽管写网络爬虫的时候,你可能像撒手让 Requests 库替本人做所有的事件,然而继续关注 cookie 的状态,把握它们能够管制的范畴是十分重要的。这样能够防止苦楚的调试和追寻网站的异样,节俭很多工夫。

HTTP 根本接入认证

在创造 cookie 之前,解决网站登录最罕用的办法就是应用 HTTP 根本接入认证(HTTP basic access authentication)。当初曾经不罕用了,然而咱们偶然还是会见到它,尤其是在一些安全性较高的网站或公司外部网站,以及一些 API 上应用。

上面是一个根本接入认证界面截图:

和后面的例子一样,须要输出用户名和明码能力登录。

Requests 库有一个 auth 模块专门用来解决 HTTP 认证:

import requests
from requests.auth import HTTPBasicAuth

def http_auth():
    auth = HTTPBasicAuth('user', '1223**%%adw')
    r = requests.post(url="http://www.test.com:3311/", auth=auth)
    print(r.text)

尽管这样看起来是一个一般的 POST 申请,然而有一个 HTTPBasicAuth 对象作为 auth 参数传递到申请当中。显示的后果将是用户名和明码验证胜利的页面(如果验证失败,会是一个回绝接入的页面)。

其余表单问题

表单是网络歹意机器人(malicious bots)热爱的网站切入点。你当然不心愿机器人创立垃圾账号,占用低廉的服务器资源,或者在博客上提交垃圾评论。因而,旧式的网站常常在 HTML 中应用很多安全措施,让表单不能被机器人批量提交数据。

对于验证码的具体内容我不打算在这篇文章中解说(因为文章曾经够长了),前面我将会介绍应用 Python 的图像处理和文本识别方法来详述这部分内容。

如果你在提交表单的时候遇到一些莫名其妙的谬误,或者服务器始终以默认的申请为理由回绝,我在当前的文章中在介绍这些问题。

本文所有的源代码曾经托管于 Github 当中,地址:https://github.com/sycct/Scrape_1_1.git

如果有任何问题,欢送大家 issue。

正文完
 0