侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python使用Srapy框架爬虫模拟登陆并抓取知乎内容

Python  /  管理员 发布于 7年前   178

一、Cookie原理
HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制
Cookie是http消息头中的一种属性,包括:

  • Cookie名字(Name)Cookie的值(Value)
  • Cookie的过期时间(Expires/Max-Age)
  • Cookie作用路径(Path)
  • Cookie所在域名(Domain),使用Cookie进行安全连接(Secure)

前两个参数是Cookie应用的必要条件,另外,还包括Cookie大小(Size,不同浏览器对Cookie个数及大小限制是有差异的)。

二、模拟登陆
这次主要爬取的网站是知乎
爬取知乎就需要登陆的, 通过之前的python内建库, 可以很容易的实现表单提交。

现在就来看看如何通过Scrapy实现表单提交。

首先查看登陆时的表单结果, 依然像前面使用的技巧一样, 故意输错密码, 方面抓到登陆的网页头部和表单(我使用的Chrome自带的开发者工具中的Network功能)

查看抓取到的表单可以发现有四个部分:

  • 邮箱和密码就是个人登陆的邮箱和密码
  • rememberme字段表示是否记住账号
  • 第一个字段是_xsrf,猜测是一种验证机制
  • 现在只有_xsrf不知道, 猜想这个验证字段肯定会实现在请求网页的时候发送过来, 那么我们查看当前网页的源码(鼠标右键然后查看网页源代码, 或者直接用快捷键)

发现我们的猜测是正确的

那么现在就可以来写表单登陆功能了

def start_requests(self):    return [Request("https://www.zhihu.com/login", callback = self.post_login)] #重写了爬虫类的方法, 实现了自定义请求, 运行成功后会调用callback回调函数  #FormRequeset  def post_login(self, response):    print 'Preparing login'    #下面这句话用于抓取请求网页后返回网页中的_xsrf字段的文字, 用于成功提交表单    xsrf = Selector(response).xpath('//input[@name="_xsrf"]/@value').extract()[0]    print xsrf    #FormRequeset.from_response是Scrapy提供的一个函数, 用于post表单    #登陆成功后, 会调用after_login回调函数    return [FormRequest.from_response(response,    formdata = {  '_xsrf': xsrf,  'email': '123456',  'password': '123456'  },  callback = self.after_login  )]

其中主要的功能都在函数的注释中说明
三、Cookie的保存
为了能使用同一个状态持续的爬取网站, 就需要保存cookie, 使用cookie保存状态, Scrapy提供了cookie处理的中间件, 可以直接拿来使用

CookiesMiddleware:

这个cookie中间件保存追踪web服务器发出的cookie, 并将这个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)

那么可以对我们的爬虫类中方法进行修改, 使其追踪cookie

  #重写了爬虫类的方法, 实现了自定义请求, 运行成功后会调用callback回调函数  def start_requests(self):    return [Request("https://www.zhihu.com/login", meta = {'cookiejar' : 1}, callback = self.post_login)] #添加了meta  #FormRequeset出问题了  def post_login(self, response):    print 'Preparing login'    #下面这句话用于抓取请求网页后返回网页中的_xsrf字段的文字, 用于成功提交表单    xsrf = Selector(response).xpath('//input[@name="_xsrf"]/@value').extract()[0]    print xsrf    #FormRequeset.from_response是Scrapy提供的一个函数, 用于post表单    #登陆成功后, 会调用after_login回调函数    return [FormRequest.from_response(response,  #"http://www.zhihu.com/login",  meta = {'cookiejar' : response.meta['cookiejar']}, #注意这里cookie的获取  headers = self.headers,  formdata = {  '_xsrf': xsrf,  'email': '123456',  'password': '123456'  },  callback = self.after_login,  dont_filter = True  )]

四、伪装头部
有时候登陆网站需要进行头部伪装, 比如增加防盗链的头部, 还有模拟服务器登陆

为了保险, 我们可以在头部中填充更多的字段, 如下

  headers = {  "Accept": "*/*",  "Accept-Encoding": "gzip,deflate",  "Accept-Language": "en-US,en;q=0.8,zh-TW;q=0.6,zh;q=0.4",  "Connection": "keep-alive",  "Content-Type":" application/x-www-form-urlencoded; charset=UTF-8",  "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": "http://www.zhihu.com/"  }

在scrapy中Request和FormRequest初始化的时候都有一个headers字段, 可以自定义头部, 这样我们可以添加headers字段

形成最终版的登陆函数

#!/usr/bin/env python# -*- coding:utf-8 -*-from scrapy.contrib.spiders import CrawlSpider, Rulefrom scrapy.selector import Selectorfrom scrapy.contrib.linkextractors.sgml import SgmlLinkExtractorfrom scrapy.http import Request, FormRequestfrom zhihu.items import ZhihuItemclass ZhihuSipder(CrawlSpider) :  name = "zhihu"  allowed_domains = ["www.zhihu.com"]  start_urls = [    "http://www.zhihu.com"  ]  rules = (    Rule(SgmlLinkExtractor(allow = ('/question/\d+#.*?', )), callback = 'parse_page', follow = True),    Rule(SgmlLinkExtractor(allow = ('/question/\d+', )), callback = 'parse_page', follow = True),  )  headers = {  "Accept": "*/*",  "Accept-Encoding": "gzip,deflate",  "Accept-Language": "en-US,en;q=0.8,zh-TW;q=0.6,zh;q=0.4",  "Connection": "keep-alive",  "Content-Type":" application/x-www-form-urlencoded; charset=UTF-8",  "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": "http://www.zhihu.com/"  }  #重写了爬虫类的方法, 实现了自定义请求, 运行成功后会调用callback回调函数  def start_requests(self):    return [Request("https://www.zhihu.com/login", meta = {'cookiejar' : 1}, callback = self.post_login)]  #FormRequeset出问题了  def post_login(self, response):    print 'Preparing login'    #下面这句话用于抓取请求网页后返回网页中的_xsrf字段的文字, 用于成功提交表单    xsrf = Selector(response).xpath('//input[@name="_xsrf"]/@value').extract()[0]    print xsrf    #FormRequeset.from_response是Scrapy提供的一个函数, 用于post表单    #登陆成功后, 会调用after_login回调函数    return [FormRequest.from_response(response,  #"http://www.zhihu.com/login",  meta = {'cookiejar' : response.meta['cookiejar']},  headers = self.headers, #注意此处的headers  formdata = {  '_xsrf': xsrf,  'email': '[email protected]',  'password': '123456'  },  callback = self.after_login,  dont_filter = True  )]  def after_login(self, response) :    for url in self.start_urls :      yield self.make_requests_from_url(url)  def parse_page(self, response):    problem = Selector(response)    item = ZhihuItem()    item['url'] = response.url    item['name'] = problem.xpath('//span[@class="name"]/text()').extract()    print item['name']    item['title'] = problem.xpath('//h2[@class="zm-item-title zm-editable-content"]/text()').extract()    item['description'] = problem.xpath('//div[@class="zm-editable-content"]/text()').extract()    item['answer']= problem.xpath('//div[@class=" zm-editable-content clearfix"]/text()').extract()    return item

五、Item类和抓取间隔
完整的知乎爬虫代码链接

from scrapy.item import Item, Fieldclass ZhihuItem(Item):  # define the fields for your item here like:  # name = scrapy.Field()  url = Field() #保存抓取问题的url  title = Field() #抓取问题的标题  description = Field() #抓取问题的描述  answer = Field() #抓取问题的答案  name = Field() #个人用户的名称

设置抓取间隔, 访问由于爬虫的过快抓取, 引发网站的发爬虫机制, 在setting.py中设置

BOT_NAME = 'zhihu'SPIDER_MODULES = ['zhihu.spiders']NEWSPIDER_MODULE = 'zhihu.spiders'DOWNLOAD_DELAY = 0.25  #设置下载间隔为250ms

更多设置可以查看官方文档

抓取结果(只是截取了其中很少一部分)

... 'url': 'http://www.zhihu.com/question/20688855/answer/16577390'}2014-12-19 23:24:15+0800 [zhihu] DEBUG: Crawled (200) <GET http://www.zhihu.com/question/20688855/answer/15861368> (referer: http://www.zhihu.com/question/20688855/answer/19231794)[]2014-12-19 23:24:15+0800 [zhihu] DEBUG: Scraped from <200 http://www.zhihu.com/question/20688855/answer/15861368>  {'answer': [u'\u9009\u4f1a\u8ba1\u8fd9\u4e2a\u4e13\u4e1a\uff0c\u8003CPA\uff0c\u5165\u8d22\u52a1\u8fd9\u4e2a\u884c\u5f53\u3002\u8fd9\u4e00\u8def\u8d70\u4e0b\u6765\uff0c\u6211\u53ef\u4ee5\u5f88\u80af\u5b9a\u7684\u544a\u8bc9\u4f60\uff0c\u6211\u662f\u771f\u7684\u559c\u6b22\u8d22\u52a1\uff0c\u70ed\u7231\u8fd9\u4e2a\u884c\u4e1a\uff0c\u56e0\u6b64\u575a\u5b9a\u4e0d\u79fb\u5730\u5728\u8fd9\u4e2a\u884c\u4e1a\u4e2d\u8d70\u4e0b\u53bb\u3002',        u'\u4e0d\u8fc7\u4f60\u8bf4\u6709\u4eba\u4ece\u5c0f\u5c31\u559c\u6b22\u8d22\u52a1\u5417\uff1f\u6211\u89c9\u5f97\u51e0\u4e4e\u6ca1\u6709\u5427\u3002\u8d22\u52a1\u7684\u9b45\u529b\u5728\u4e8e\u4f60\u771f\u6b63\u61c2\u5f97\u5b83\u4e4b\u540e\u3002',        u'\u901a\u8fc7\u5b83\uff0c\u4f60\u53ef\u4ee5\u5b66\u4e60\u4efb\u4f55\u4e00\u79cd\u5546\u4e1a\u7684\u7ecf\u8425\u8fc7\u7a0b\uff0c\u4e86\u89e3\u5176\u7eb7\u7e41\u5916\u8868\u4e0b\u7684\u5b9e\u7269\u6d41\u3001\u73b0\u91d1\u6d41\uff0c\u751a\u81f3\u4f60\u53ef\u4ee5\u638c\u63e1\u5982\u4f55\u53bb\u7ecf\u8425\u8fd9\u79cd\u5546\u4e1a\u3002',        u'\u5982\u679c\u5bf9\u4f1a\u8ba1\u7684\u8ba4\u8bc6\u4ec5\u4ec5\u505c\u7559\u5728\u505a\u5206\u5f55\u8fd9\u4e2a\u5c42\u9762\uff0c\u5f53\u7136\u4f1a\u89c9\u5f97\u67af\u71e5\u65e0\u5473\u3002\u5f53\u4f60\u5bf9\u5b83\u7684\u8ba4\u8bc6\u8fdb\u5165\u5230\u6df1\u5c42\u6b21\u7684\u65f6\u5019\uff0c\u4f60\u81ea\u7136\u5c31\u4f1a\u559c\u6b22\u4e0a\u5b83\u4e86\u3002\n\n\n'],   'description': [u'\u672c\u4eba\u5b66\u4f1a\u8ba1\u6559\u80b2\u4e13\u4e1a\uff0c\u6df1\u611f\u5176\u67af\u71e5\u4e4f\u5473\u3002\n\u5f53\u521d\u662f\u51b2\u7740\u5e08\u8303\u4e13\u4e1a\u62a5\u7684\uff0c\u56e0\u4e3a\u68a6\u60f3\u662f\u6210\u4e3a\u4e00\u540d\u8001\u5e08\uff0c\u4f46\u662f\u611f\u89c9\u73b0\u5728\u666e\u901a\u521d\u9ad8\u4e2d\u8001\u5e08\u5df2\u7ecf\u8d8b\u4e8e\u9971\u548c\uff0c\u800c\u987a\u6bcd\u4eb2\u5927\u4eba\u7684\u610f\u9009\u4e86\u8fd9\u4e2a\u4e13\u4e1a\u3002\u6211\u559c\u6b22\u4e0a\u6559\u80b2\u5b66\u7684\u8bfe\uff0c\u5e76\u597d\u7814\u7a76\u5404\u79cd\u6559\u80b2\u5fc3\u7406\u5b66\u3002\u4f46\u4f1a\u8ba1\u8bfe\u4f3c\u4e4e\u662f\u4e3b\u6d41\u3001\u54ce\u3002\n\n\u4e00\u76f4\u4e0d\u559c\u6b22\u94b1\u4e0d\u94b1\u7684\u4e13\u4e1a\uff0c\u6240\u4ee5\u5f88\u597d\u5947\u5927\u5bb6\u9009\u4f1a\u8ba1\u4e13\u4e1a\u5230\u5e95\u662f\u51fa\u4e8e\u4ec0\u4e48\u76ee\u7684\u3002\n\n\u6bd4\u5982\u8bf4\u5b66\u4e2d\u6587\u7684\u4f1a\u8bf4\u4ece\u5c0f\u559c\u6b22\u770b\u4e66\uff0c\u4f1a\u6709\u4ece\u5c0f\u559c\u6b22\u4f1a\u8ba1\u501f\u554a\u8d37\u554a\u7684\u7684\u4eba\u5417\uff1f'],   'name': [],   'title': [u'\n\n', u'\n\n'],   'url': 'http://www.zhihu.com/question/20688855/answer/15861368'}...

六、存在问题

  • Rule设计不能实现全网站抓取, 只是设置了简单的问题的抓取
  • Xpath设置不严谨, 需要重新思考
  • Unicode编码应该转换成UTF-8

您可能感兴趣的文章:

  • python爬虫之模拟登陆csdn的实例代码
  • python编程使用selenium模拟登陆淘宝实例代码
  • 利用selenium 3.7和python3添加cookie模拟登陆的实现
  • Python爬虫利用cookie实现模拟登陆实例详解
  • Python模拟登陆淘宝并统计淘宝消费情况的代码实例分享
  • 分享一个常用的Python模拟登陆类
  • python模拟登陆阿里妈妈生成商品推广链接
  • python3.3教程之模拟百度登陆代码分享
  • python模拟新浪微博登陆功能(新浪微博爬虫)
  • 详解python项目实战:模拟登陆CSDN


  • 上一条:
    python中函数传参详解
    下一条:
    Python的爬虫程序编写框架Scrapy入门学习教程
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客