scrapy基础:创建爬虫、发送post请求与携带cookie

文章目录

    • scrapy基础:创建爬虫、发送post请求与携带cookie
      • crawlspider的简单用法
      • 使用scrapy发送post请求
        • 使用scrapy发送post请求时需要注意的问题
        • 关于scrapy使用cookie出现的一系列问题
      • 正方教务系统的爬取
        • 使用requests爬取(十分简单)
        • 使用scrapy爬取(坑很多)

scrapy基础:创建爬虫、发送post请求与携带cookie

crawlspider的简单用法

创建爬虫: scrapy genspider -t crawl wx_spider wxapp-union.com 使用的是craw爬虫模块

                                要爬取的页面

scrapy基础:创建爬虫、发送post请求与携带cookie_第1张图片

代码如下: (主要是在spiders文件中操作)

class WxSpiderSpider(CrawlSpider):
    name = 'wx_spider'
    allowed_domains = ['wxapp-union.com']
    start_urls = ['http://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1']

    rules = (
        Rule(LinkExtractor(allow=r'.*?portal.php?mod=list&catid=2&page=/d'), follow=True),  #定义爬取规则,这个是翻页爬取,注意这里follow是需要跟进的意思     	 		      Rule(LinkExtractor(allow=r'/article-.*\d'),callback="parse_content",follow=False)
        	)  #这个是爬取每一页里面的文章链接,此处进入文章链接后不需要再文章内跟进与爬取规则相同的链接

    def parse_content(self, response):
        title=response.xpath('//h1[@class="ph"]/text()').extract()
        print(title)
        print(response.headers)

最终爬虫将会先爬取第一页链接,再在第一页中找到个文章的链接爬取,爬取完成后在爬取第二页链接,然后爬取第二页链接内的各个文章,并以这样的顺序继续爬取


使用scrapy发送post请求

由于我们默认创建的basic spider是默认使用start_urls里面的url来发送get请求的,

因此要发送post请求需要改写start_requests(self)方法

例如登录人人网

def start_requests(self):    
	url='http://www.renren.com/Plogin.do'    
    data={'email':'填入账号','password':'填入密码'} 
    request=scrapy.FormRequest(url=url,formdata=data,callback=self.parse_page) #构建表单请求 
    yield request

注意,在构建post请求时需要用到scrapy.FormRequest()来构建请求

使用scrapy发送post请求时需要注意的问题
  1. scrapy.FormRequest()里面的参数formdata表单数据不是随便填写的,而是需要在登陆的网页上找到一个提交登陆信息请求的post数据包,查看里面的formdata数据,进而能够伪造formdata数据

  2. 对于有验证码的网页可以使用PIL库提取验证码(这里目前还没学到自动处理图片,只是把图片下载下来由人来识别),具体方法也很简单,如下:

    • pip install Pillow 使用 PIL需要下载这个库

    • from PIL import Image 同时也需要导入一个比较方便的下载图片的模块(内置的,无需下载):from urllib.request import urlretrieve

    • urlretrieve('图片链接','要保存的本地地址')

    • Img=Image.open('打开本地保存的图片地址')

    • Img.show() 将图片显示出来


关于scrapy使用cookie出现的一系列问题

根据官方文档介绍,scrapy使用cookie非常简单只需要在scrapy.Request( )中传递一个meta={‘cookiejar’: i }参数就行。后面的i可用是用户自行设置的参数,如数字等,下面看看它的具体用法

这里为了从一开始便维持同一个cookie会话,我改写了start_requests用法

def start_requests(self):
   yield scrapy.Request(url=self.url,meta={'cookiejar':1},callback=self.parse)

为了将这个会话维持下来,我需要在接下来的回调函数中接着带上此cookiejar

def parse(self, response):
	yield 	scrapy.FormRequest(url=self.url,formdata=self.data,callback=self.parse_content,meta={'cookiejar':response.meta['cookiejar']})

那么这次请求的便是带上了上次此请求的cookie

那么问题来了,在使用scrapy爬取正方教务系统时,尽管使用了cookie,但是还是出现了一系列问题,这里也顺便介绍下正方教务系统的爬取方法


正方教务系统的爬取

scrapy基础:创建爬虫、发送post请求与携带cookie_第2张图片

  1. 前期观察:由于要模拟登陆,需要在登陆页面抓包到使用post传输数据的包,找到其formdata数据并伪造即可

    这是我抓到的包

scrapy基础:创建爬虫、发送post请求与携带cookie_第3张图片

⏬继续观察下面的 formdata表单数据
scrapy基础:创建爬虫、发送post请求与携带cookie_第4张图片

可用看到我需要提交前六个数据,后面两个数据为空,现介绍前五个数据的含义

  • __VIEWSTATE:此数据在每次刷新时都会改变,我可以在网页源代码中找到这个数据,因此只需要获取登陆界面的源代码并提取即可在这里插入图片描述
  • __VIEWSTATEENERATOP:固定不变的数据,网页源代码中也有。
  • TestBox1TextBox3分别是学号,密码和验证码。
  • RadioButtonLIst1:我个人理解是一串无法在网页上显示的编码,经过反url编码**(gb2312)**转出来的是 学生 ,其实也是固定的,我只要知道‘学生’的gb2312编码即可

这里需要特别注意验证码图片,这是个大坑!!!

在这里插入图片描述

我们可以很轻易的找到图片的地址,例如这样的地址http://202.195.145.170/jndx/CheckCode.aspx(要用我们学校才能打开

但是这里我们会发现:每次打开图片的地址,验证码都会变,并且对着图片地址刷新,验证码也会变!

这里就涉及到一个问题:你从网页上获取的图片验证码与你需要登陆使用的验证码是否一致!由于你需要使用爬虫爬取这个登陆网站两次:一次是获取爬取各个formdata的信息,一次是使用formdata登陆,所以必须确保两次打开的网站是同一个,也就是是同一个会话cookie要保持一致,这里用requests便很好解决

使用requests爬取(十分简单)
url = "http://202.195.144.163/jndx/default2.aspx"   #教务处网站地址
s =requests.session() #建立一个会话
response =s.get(url)  #此后一直使用s.get()访问此链接便能确保会话

之后的代码就很简单了:RadioButtonList1 = u"学生".encode('gb2312','replace')#这个是固定的,‘学生’的gb2312编码

​ 伪造好data提交的表单数据

data = {
"RadioButtonList1":RadioButtonList1,
"__VIEWSTATE":__VIEWSTATE,
"TextBox1":'学号',
"TextBox2":'密码',
"TextBox3":'验证码',  #验证码使用前面提到的使用PIL提取的方法
"Button1":"",
"lbLanguage":""
}
response = s.post(url,data=data,headers=headers)
使用scrapy爬取(坑很多)
  1. 第一个坑:不要使用urlretrieve()模块来下载验证码图片!!!

    urlretrieve()不能够带cookie来访问图片,这就造成了你下载的图片不是你要登陆使用的验证码图片,其结果是得到的源码一直有验证码错误这几个字

  2. 在spider文件中写有多个回调函数时不要再一个回调函数中使用多个yield scrapy.Requests(),因为这两个发送请求的代码不会按照你希望的顺序调用回调函数(并不是先调用写在前面的代码里面的回调函数)

  3. 在使用cookiejar的时候最好在settings文件中打开COOKIES_ENABLED =True这个选项来使用cookie

接着附上spider里面的代码

# -*- coding: utf-8 -*-
#仅仅至少测试登陆的代码,比较简单
import scrapy
from PIL import Image
from urllib.request import urlretrieve

class JwcSpider(scrapy.Spider):
    name = 'jwc'
    data = {
        "RadioButtonList1":'',
        '__VIEWSTATE':'',
        "TextBox1":'输入学号',
        "TextBox2":'输入密码',
        "TextBox3":'',
        "Button1": "",
        "lbLanguage": ""
            }
    url='http://202.195.144.168/jndx/default2.aspx/' #教务处的登陆网站
 
#meta用来传递cookie,cookiejar是固定表示的
    def start_requests(self):
        yield scrapy.Request(url=self.url,meta={'cookiejar':1},callback=self.parse)

        #这个回调函数用来解析第一次请求登陆页面,获取我需要的formdata中的数据
    def parse(self, response):
        img_url = 'http://202.195.144.168/jndx/' + response.xpath('//img[@id="icode"]/@src').get()
        value = response.xpath('//*[@id="form1"]/input/@value').get()
        self.data['RadioButtonList1'] = u"学生".encode('gb2312', 'replace')
        self.data['__VIEWSTATE'] = value
        yield scrapy.Request(url=img_url, meta={'cookiejar':response.meta['cookiejar']}, callback=self.parse_img) #发送处理图片链接的请求时一定要带上cookie

    #此回调函数用来处理验证码图片
    def parse_img(self,response):
        print('开始处理照片链接的响应')
        with open('img.jpg','wb') as f:
            f.write(response.body)
        img=Image.open('img.jpg')
        img.show()
        self.data['TextBox3'] = input('请输入验证码:')
        yield scrapy.FormRequest(url=self.url, formdata=self.data, callback=self.parse_content,meta={'cookiejar': response.meta['cookiejar']})


    def parse_content(self,response):
        print(response.body.decode('GB2312')) #登陆后的网页,用GB2312解码,其他方式解码的话会乱码

*此代码写的很粗糙,只是为了测试用*


你可能感兴趣的:(python,爬虫,scrapy)