0%

小白进阶之Scrapy第二篇(登录篇)

QQ图片20161021225948其实拿这个网站当教程刚开始我是拒绝、换其他网站吧,又没什么动力···· 然后就··········· 上一篇Scrapy带大家玩了 Spider 今天带带大家玩的东西有两点、第一CrawlSpider、第二Scrapy登录。 目标站点:www.haoduofuli.wang 9555112 Go Go Go!开整! 还记得第一步要干啥? 创建项目文件啊!没有Scrapy环境的小伙伴们请参考第一篇安装一下环境哦! 打开你的命令行界面(Windows是CMD)使用切换目录的命令到你需要的存放项目文件的磁盘目录

1
2
D:
scrapy startproject haoduofuli

好了 我在D盘创建了一个叫做haoduofuli的项目。 用Pycharm打开这个目录开始我们的爬取之路 Come on! 下一步我们该做什么记得吧?当然是在items.py中声明字段了!方便我们在Spider中保存获取的内容并通过Pipline进行保存(items.py本质上是一个dict字典) 我在items.py中声明了以下类容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class HaoduofuliItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()

category = scrapy.Field() #类型
title = scrapy.Field() #标题
imgurl = scrapy.Field() #图片的地址
yunlink = scrapy.Field() #百度云盘的连接
password = scrapy.Field() #百度云盘的密码
url = scrapy.Field() #页面的地址

至于为啥声明的这些类容:各位自己去网站上观察一下、(主要是吧,贴在这儿的话 估计这博文就要被人道主义销毁了) 别忘记上一篇博文教大家的那种在IDE中运行Scrapy的方法哦! 好上面的我们搞定、开始下一步编写Spider啦! QQ图片20161021223818 在spiders文件夹中新建一个文件haoduofuli.py(还不清楚目录和作用的小哥儿快去看看Scrapy的第一篇) 首先导入以下包:

1
2
3
4
from scrapy.spiders import CrawlSpider, Rule, Request ##CrawlSpider与Rule配合使用可以骑到历遍全站的作用、Request干啥的我就不解释了
from scrapy.linkextractors import LinkExtractor ##配合Rule进行URL规则匹配
from haoduofuli.items import HaoduofuliItem ##不解释
from scrapy import FormRequest ##Scrapy中用作登录使用的一个包

详细介绍请参考:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/spiders.html 中的:CrawlSpider、爬取规则(Crawling rules)、pare_start_url(response)|(此方法重写start_urls)、以及Spider中start_requests()方法的重写。 下面我带大家简单的玩玩儿顺便获取我们想要的东西。 前面提到了我们需要获取全站的资源、如果使用Spider的话就需要写大量的代码(当然只是相对而言的大量代码)!但是我们还有另一个选择那就是今天要说的CrawlSpider! 吃惊表情1 首先我们新建一个函数 继承CrawlSpider(上一篇博文是继承Spider哦!) 见证奇迹的时刻到了!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from scrapy.spiders import CrawlSpider, Rule, Request ##CrawlSpider与Rule配合使用可以骑到历遍全站的作用、Request干啥的我就不解释了
from scrapy.linkextractors import LinkExtractor ##配合Rule进行URL规则匹配
from haoduofuli.items import HaoduofuliItem ##不解释
from scrapy import FormRequest ##Scrapy中用作登录使用的一个包

class myspider(CrawlSpider):

name = 'haoduofuli'
allowed_domains = ['haoduofuli.wang']
start_urls = ['http://www.haoduofuli.wang']

rules = (
Rule(LinkExtractor(allow=('\.html',)), callback='parse_item', follow=True),
)

def parse_item(self, response):
print(response.url)
pass

是不是很厉害!加上中间的空行也就不到二十行代码啊!就把整个网站历遍了!So Easy!! 上面的几行代码的意思 很明了了啊!我只说说rules这一块儿 表示所有response都会通过这个规则进行过滤匹配、匹配啥?当然是后缀为.html的URL了、callback=’parse_item’表示将获取到的response交给parse_item函数处理(这儿要注意了、不要使用parse函数、因为CrawlSpider使用的parse来实现逻辑、如果你使用了parse函数、CrawlSpider会运行失败。)、follow=True表示跟进匹配到的URL(顺便说一句allow的参数支持正则表达式、虽然我也用得不熟、不过超级好使) 至于我这儿的allow的参数为啥是’.\html’;大伙儿自己观察一下我们需要获取想要信息的页面的URL是不是都是以.html结束的?明白了吧! 然后rules的大概运作方式是下面这样: QQ截图20170122164117 图很清晰明了了(本人也是初学、如有错误 还请各位及时留言 我好纠正。)中间的数据流向是靠引擎来完成的。 好了 我们来看看效果如何: QQ20170122-011812 这是我们返回response的URL、一水儿的 URL啊!完美!下面就可以进行提取数据了(诶!不对啊怎么没有没什么提取工具啊!还记得上篇博文说的不?下载器返回的response是支持Xpath的哦!我们直接使用Xpath来提取数据就行啦!) 表情2 那么问题来了!Xpath没用过啊!不会用啊!这可咋整啊!别怕!草鸡简单的!!来不着急! 先大声跟我念:Google大法好啊! 哈哈哈 没错、我们需要Chrome(至于为啥不用Firefox、因为不知道为啥Firefox的Xpath有时和Chrome的结构不一样 有些时候提取不到数据、Chrome则没什么问题) 来来!跟着我的节奏来!包你五分钟学会使用Xpath!学不会也没关系、毕竟你也不能顺着网线来打我啊! 第一步:打开你的Chrome浏览器 挑选上面任意一个URL打开进入我们提取数据的页面(不贴图 容易被Say GoogBay): 第二步:打开Chrome的调试模式找到我们需要提取的内容(如何快速找到呢?还不知道的小哥儿 我只能说你实在是太水了) 点击下面红圈的箭头 然后去网页上点击你需要的内容就 哔!的一下跳过去了! QQ20170122-013435 第三步:在跳转的那一行就是你想要提取内容的一行(背景色完全区别于其它行!!)右键Copy ——Copy XPath: 就像下面我提取标题: QQ20170122-013823 你会得到这样的内容: //[@id=”post_content”]/p[1] 意思是:在根节点下面的有一个id为post_content的标签里面的第一个p标签(p[1]) 如果你需要提取的是这个标签的文本你需要在后面加点东西变成下面这样: //[@id=”post_content”]/p[1]/text() 后面加上text()标签就是提取文本 如果要提取标签里面的属性就把text()换成@属性比如: //*[@id=”post_content”]/p[1]/@src So Easy!XPath提取完毕!来看看怎么用的!那就更简单了!!!! response.xpath(‘你Copy的XPath’).extract()[‘要取第几个值’] 注意XPath提取出来的默认是List。 QQ图片20161021224219 看完上面这一段 估计还没有五分钟吧 !好了XPath掌握了!我们来开始取我们想要的东西吧!现在我们的代码应该变成这样了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from scrapy.spiders import CrawlSpider, Rule, Request ##CrawlSpider与Rule配合使用可以骑到历遍全站的作用、Request干啥的我就不解释了
from scrapy.linkextractors import LinkExtractor ##配合Rule进行URL规则匹配
from haoduofuli.items import HaoduofuliItem ##不解释
from scrapy import FormRequest ##Scrapy中用作登录使用的一个包

class myspider(CrawlSpider):

name = 'haoduofuli'
allowed_domains = ['haoduofuli.wang']
start_urls = ['http://www.haoduofuli.wang']

rules = (
Rule(LinkExtractor(allow=('\.html',)), callback='parse_item', follow=True),
)

def parse_item(self, response):
item = HaoduofuliItem()
item['url'] = response.url
item['category'] = response.xpath('//*[@id="content"]/div[1]/div[1]/span[2]/a/text()').extract()[0]
item['title'] = response.xpath('//*[@id="content"]/div[1]/h1/text()').extract()[0]
item['imgurl'] = response.xpath('//*[@id="post_content"]/p/img/@src').extract()
return item

我们来跑一下!简直完美! QQ20170122-020745 关于imgurl那个XPath: 你先随便找一找图片的地址Copy XPath类似得到这样的: //[@id=”post_content”]/p[2]/img 你瞅瞅网页会发现每一个有几张图片 每张地址都在一个p标签下的img标签的src属性中 把这个2去掉变成: //[@id=”post_content”]/p/img 就变成了所有p标签下的img标签了!加上 /@src 后所有图片就获取到啦!(不加[0]是因为我们要所有的地址、加了 就只能获取一个了!) 关于XPath更多的用法与功能详解,建议大家去看看w3cschool (^o^)/ 第一部分完工、开始第二部分的工作吧!登!录! QQ图片20161022193315 毕竟这些都不是我们要的重点!我们要的是资源 资源啊!能下载东西的地方!如果不是为了资源 那么爬虫将毫无意义(给工钱的另算)。 但是下载资源是隐藏的,需要登录才能看见(别找我要帐号、我也是借的别人的。) 我们先来看看这个网站是怎么登录的,使用Firefox打开www.haoduofuli.wang/login.php(为啥是Firefox、因为个人感觉Firefox的表单界面看起来很爽啊!哈哈哈) 打开页面之后开启调试模式(怎么开不说了)—开启持续日志(不然跳转之后没了) QQ截图20170122101749 然后选择网络—选中html和XHR(这样页面类容就会少很多、又不会缺少我们需要的东西) QQ截图20170122103140 现在开始登录(顺手把记住登录也勾上)!调试窗口不要关啊!!!!登录完毕之后你会发现出现一些内容 我们找到其中方法为post的请求、然后选择 参数 就能看到我们需要的登录表单啦! QQ截图20170122104241 我划掉的是帐号密码、这个位置应该显示你的帐号密码(这是很简单的一个登录表单、不通用但是思路是一样的。)找到了我们想要的东西我们开始登录吧 首先要知道Scrapy登录是如何实现的? 借助于FromRequests这个包实现的(前面已经导入过了),下面开整。不需要太大的改动只需增加一些函数 就可以轻而易举的实现的登录。 将我们的start_urls中的地址换掉换成我们我们的登陆地址www.haoduofuli.wang/login.php变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from scrapy.spiders import CrawlSpider, Rule, Request ##CrawlSpider与Rule配合使用可以骑到历遍全站的作用、Request干啥的我就不解释了
from scrapy.linkextractors import LinkExtractor ##配合Rule进行URL规则匹配
from haoduofuli.items import HaoduofuliItem ##不解释
from scrapy import FormRequest ##Scrapy中用作登录使用的一个包



account = '你的账号'
password = '你的密码'

class myspider(CrawlSpider):

name = 'haoduofuli'
allowed_domains = ['haoduofuli.wang']
start_urls = ['http://www.haoduofuli.wang/wp-login.php']

那么问题来了!参考上面的流程图你会发现、这丫的没法登录表单没法写啊!start_urls返回的responses就直接给rules进行处理了诶!我们需要一个什么方法来截断start_urls返回的responses 方便我们把登录的表单提交上去!那么问题来了 !该用啥? 答案是:parse_start_url(response)这方法;此方法作用是当start_url返回responses时调用这个方法。官方解释如下: QQ截图20170122105258 然后呢?当然是构造表单并通过FormRequests提交了!所以我们的程序现在就应该变成这样子了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from scrapy.spiders import CrawlSpider, Rule, Request ##CrawlSpider与Rule配合使用可以骑到历遍全站的作用、Request干啥的我就不解释了
from scrapy.linkextractors import LinkExtractor ##配合Rule进行URL规则匹配
from haoduofuli.items import HaoduofuliItem ##不解释
from scrapy import FormRequest ##Scrapy中用作登录使用的一个包



account = '你的帐号'
password = '你的密码'

class myspider(CrawlSpider):

name = 'haoduofuli'
allowed_domains = ['haoduofuli.wang']
start_urls = ['http://www.haoduofuli.wang/wp-login.php']

def parse_start_url(self, response):
###
如果你登录的有验证码之类的,你就可以在此处加入各种处理方法;
比如提交给打码平台,或者自己手动输入、再或者pil处理之类的
###
formdate = {
'log': account,
'pwd': password,
'rememberme': "forever",
'wp-submit': "登录",
'redirect_to': "http://www.haoduofuli.wang/wp-admin/",
'testcookie': "1"
}
return [FormRequest.from_response(response, formdata=formdate, callback=self.after_login)]

最后一句的意思是提交表单formdate并将回调after_login函数处理后续内容(一般用来判断是否登录成功) 然后开始请求我们需要爬取的页面 现在就变成这样了!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from scrapy.spiders import CrawlSpider, Rule, Request ##CrawlSpiderRule配合使用可以骑到历遍全站的作用、Request干啥的我就不解释了
from scrapy.linkextractors import LinkExtractor ##配合Rule进行URL规则匹配
from haoduofuli.items import HaoduofuliItem ##不解释
from scrapy import FormRequest ##Scrapy中用作登录使用的一个包



account = '你的帐号'
password = '你的密码'

class myspider(CrawlSpider):

name = 'haoduofuli'
allowed_domains = ['haoduofuli.wang']
start_urls = ['http://www.haoduofuli.wang/wp-login.php']

def parse_start_url(self, response):
###
如果你登录的有验证码之类的,你就可以在此处加入各种处理方法;
比如提交给打码平台,或者自己手动输入、再或者pil处理之类的
###
formdate = {
'log': account,
'pwd': password,
'rememberme': "forever",
'wp-submit': "登录",
'redirect_to': "http://www.haoduofuli.wang/wp-admin/",
'testcookie': "1"
}
return [FormRequest.from_response(response, formdata=formdate, callback=self.after_login)]


def after_login(self, response):
###
可以在此处加上判断来确认是否登录成功、进行其他动作。
###
lnk = 'http://www.haoduofuli.wang'
return Request(lnk)

rules = (
Rule(LinkExtractor(allow=('\.html',)), callback='parse_item', follow=True),
)

def parse_item(self, response):
item = HaoduofuliItem()
try:
item['category'] = response.xpath('//*[@id="content"]/div[1]/div[1]/span[2]/a/text()').extract()[0]
item['title'] = response.xpath('//*[@id="content"]/div[1]/h1/text()').extract()[0]
item['imgurl'] = response.xpath('//*[@id="post_content"]/p/img/@src').extract()
item['yunlink'] = response.xpath('//*[@id="post_content"]/blockquote/a/@href').extract()[0]
item['password'] = response.xpath('//*[@id="post_content"]/blockquote/font/text()').extract()[0]
return item
except:
item['category'] = response.xpath('//*[@id="content"]/div[1]/div[1]/span[2]/a/text()').extract()[0]
item['title'] = response.xpath('//*[@id="content"]/div[1]/h1/text()').extract()[0]
item['imgurl'] = response.xpath('//*[@id="post_content"]/p/img/@src').extract()
item['yunlink'] = response.xpath('//*[@id="post_content"]/blockquote/p/a/@href).extract()[0]
item['password'] = response.xpath('//*[@id="post_content"]/blockquote/p/span/text()').extract()[0]
return item

return Request(lnk)就表示我们的开始页面了 至于为啥多了一个try判断;完全是因为 这站长不守规矩啊!有些页面不一样·····我能怎么办 我也很无奈啊! 都是被逼的。囧 好了!Spider写完啦!但是我们的工作还没完!!!网站是靠什么知道这个request是否是登录用户发出的?答案是 Cookie! 所以我们需要 下载器 在下载网页之前在request中加入Cookie来向网站证明我们是登录用户身份;才能获取到需要登录才能查看的信息! 这个该怎么做?现在Scrapy的中间件派上用场了! 关于Cookie中间件参考:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/downloader-middleware.html#module-scrapy.contrib.downloadermiddleware.cookies 我们需要做的就是在settings.py中的 DOWNLOADER_MIDDLEWARES 开启这个中间件:scrapy.downloadermiddlewares.cookies.CookiesMiddleware 请注意!!!!!! 每一个中间件会对request进行操作、你所做的操作可能会依赖于前一个中间件、所以每个中间件的顺序就异常的重要。具体该设置多少请参考: http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/settings.html#std:setting-DOWNLOADER_MIDDLEWARES_BASE QQ截图20170122165743 中的值设置!!这点务必注意···如果不清楚依赖关系 请按照上图的值设置。 从上面可以看出Cookie中间件的值为700 、我们在settings.py设置也应该为700 QQ截图20170122170041 我注释掉的请无视掉!!! 做好这些以后Scrapy运作的整个流程大概就变成了下面这样: QQ20170122-232839

1
return Request(lnk) 这一个请求也算作 初始URL 只不过 不是start_urls的返回response 所以不会调用parse_start_url函数哦!

QQ20170122-230207 跑一下!效果杠杠滴!!!至于后面的数据持久化(如何保存数据、大家请自行解决哦!比毕竟上一篇博文讲过了、) 这种更适合使用MongoDB存储 超级简单好使。 至此本篇博文结束。 这个还有一个分布式的版本、现在不想写了··· 等年后再写吧。 另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。另外我真的一个资源都没看。