前面学习了爬虫的不少知识,都是分析 HTML、json 数据,有不少的网站为了反爬虫,除了须要高可用代理 IP 地址池外,还须要登陆,登陆的时候不单单须要输入帐户名和密码,并且有可能验证码,下面就介绍 Scrapy 爬虫模拟登录的几种策略。html
前面介绍的爬虫 scrapy 的基本请求流程是 start_request 方法遍历 start_urls 列表,而后 make_requests_from_url方法,里面执行 Request 方法,请求 start_urls 里面的地址,使用的是 GET 方法,因为直接使用用户名和密码能够登陆,使用 POST 方法进行登陆。git
例子:人人网登陆github
登陆地址:http://www.renren.com/PLogin.doshell
案例步骤:json
第一步:建立项目。浏览器
在 dos下切换到目录安全
D:\scrapy_project服务器
新建一个新的爬虫项目:scrapy startproject renrencookie
第二步:建立爬虫。session
在 dos下切换到目录。
D:\scrapy_project\renren\renren\spiders
用命令 scrapy genspider renren1 " renren.com" 建立爬虫。
第三步: 经过浏览器登陆人人网,使用 fiddler 抓包抓取登陆 post 请求的 data。
第四步:编写爬虫文件。
import scrapy
# 登陆只须要提供 post 数据就能够登陆的,就能够用这种方法,
# 下面示例:post 数据是帐户密码
class Renren1Spider(scrapy.Spider):
name = "renren1"
allowed_domains = ["renren.com"]
def start_requests(self):
url = 'http://www.renren.com/PLogin.do'
# FormRequest 是 Scrapy 发送 POST 请求的方法
yield scrapy.FormRequest(
url = url,
formdata = {"email" : "13554799060", "password" : "xny123"},
callback = self.parse_page)
# 回调方法,对返回的 response 进行处理(把response.body保存到 xiao.html 中)
def parse_page(self, response):
with open("xiao.html", "wb") as filename:
filename.write(response.body)
第五步:修改 settings 文件。
设置爬虫请求的默认头信息。
第六步:运行爬虫。
在 dos下切换到目录
D:\scrapy_project\renren\renren 下
经过命令运行爬虫 :scrapy crawl renren1
第七步:查看结果。
xiao.html 中显示的内容正是登陆本身人人网以后的主页内容,说明登陆成功。
标准的模拟登陆方法:
一、首先发送登陆页面的 get 请求,获取到页面里的登陆必须的参数。
二、登陆必须的参数和帐户密码一块儿 post 到服务器,登陆成功。
HTTP 是无状态的面向链接的协议, 为了保持链接状态, 标准的模拟登录案例引入了 Cookie 机制。
Cookie 是 http 消息头中的一种属性,包括:
.Cookie 名字(Name)Cookie 的值(Value)
.Cookie 的过时时间(Expires/Max-Age)
.Cookie 做用路径(Path)
.Cookie 所在域名(Domain),使用 Cookie 进行安全链接(Secure)。
前两个参数是 Cookie 应用的必要条件,另外,还包括 Cookie 大小( Size,不一样浏览器对Cookie 个数及大小限制是有差别的 )。
爬取的网站:github (https://github.com/login)
案例步骤:
第一步:爬取前分析。
打开 fiddler,接着咱们打开 github 的登录页面(https://github.com/login ),输入用户名、密码( 输入错误的密码 ),提交查看 fiddler 获取的信息,结果入下:
输入用户名和错误密码获取的 fiddler 结果:
咱们用 google 浏览器看源码也能够看到 form 提交时会加入 authenticity_token 参数一块儿,以下图:
第二步:建立项目。
在 dos下切换到目录
D:\scrapy_project
新建一个新的爬虫项目:scrapy startproject github
第三步:建立爬虫。
在 dos下切换到目录。
D:\scrapy_project\github\github\spiders
用命令 scrapy genspider gh "github.com" 建立爬虫。
第四步: 开始前的准备工做。
(一)、在 scrapy.cfg 同级目录下建立 pycharm 调试脚本 run.py,内容以下:
# -*- coding: utf-8 -*-
from scrapy import cmdline
cmdline.execute("scrapy crawl github".split())
(二)修改 settings 中的 ROBOTSTXT_OBEY = True 参数为 False,由于默认为 True,就是要遵照 robots.txt 的规则, robots.txt 是遵循 Robot协议 的一个文件,它保存在网站的服务器中,它的做用是,告诉搜索引擎爬虫,本网站哪些目录下的网页不但愿你进行爬取收录。在 Scrapy 启动后,会在第一时间访问网站的 robots.txt 文件,而后决定该网站的爬取范围。查看 robots.txt 能够直接网址后接 robots.txt 便可。
例如百度:https://www.baidu.com/robots.txt
修改 settings 文件。
(三)模拟登录时,必须保证 settings.py 里的 COOKIES_ENABLED (Cookies中间件) 处于开启状态。
COOKIES_ENABLED = True
第五步:编写爬虫文件-获取 authenticity_token。
首先要打开登录页面,获取 authenticity_token,代码以下:
import scrapy
class GithubSpider(scrapy.Spider):
name = 'gh'
allowed_domains = ['github.com']
def start_requests(self):
urls = ['https://github.com/login']
for url in urls:
# 重写 start_requests 方法,经过 meta 传入特殊 key cookiejar,爬取 url 做为参数传给回调函数
yield scrapy.Request(url, meta={'cookiejar': 1}, callback=self.github_login)
def github_login(self, response):
# 首先获取authenticity_token,这里能够借助scrapy shell ”url“来获取页面
# 而后从源码中获取到authenticity_token的值
authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
# 利用 scrapy 内置 logger 打印 info 信息
self.logger.info('authenticity_token='+ authenticity_token)
pass
运行结果:
经过运行的结果,能够看到咱们已经获取了 authenticity_token 的值,这一步重点要说明meta、cookiejar 和 logger。
【meta】:字典格式的元数据,能够传递给下一个函数 meta。
【cookiejar】:是 meta 的一个特殊的key,经过 cookiejar 参数能够支持多个会话对某网站进行爬取,能够对 cookie 作标记,1,2,3,4......这样 scrapy 就维持了多个会话;
【logger】:scrapy 为每一个 spider 实例内置的日志记录器。
为了能使用同一个状态持续的爬取网站, 就须要保存cookie, 使用cookie保存状态, Scrapy 提供了 cookie 处理的中间件, 能够直接拿来使用,Scrapy 官方的文档中给出了下面的代码范例 :
for i, url in enumerate(urls):
yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
callback=self.parse_page)
def parse_page(self, response):
# do some processing
return scrapy.Request("http://www.example.com/otherpage",
meta={'cookiejar': response.meta['cookiejar']},
callback=self.parse_other_page)
第六步:修改爬虫文件- FormRequest(登陆表单提交)
Scrapy 提供了 FormRequest 类,是 Request 类的扩展,专门用来进行 Form 表单提交。咱们主要使用 FormRequest.from_response()方法来模拟简单登录,经过FormRequest.from_response 提交后,交给回调函数处理。代码以下:
import scrapy
class GithubSpider(scrapy.Spider):
name = 'gh'
allowed_domains = ['github.com']
def start_requests(self):
urls = ['https://github.com/login']
for url in urls:
# 重写 start_requests 方法,经过 meta 传入特殊 key cookiejar,爬取 url 做为参数传给回调函数
yield scrapy.Request(url, meta={'cookiejar': 1}, callback=self.github_login)
def github_login(self, response):
# 首先获取authenticity_token,这里能够借助scrapy shell ”url“来获取页面
# 而后从源码中获取到authenticity_token的值
authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
# 利用 scrapy 内置 logger 打印 info 信息
self.logger.info('authenticity_token='+ authenticity_token)
# url 能够从 fiddler 抓取中获取,dont_click 做用是若是是 True,表单数据将被提交,而不须要单击任何元素。
return scrapy.FormRequest.from_response(
response,
url='https://github.com/session',
meta = {'cookiejar': response.meta['cookiejar']},
headers = self.headers,
formdata = {'utf8':'?',
'authenticity_token': authenticity_token,
'login': 'xxxxxx@qq.com',
'password': 'xxxxxx'},
callback = self.github_after,
dont_click = True,
)
第七步:修改爬虫文件- 假装头部。
为了更真实的模拟浏览器登录网站,须要进行头部假装, 在 scrapy 中 Request 和 FormRequest 初始化的时候都有一个 headers 字段, 能够自定义头部, 这样咱们能够添加 headers 字段。
# 头信息直接从 fiddler 中复制出来
headers = {
"Connection": "keep-alive",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36",
"Referer": "https: // github.com /",
"Content - Type": "application / x - www - form - urlencoded",
}
第八步:修改爬虫文件- 增长回调函数,主要是登录成功以后,获取登陆以后返回的页面(response)的元素进行断言,验证登陆结果。
登陆以后,主页以下:
# 回调函数
def github_after(self, response):
# 获取登陆页面主页中的字符串'Browse activity'
list = response.xpath("//a[@class=‘tabnav-tab selected‘]/text()").extract()
# 若是含有字符串,则打印日志说明登陆成功
if 'Browse activity' in list:
self.logger.info('我已经登陆成功了,这是我获取的关键字:Browse activity')
else:
self.logger.error('登陆失败')
第九步:整理完整的爬虫文件
import scrapy
class GithubSpider(scrapy.Spider):
name = 'gh'
allowed_domains = ['github.com']
# 头信息直接从 fiddler 中复制出来
headers = {
"Connection": "keep-alive",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36",
"Referer": "https: // github.com /",
"Content - Type": "application / x - www - form - urlencoded",
}
def start_requests(self):
urls = ['https://github.com/login']
for url in urls:
# 重写 start_requests 方法,经过 meta 传入特殊 key cookiejar,爬取 url 做为参数传给回调函数
yield scrapy.Request(url, meta={'cookiejar': 1}, callback=self.github_login)
def github_login(self, response):
# 首先获取authenticity_token,这里能够借助scrapy shell ”url“来获取页面
# 而后从源码中获取到authenticity_token的值
authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
# 利用 scrapy 内置 logger 打印 info 信息
self.logger.info('authenticity_token='+ authenticity_token)
# url 能够从 fiddler 抓取中获取,dont_click 做用是若是是 True,表单数据将被提交,而不须要单击任何元素。
return scrapy.FormRequest.from_response(
response,
url='https://github.com/session',
meta = {'cookiejar': response.meta['cookiejar']},
headers = self.headers,
formdata = {'utf8':'?',
'authenticity_token': authenticity_token,
'login': '55666727@qq.com',
'password': 'xny8816056'},
callback = self.github_after,
dont_click = True,
)
# 回调函数
def github_after(self, response):
# 获取登陆页面主页中的字符串'Browse activity'
list = response.xpath("//a[@class=‘tabnav-tab selected‘]/text()").extract()
# 若是含有字符串,则打印日志说明登陆成功
if 'Browse activity' in list:
self.logger.info('我已经登陆成功了,这是我获取的关键字:Browse activity')
else:
self.logger.error('登陆失败')
第十步:查看运行的结果。
经过运行的结果说明登陆成功。
若是实在没办法了,能够用策略三这种方法模拟登陆,虽然麻烦一点,可是成功率100%。
案例步骤:
第一步:建立项目。
在 dos下切换到目录
D:\scrapy_project
新建一个新的爬虫项目:scrapy startproject renren2
第二步:建立爬虫。
在 dos下切换到目录。
D:\scrapy_project\renren2\renren2\spiders
用命令 scrapy genspider ren2 "renren.com" 建立爬虫。
第三步: 经过浏览器登陆人人网,使用 fiddler 抓包抓取登陆后的Cookis。
第四步: 开始前的准备工做。
(一)、在 scrapy.cfg 同级目录下建立 pycharm 调试脚本 run.py,内容以下:
# -*- coding: utf-8 -*-
from scrapy import cmdline
cmdline.execute("scrapy crawl renren".split())
(二)修改 settings 中的 ROBOTSTXT_OBEY = True 参数为 False,由于默认为 True,就是要遵照 robots.txt 的规则, robots.txt 是遵循 Robot协议 的一个文件,它保存在网站的服务器中,它的做用是,告诉搜索引擎爬虫,本网站哪些目录下的网页不但愿你进行爬取收录。在 Scrapy 启动后,会在第一时间访问网站的 robots.txt 文件,而后决定该网站的爬取范围。查看 robots.txt 能够直接网址后接 robots.txt 便可。
修改 settings 文件。
(三)模拟登录时,必须保证 settings.py 里的 COOKIES_ENABLED ( Cookies 中间件) 处于开启状态。
COOKIES_ENABLED = True
第五步: 编写爬虫文件。
import scrapy
class RenrenSpider(scrapy.Spider):
name = "renren"
allowed_domains = ["renren.com"]
Cookies = {
"anonymid": "jlvxr345k9ondn",
"wp_fold": "0",
"depovince": "GW",
"jebecookies": "3af719cc-f819-4493-bcb6-c967fc59f04a|||||",
"_r01_": "1",
"JSESSIONID": "abcwnUubDsWO467i0mgxw",
"ick_login":"27af5597-30d7-469c-b7c4-184a6e335fcb",
"jebe_key":"d1f5682d-03b4-46cd-87c0-dc297525ed11%7Ccfcd208495d565ef66e7dff9f98764da%7C1536628574466%7C0%7C1536628572944",}
# 能够重写 Spider 类的 start_requests 方法,附带 Cookie 值,发送 POST 请求
def start_requests(self):
url = 'http://www.renren.com/PLogin.do'
# FormRequest 是 Scrapy 发送 POST 请求的方法
yield scrapy.FormRequest(url, cookies = self.Cookies, callback = self.parse_page)
# 处理响应内容
def parse_page(self, response):
print("===========" + response.url)
with open("xiao2.html", "wb") as filename:
filename.write(response.body)
第六步: 运行程序,查看运行结果。
Xiao2.html 中显示的内容正是登陆本身人人网以后的主页内容,说明登陆成功。