2019独角兽企业重金招聘Python工程师标准>>>
由于Python简单上手,方便做一些小功能,最近学习了一下,参考了一些Python爬虫的文章,写了一个通过cookie登陆,然后获取页面图片的简单爬虫实例。
版本:Pyhton3.4 网页:知乎
import gzip
import re
import http.cookiejar
import urllib.request
import io
import sys
import os
__URL__ = 'https://www.zhihu.com/'
__cookiePATH__ = "F:\\cookie.txt"
__savePATH__ = "F:\\test.html"
# #图片保存路径
__targetPATH__ = "F:\\test\\zhihu"
# 创建MozillaCookieJar实例对象
_cookie = http.cookiejar.MozillaCookieJar()
def saveFile(data):f_obj = open(__savePATH__, 'wb') # wb 表示打开方式f_obj.write(data)f_obj.close()
#提取文件名,保存同名到本地路径
def destFile(path):if not os.path.isdir(__targetPATH__):os.mkdir(__targetPATH__)pos = path.rindex('/') t = os.path.join(__targetPATH__, path[pos+1:])return t
#解压函数
def unzip(data):try: # 尝试解压print('正在解压.....')data = gzip.decompress(data)print('解压完毕!')except:print('未经压缩, 无需解压')return data
#获取_xsrf
def getXSRF(data):cer = re.compile('name="_xsrf" value="(.*)"', flags = 0)strlist = cer.findall(data)print("strlist:",strlist)return strlist[0]
#构造文件头
def getOpener(head):#设置一个cookie处理器,它负责从服务器下载cookie到本地,并且在发送请求时带上本地的cookiehandler = urllib.request.HTTPCookieProcessor(_cookie)opener = urllib.request.build_opener(handler)header = []for key, value in head.items():elem = (key, value)header.append(elem)opener.addheaders = headerreturn opener
#构造header,一般header至少要包含一下两项。这两项是从抓到的包里分析得出的。
header = {'Connection': 'Keep-Alive','Accept': 'text/html, application/xhtml+xml, */*','Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3','User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',# 'Accept-Encoding': 'gzip, deflate','Host': 'www.zhihu.com','DNT': '1'
}
# 改变标准输出的默认编码,因为pyhon本身Unicode对部分UTF-8不支持
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') def _init():global _cookie###一、有cookie登陆,从文件中读取cookie内容到变量,用cookie登陆信息#### _cookie.load(__cookiePATH__, ignore_discard=True, ignore_expires=True)# opener = getOpener(header)###二、没有cookie登陆,发起三次请求###opener = getOpener(header)# 第一次请求,获取返回的_xsrf值response = opener.open(__URL__)data = response.read()data = unzip(data) # 解压_xsrf = getXSRF(data.decode()) ##post数据接收和处理的(登陆)页面(我们要向这个页面发送我们构造的Post数据)loginUrl = 'https://www.zhihu.com/login/email'id = 'alvinlovelife@163.com'password = '1'#构造Post数据,他也是从抓大的包里分析得出的。postDict = {'_xsrf':_xsrf, #特有数据,不同网站可能不同 'password': password,'captcha_type':'cn','remember_me':'true','email': id}#需要给Post数据编码 postData = urllib.parse.urlencode(postDict).encode()# 第二次请求,登陆并获取登陆结果response = opener.open(loginUrl, postData)# 登陆成功后保存cookie_cookie.save(__cookiePATH__,ignore_discard = True,ignore_expires = True)# 显示登陆请求后的返回值data = response.read()data = unzip(data)print("response:",data.decode())# 第三次请求,登陆后再次发起实际请求response = opener.open(__URL__)data2 = response.read()saveFile(data2)data2 = unzip(data2)# print("result:",data2.decode())contentBytes = data2.decode("utf8")#正则表达式查找所有的图片for link,t in set(re.findall(r'(https:[^s]*?(jpg|png|gif))', str(contentBytes))):print(link)try: urllib.request.urlretrieve(link, destFile(link)) #下载图片except Exception as e:print('下载图片失败:',e)#异常抛出_init()
代码中将所有调用都封装到各个方法中,通过调用_init()执行代码。
1、第一次调用时使用无cookie的登陆,使用个人账号id和password来登陆,将自动把cookie保存到本地。
2、这时下次调用就可以使用有cookie的登陆了(注释掉“二、无cookie登陆”的前两步请求代码,启用“一、有cookie登陆”的请求代码)。
3、登陆之后,这里将通过正则表达式将网页的图片下载到本地。
注意:第一次使用账号密码登陆后,就可以改用保存到本地的cookie模拟浏览器登陆了,如果多次使用账号密码方式登陆,会返回要求“请填写验证码(登陆失败)”的提示。目前还没研究到验证码获取的方法~。
GitHub: https://github.com/alvinlovelife/Python.git