上一期我们讲解了PythonRequests库,提交一个基本的表单,HTML相关控件等,本篇我们继续上篇介绍通过PythonRequests提交文件和图片,处理登录cookie,HTTP基本访问认证,以及其他与表单相关的问题。提交文件和图像虽然上传文件在互联网上很常见,但它并不常用于网络数据收集。但是,如果您想为自己的网站上传文件的测试实例,可以使用PythonRequests库来完成。无论如何,了解事物的运作方式总是有用的。以下是文件上传的源代码示例:type="button"class="ButtonUserCoverEditor-simpleEditButtonDynamicColorButtonDynamicColorButton--dark">编辑封面图片文件上传表单,除了标签中多了一个type属性,就是file。事实上,PythonRequests库处理这种形式的方式与之前非常相似:http://pythonscraping.com/pages/processing2.php",files=files)print(r.text)if__name__=='__main__':upload_image()需要注意的是这里提交给表单域uploadFile的值不一定是简单的字符串,而是用open函数打开的Python文件对象。在这个例子中,我们提交一个保存在我们电脑上的图片文件,文件路径是相对于Python程序所在位置的。处理登录和cookie到目前为止,我们介绍的大多数表单都允许您向网站提交信息,或者允许您在提交表单后立即看到所需的页面信息。那么,这些表单和登录表单(让您在浏览网站时保持“登录”状态)有什么区别?大多数现代网站使用cookie来跟踪用户是否登录。一旦网站验证了您的登录凭据,它会将它们保存在您浏览器的cookie中,该cookie通常包含服务器生成的令牌、登录有效期和登录状态跟踪信息。当您浏览本网站的每个页面时,本网站将使用此cookie作为信息验证的凭据并呈现给服务器。在20世纪90年代中期广泛使用cookie之前,保持用户的安全身份验证和跟踪用户是网站上的一个大问题。虽然cookie为网络开发人员解决了一个大问题,但它们也为网络爬虫带来了一个大问题。您一天只能提交一次登录表单,但是如果您不注意表单后返回给您的cookie,那么当您在一段时间后访问新页面时,您的登录状态将丢失,您将需要重新登录。现在我们有了一个博客管理后台。我们需要登录才能发表文章和上传图片。接下来,我们使用PythonRequests模拟登录并跟踪cookie。下面是代码示例:importrequestsfrombs4importBeautifulSoupfromrequestsimportSession,exceptionsfromutilsimportconnection_utilclassGetCookie(object):def__init__(self):self._session=Session()self._init_connection=connection_util.ProcessConnection()defget_cookie_by_login(self):#get_token=self.request_verification_token()在另一个会话中ifget_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错误ifr.status_code==500:print(r.content.decode('utf-8'))print('Cookie设置为:')print(r.cookies.get_dict())print('--------------------------------')print('要发布文章页面..')r=self._session.get('https://pdf-lib.org/Manage/ArticleList',cookies=r.cookies)print(r.text)defrequest_verification_token(self):#这里还是会获取到需要的内容get_content=self._init_connection.init_connection('https://pdf-lib.org/account/admin')如果get_content:try:get_token=get_content.find("input",{"name":"__RequestVerificationToken"}).get("value")exceptExceptionase:print(f"otunhandledexception{e}")returnFalsereturnget_tokenif__name__=='__main__':get_cookie=GetCookie()get_cookie.get_cookie_by_login()上面的代码我们发送登录页面发送相关参数,作用是模拟我们输入用户名和密码登录页面,然后从请求中获取cookie,打印登录结果。对于简单的页面,我们这样做是没有问题的,但是如果网站比较复杂,他经常偷偷调整cookies,或者我们一开始不想用cookies,那我们应该怎么处理呢?Requests库的session函数可以完美解决这些问题:importrequestsfrombs4importBeautifulSoupfromrequestsimportSession,exceptionsfromutilsimportconnection_utilclassGetCookie(object):def__init__(self):self._session=Session()self._init_Connection.connection=connection()defget_cookie_by_login(self):#get_token=self.get_request_verification_token()在另一个会话中ifget_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,一个如果r.status_code==500,这里会出现500错误:print(r.content.decode('utf-8'))print('Cookieissetto:')print(r.cookies.get_dict())print('--------------------------------')print('要发布文章页面..')r=self._session.get('https://pdf-lib.org/Manage/ArticleList',cookies=r.cookies)print(r.text)defget_request_verification_token(self):#连接网站try:headers={"User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/85.0.4183.121Safari/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)除了(exceptions.ConnectionError,exceptions.HTTPError,exceptions.Timeout)作为e:返回False尝试:bsObj=BeautifulSoup(html.text,features='html.parser')exceptAttributeErrorase:returnFalseifbsObj:try:get_token=bsObj.find("input",{"name":"__RequestVerificationToken"}).get("value")除了Exceptionase:print(f"otunhandledexception{e}")returnFalsereturnget_tokenif__name__=='__main__':get_cookie=GetCookie()get_cookie.get_cookie_by_login()在此示例中,会话对象(调用请求.Session()获取)会持续跟踪session信息,比如cookies,headers,甚至还有运行HTTP协议的信息,比如HTTPAdapter(为HTTP和HTTPS链接session提供统一接口)Requests是一个很强大的库,程序员你不用完全不需要担心,也不需要写代码。它可能只是不如Selenium。虽然在写网络爬虫的时候,你可能会让Requests库为你做所有的事情,但是时刻关注cookies的状态,把握它们可以控制的范围是非常重要的。通过避免痛苦的调试和寻找网站异常,这节省了大量时间。HTTPBasicAccessAuthentication在cookie发明之前,最常见的处理网站登录的方式是使用HTTPBasicaccessauthentication。现在已经不常用了,但我们还是偶尔会看到它,尤其是在一些安全性高的网站或者公司内部网站,以及一些API上。下面是基本访问认证界面的截图:和前面的例子一样,需要输入用户名和密码才能登录。Requests库有一个专门用于HTTP认证的auth模块:importrequestsfromrequests.authimportHTTPBasicAuthdefhttp_auth():auth=HTTPBasicAuth('user','1223**%%adw')r=requests.post(url="http://www.test.com:3311/",auth=auth)打印(r.text)虽然这看起来像一个普通的POST请求,但是有一个HTTPBasicAuth对象作为auth参数传递给请求。显示的结果将是一个用户名和密码验证成功的页面(或者如果验证失败则访问被拒绝的页面)。其他表单问题表单是恶意机器人最喜欢的网站入口点。您当然不希望机器人创建垃圾帐户、占用昂贵的服务器资源或在您的博客上提交垃圾评论。因此,现代网站往往在HTML中使用很多安全措施,使得表单无法被机器人批量提交。验证码的细节我不打算在这篇文章中详细讲解(因为文章已经够长了),我会介绍使用Python的图像处理和文本识别方法来详细介绍这部分内容。如果在提交表单时遇到莫名其妙的错误,或者服务器一直以默认原因拒绝请求,我会在以后的文章中介绍这些问题。本文所有源码已托管在Github上,地址:https://github.com/sycct/Scrape_1_1.git如有任何问题,欢迎issue。