Request对象
Request对象在我们写爬虫 爬取一页的数据需要重新发送一个请求的时候调用
其中比较常用的参数有:
- url:这个request对象发送请求的url
- callback:在下载器下载完相应的数据后执行的回调函数
- method:请求方式,默认为GET,可以设置为其他方式
- headers:请求头,对于一些固定的设置,放在settings.py中指定即可。对于那些非固定的,可以在发送请求的时候指定
- meta:比较常用,用于在不同的请求之间传递数据
- encoding:编码,默认为utf-8,使用默认即可
- dot_filter:表示不由调速器过滤,在执行多次重复的请求时 用的比较多
- errback:在发生错误的时候执行的函数
Response对象:
Response对象一般是由scrapy自动构建的,因此开发者不需要关心如何创建Response对象,而是如何使用它
Response对象有很多属性,可以用来提取数据的,主要有以下属性:
- meta:从其他请求传过来的meta属性,可以用来保持多个请求之间的数据连接
- encoding:返回当前字符串编码和解码的格式
- text:将返回来的数据作为unicode字符串返回
- body:将返回来的数据作为bytes宇符串返回
- xpath:xpath选择器
- css:css选择器
发送get、post请求
在请求数据的时候如果想要发送post请求,推荐使用FormRequest对象,FormRequest继承Request,可以方便的指定表单数据
如果在爬虫一开始的时候就需要发送post请求,需要在爬虫类中重写start_requests(self)方法,在这个方法中发送post请求,程序会最先开始执行这个方法,并且不再调用start_urls里的url
模拟登陆人人网
创建爬虫
scrapy startproject renren
cd renren
scrapy gensipder renren_login "renren.com"
修改settings.py代码
爬虫部分代码
# -*- coding: utf-8 -*-
import scrapy
'''
登录人人网,访问大鹏页面 post、get请求
'''
class RenrenLoginSpider(scrapy.Spider):
name = 'renren_login'
allowed_domains = ['renren.com']
start_urls = ['http://renren.com/']
def start_requests(self):
# 重写start_requests(self)方法,发送post请求,重写后就不是最先访问start_urls里的url了
data = {
'email': '账号',
'password': '密码'
}
login_url = 'http://www.renren.com/PLogin.do' # 这个接口没有加密什么的 直接账号密码提交过去就行了
request = scrapy.FormRequest(login_url, formdata=data, callback=self.parse_page)
yield request
# 使用scrapy.FormRequest发送post请求:传入url 参数 回调函数,最后把返回结果传递给回调函数
# 返回结果一般都在response(响应)参数里
def parse_page(self, response): # 访问大鹏主页
request = scrapy.Request(url='http://www.renren.com/880151247/profile', callback=self.parse_profile)
yield request
# 使用scrapy.Request发送get请求:传入url 回调函数,最后把返回结果传递给回调函数
def parse_profile(self, response): # 把大鹏主页HTML代码写到文件里
with open('response.html', 'w', encoding='utf-8') as f:
f.write(response.text)
由于只是提交get、post请求,无需获取数据,items.py和pipelines.py不用设置什么
模拟登录豆瓣网(识别验证码)
创建爬虫
scrapy startproject douban
cd douban
scrapy gensipder douban_login "www.douban.com"
修改settings.py代码
和人人网一样,设置ROBOTSTXT_OBEY = False、DEFAULT_REQUEST_HEADERS即可
爬虫部分代码
# -*- coding: utf-8 -*-
import scrapy
from urllib import request
from PIL import Image
'''
登录豆瓣,修改个性签名 post get请求
'''
class DoubanLoginSpider(scrapy.Spider):
name = 'douban_login'
allowed_domains = ['www.douban.com']
start_urls = ['https://accounts.douban.com/login']
# 登录页面的url,模块会最先访问到登录页面,然后把返回结果传给函数parse
login_url = 'https://www.douban.com/login' # 提交post登录的url
profile_url = 'https://www.douban.com/people/akajiuren/' # 访问个人中心的url
def parse(self, response): # 登录豆瓣
formdata = {
'source': 'None',
'redir': 'https://www.douban.com',
'form_email': '账号',
'form_password': '密码',
'remember': 'on',
'login': '登录'
}
captcha_url = response.css('img#captcha_image::attr(src)').get()
# 使用css获取带有captcha_image属性的img标签的src属性(图片验证码url),attr()是获取属性
# response是Scrapy在访问上面start_urls时返回的结果(登陆页面)
if captcha_url: # 如果登录页面有图片验证码的url,说明登录的时候需要图片验证码
captcha = self.regonize_captcha(captcha_url) # 调用手动输入图片验证码的函数
# 把获取到的图片验证码和captcha-id这两个参数加入到formdata
formdata['captcha-solution'] = captcha
formdata['captcha-id'] = response.xpath('//input[@name="captcha-id"]/@value').get()
# 发送post登录请求,将结果传给函数parse_after_login
yield scrapy.FormRequest(url=self.login_url, formdata=formdata, callback=self.parse_after_login)
def regonize_captcha(self, image_url): # 手动输入图片验证码
request.urlretrieve(image_url, 'captcha.png')
image = Image.open('captcha.png') # 用Image模块打开验证码
image.show() # show方法可以把验证码展示出来(电脑看图工具方式打开)
captcha = input('请输入图片验证码:')
return captcha # 最终返回输入的验证码
def parse_after_login(self, response): # 判断是否登录成功
if response.url == 'https://www.douban.com': # 登录成会跳转到豆瓣首页的url上,所以以此来判断
yield scrapy.Request(url=self.profile_url, callback=self.parse_profile)
# 登录成功的话就访问到个人中心,将结果传给函数parse_profile来执行修改签名操作
print('登录成功')
else:
print('登录失败')
def parse_profile(self, response): # 修改个性签名
if response.url == self.profile_url: # 判断当前页面是否在个人中心
print('进入个人中心,修改个性签名', response.url)
url = 'https://www.douban.com/j/people/akajiuren/edit_signature'
ck = response.xpath('//input[@name="ck"]/@value').get() # 从个人中心页面取出ck值
formdata = {
'ck': ck,
'signature': '我是软件'
}
# 构造url和参数,发送post数据来修改个性签名
yield scrapy.FormRequest(url, formdata=formdata, callback=self.parse_none)
# 这里只是修改个性签名,后面不做其他操作了,所以这里的callback给一个空的函数
# 不指定callback的话会继续执行parse函数,等于重新跑一遍了,这个时候程序会从当前页面(个人中心的页面) 去执行获取图片验证码和登录的一系列操作,那么肯定会出现错误
print('修改个性签名成功')
else:
print('修改个性签名失败:“没有成功进入个人中心页面”')
def parse_none(self, response):
pass
对接阿里云图片验证码识别api,自动识别豆瓣图片验证码
人人网:response.html:
<!Doctype html>
<html class="nx-main860">
<head>
<meta name="Description" content="人人网 校内是一个真实的社交网络,联络你和你周围的朋友。 加入人人网校内你可以:联络朋友,了解他们的最新动态;和朋友分享相片、音乐和电影;找到老同学,结识新朋友;用照片和日志记录生活,展示自我。"/>
<meta name="Keywords" content="Xiaonei,Renren,校内,大学,同学,同事,白领,个人主页,博客,相册,群组,社区,交友,聊天,音乐,视频,校园,人人,人人网"/>
<title>人人网 - 大鹏董成鹏</title>
<meta charset="utf-8"/>
<link rel="shortcut icon" type="image/x-icon" href="http://a.xnimg.cn/favicon-rr.ico?ver=3" />
<link rel="apple-touch-icon" href="http://a.xnimg.cn/wap/apple_icon_.png" />
<link rel="stylesheet" type="text/css" href="http://s.xnimg.cn/a86614/nx/core/base.css">
<script type="text/javascript">
if(typeof nx === 'undefined'){
var nx = {
};
}
nx.log = {
startTime : + new Date()
};
nx.user = {
id : "430868656",
ruid:"430868656",
tinyPic : "http://head.xiaonei.com/photos/0/0/men_tiny.gif ",
name : "新用户80620",
privacy: "99",
requestToken : '-1456040411',
_rtk : '74f7947f'
};nx.user.isvip = false;nx.user.hidead = false;nx.webpager = nx.webpager || {
};
nx.production = true;
</script>
<script type="text/javascript" src="http://s.xnimg.cn/a83151/nx/core/libs.js"></script>
<script type="text/javascript">
define.config({
map:{
"backbone":"http://s.xnimg.cn/a75208/nx/core/backbone.js",
"ui/draggable":"http://s.xnimg.cn/a70750/nx/core/ui/draggable.js",
"ui/menu":"http://s.xnimg.cn/a70736/nx/core/ui/menu.js",
"ui/resizable":"http://s.xnimg.cn/a70738/nx/core/ui/resizable.js",
"ui/sortable":"http://s.xnimg.cn/a70749/nx/core/ui/sortable.js",
"ui/tabs":"http://s.xnimg.cn/a78333/nx/core/ui/tabs.js",
"ui/ceiling":"http://s.xnimg.cn/a76297/nx/core/ui/ceiling.js",
"ui/columns":"http://s.xnimg.cn/a68070/nx/core/ui/columns.js",
"ui/dialog":"http://s.xnimg.cn/a76395/nx/core/ui/dialog.js",
"ui/fileupload":"http://s.xnimg.cn/a81310/nx/core/ui/fileupload.js",
"ui/pagination":"http://s.xnimg.cn/a70307/nx/core/ui/pagination.js",
"ui/placeholder":"http://s.xnimg.cn/a79685/nx/core/ui/placeholder.js",
"ui/progressbar":"http://s.xnimg.cn/a62964/nx/core/ui/progressbar.js",
"ui/rows":"http://s.xnimg.cn/a62964/nx/core/ui/rows.js",
"ui/scroll":"http://s.xnimg.cn/a61518/nx/core/ui/scroll.js",
"ui/scrollbar":"http://s.xnimg.cn/a76868/nx/core/ui/scrollbar.js",
"ui/select":"http://s.xnimg.cn/a82096/nx/core/ui/select.js",
"ui/slideshow":"http://s.xnimg.cn/a72804/nx/core/ui/slideshow.js",
"ui/speech":"http://s.xnimg.cn/a77631/nx/core/ui/speech.js",
"ui/textbox":"http://s.xnimg.cn/a79526/nx/core/ui/textbox.js",
"ui/renren/textbox":"http://s.xnimg.cn/a92727/nx/core/ui/renren/textbox.js",
"ui/tooltip":"http://s.xnimg.cn/a73228/nx/core/ui/tooltip.js",
"ui/renren/addfriend":"http://s.xnimg.cn/a78457/nx/core/ui/renren/addFriendLayer.js",
"ui/renren/at":"http://s.xnimg.cn/a78409/nx/core/ui/renren/atAndEmotion.js",
"ui/renren/emotion":"http://s.xnimg.cn/a78409/nx/core/ui/renren/atAndEmotion.js",
"ui/renren/commentCenter":"http://s.xnimg.cn/a83569/nx/core/ui/renren/commentCenter.js",
"ui/renren/friendgroup":"http://s.xnimg.cn/a62964/nx/core/ui/renren/friendGroup.js",
"ui/renren/friendListSelector":"http://s.xnimg.cn/a78513/nx/core/ui/renren/friendListSelector.js",
"ui/renren/like":"http://s.xnimg.cn/a83569/nx/core/ui/renren/like.js",
"nx/namecard":"http://s.xnimg.cn/a77668/nx/core/ui/renren/namecard.js",
"ui/renren/pagelayer":"http://s.xnimg.cn/a62964/nx/core/ui/renren/pageLayer.js",
"ui/renren/photoupload":"http://s.xnimg.cn/a82833/nx/core/ui/renren/photoupload.js",
"ui/renren/privacy":"http://s.xnimg.cn/a76680/nx/core/ui/renren/privacy.js",
"ui/renren/share":"http://s.xnimg.cn/a78999/nx/core/ui/renren/share.js",
"ui/renren/vocal":"http://s.xnimg.cn/a77347/nx/core/ui/renren/vocal.js",
"ui/renren/mvideo":"http://s.xnimg.cn/a80641/nx/core/ui/renren/mvideo.js",
"ui/renren/with":"http://s.xnimg.cn/a82994/nx/core/ui/renren/with.js",
"ui/clipboard":"http://s.xnimg.cn/a63417/nx/core/ui/clipboard.js",
"app/publisher":"http://s.xnimg.cn/a91505/nx/core/app/publisher.js",
"viewer":"http://s.xnimg.cn/a83025/nx/photo/viewer/js/viewer.js",
"media/player": "http://s.xnimg.cn/nx/photo/viewer/js/mediaplayer.js",
"ui/renren/like/commentseed":"http://s.xnimg.cn/a64636/nx/core/ui/renren/like.seed.comment.js",
"ui/renren/like/seed":"http://s.xnimg.cn/a62964/nx/core/ui/renren/like.seed.js",
"ui/renren/share/seed":"http://s.xnimg.cn/a62964/nx/core/ui/renren/share.seed.js",
"ui/renren/follow":"http://s.xnimg.cn/a78456/nx/core/ui/renren/follow.js",
"ui/renren/relationFollow":"http://s.xnimg.cn/a78457/nx/core/ui/renren/relationFollow.js",
"ui/autocomplete":"http://s.xnimg.cn/a70736/nx/core/ui/autocomplete.js",
"ui/showCommonFriend":"http://s.xnimg.cn/a78917/nx/core/ui/renren/showcommonfriend.js",
"photo/circler":"http://s.xnimg.cn/a73344/nx/photo/phototerminal/js/circler.js",
"ui/friendSearch":"http://s.xnimg.cn/a64338/nx/core/ui/renren/friendSearch.js",
"ui/renren/replyOption":"http://s.xnimg.cn/a68256/nx/core/ui/renren/replyOption.js",
"photo/avatarUpload": "http://s.xnimg.cn/a77340/nx/photo/upload-avata/js/avatarUpload.js",
"ui/renren/school":"http://s.xnimg.cn/a85689/nx/core/ui/renren/school.js"
}});
nx.data.isDoubleFeed = Boolean();
nx.data.isDoubleFeedGuide = Boolean();
</script>
<script type="text/javascript" src="http://s.xnimg.cn/a88603/nx/core/base.js"></script>
<!--[if lt IE 9]>
<script type="text/javascript">
document.execCommand("BackgroundImageCache", false, true);
</script>
<![endif]-->
<script type="text/javascript">
console.log('tiemline_v7.jsp');
nx.webpager.fold = true;
nx.user.pageid = 'profile';
</script>
<script type="text/javascript">
window._developer_no_webpager = true;
</script>
<script>XN = {
get_check:'-1456040411',get_check_x:'74f7947f',env:{
domain:'renren.com',shortSiteName:'人人',siteName:'人人网'}};</script>
<link href="http://s.xnimg.cn/a72965/n/core/global2-all-min.css" rel="stylesheet" />
<script src="http://s.xnimg.cn/a72842/n/core/base-all2.js"></script>
<script>
XN.getFileVersion([
'http://s.xnimg.cn/a19816/csspro/apps/profile.css',
'http://s.xnimg.cn/a54265/csspro/module/friendSelector.css',
'http://s.xnimg.cn/a16298/csspro/module/status-pop.css',
'http://s.xnimg.cn/a58689/csspro/module/school-selector.css',
'http://s.xnimg.cn/a64379/csspro/module/minieditor.css',
'http://s.xnimg.cn/a20457/jspro/xn.app.recommendFriend.js',
'http://s.xnimg.cn/a63482/jspro/xn.app.status.js',
'http://s.xnimg.cn/a69051/jspro/xn.app.share.js',
'http://s.xnimg.cn/a64158/jspro/xn.app.ilike.js',
'http://s.xnimg.cn/a58863/jspro/xn.ui.pager.js',
'http://s.xnimg.cn/a32035/jspro/xn.ui.multiFriendSelectorBox.js',
'http://s.xnimg.cn/a57199/jspro/xn.app.friend.group.js',
'http://s.xnimg.cn/a72369/jspro/lib/mediaplayer.js',
'http://s.xnimg.cn/a64992/jspro/xn.ui.schoolSelectors.js',
'http://s.xnimg.cn/a13200/jspro/album/ZeroClipboard.js',
'http://s.xnimg.cn/a66084/jspro/xn.ui.emoticons.js',
'http://s.xnimg.cn/a30963/n/apps/home/modules/drag-upload/drag-upload.js',
'http://a.xnimg.cn/n/core/modules/flashUploader/flashUploader.js',
'http://s.xnimg.cn/a33832/n/core/modules/flashUploader/upload-pop-all-min.css',
'http://s.xnimg.cn/a66726/n/core/feed/video/video-show.js'
]);
XN.namespace( 'user' );
XN.$extend(XN.user, {
'id':'430868656',
'ruid':'430868656',
'tinyPic':'http://head.xiaonei.com/photos/0/0/men_tiny.gif',
'name':"%E6%96%B0%E7%94%A8%E6%88%B780620",
'pageVersion':6
});
</script>
<link rel="stylesheet" type="text/css" href="http://s.xnimg.cn/a84113/apps/profile2/profile-all-min.css" />
<link rel="stylesheet" type="text/css" href="http://s.xnimg.cn/a62931/modules/global-publisher/products/profile/publisher-all-min.css" />
<link rel="stylesheet" type="text/css" href="http://s.xnimg.cn/a79828/nx/timeline/profile.css" /><script type="text/javascript" data-src="http://s.xnimg.cn/a84115/n/core/modules/ilike/index.js" data-module="xn/ilike"></script>
<script type="text/javascript">
var CoverInfo = {
uid: '880151247',
profileid: '430868656',
coverScale: '0.0',
coverAddress: '',
albumid: '0',
photoid: '0',
uploadCoverMd5String: 'ca53454ff28ef3eb79a5eb0e890e19f8'
};
var profileOwnerId = '880151247';
var profileOwnerName = '大鹏董成鹏';
var uid = '430868656';
var uname = '新用户80620';
var highlightIds = [];
var highlightNums = [];
var tlNavData = '[{"year":2016,"month":[4,3,2,1]},{"year":2015,"month":[12,11,10,9,8,7]}]';
var birthYear = '1982';
var birthMonth = '1';
var birthDay = '12';
var profileNowYear = '2018';
var profileNowMonth = '12';
var profileNowDay = '2';
if(XN) XN.pageId = 'profile'; // 照片弹層
var isInWhiteList = true; // 是否在百名单内
var isStar = 0; //是否是星级用户
var superAdmin = false; //超级管理员
var friend_type = '5'; //好友状态
var lastdayGuide = false; //末日引导下线
var isUseSkin = false;
var timelineV7 = true;
</script>
<script type="text/javascript" src="http://s.xnimg.cn/a53261/jspro/xn.app.gossip.js"></script>
<script type="text/javascript" src="http://s.xnimg.cn/a53030/jspro/xn.ui.minieditor.js"></script>
<script src="http://s.xnimg.cn/a90984/apps/profile2/combine/profile-v7.js"></script>
<script src="http://s.xnimg.cn/a90985/nx/timeline/profile-v7.js"></script>
<script type="text/javascript" src="http://s.xnimg.cn/a60989/n/apps/photo/modules/flashUploaderAndSend/friendSelector.js"></script>
<script data-src="http://s.xnimg.cn/a50466/apps/profile2/module/lifeevent/tplCreate.js" data-module="xn/profile/tplcreate"></script>
<script data-src="http://s.xnimg.cn/a49432/apps/profile2/module/lifeevent/tplEdit.js" data-module="xn/profile/tpledit"></script>
<link rel="stylesheet" type="text/css" href="http://s.xnimg.cn/a58377/jspro/privacy/style/index-all-min.css" media="all" />
<script type="text/javascript">
object.predefine('friendsSelector', 'http://s.xnimg.cn/a74102/jspro/xn.app.friendsSelector.js');
object.predefine('privacy', 'http://s.xnimg.cn/a73997/jspro/xn.app.privacy.js');
object.predefine('xn/feed/videoShow', 'http://s.xnimg.cn/a66726/n/core/feed/video/video-show.js');window.IS_PRIVACY_ON =