2020/04/12 02
scrapy提供了大量的脚手架,其实要写的部分都可以通过脚手架来完成
先是创建一个项目,明确爬取目标
这是项目里需要配置的东西
首先要配置user-agent和robotstxt协议改成false,不改成false,就会把别人不允许的都跳过不爬取,cookie一般 不用,除非你用cookie做一些事情,否则不要保留cookie了,相当于对url来讲每一次发起的都是全新的请求。
在爬取的时候注意并发数,浏览器对同一个域名发起的url请求是有限制的, 你不限制,就有可能判断出你不是一个浏览器就可能对你进行禁止,concurrent这个数字也是需要调整的。
如果要爬取多个网站,可以为某一个域设置单独的并发数,一般注意爬取的并发数和爬取的delay,每爬取到下一次的动作要歇一会,模拟人看网页的事情。
spider你只要写name就可以list出来
对网页分析好后可以写item,item的名字可以随便写,里面有字段,是个类字典对象,把属性写好,最后可以当字典来用
而后可以写爬虫,可以进行分析,用item来封装数据,封装数据后将这个数据打出去,yield出去,parse函数对spider来讲非常重要,最重要的就是parse,这个在spider中未实现,代表我们子类必须实现对response的解析
我们基于basic模版,有三大项必须写,name爬虫名字,域控制范围,起始url有哪些,最后返回数据到parse,parse进行解析
不想看详细过程,把nolog去掉即可
在这里可以导出分析里面的数据
解析url
上次写了book作为一个爬虫
解析需先把response的东西保存下来,保存下来给数据做测试,传统都是在scrapy shell进行测试,太麻烦
downloader把数据经过引擎给spider,然后分析数据给item pipeline,这个引擎就没有再接收其他start_urls之外的链接了,也就是scheduler就空的了,就不继续爬了。
如果spider还能返回一些request对象,就投递给scheduler,,然后发给downloader,返回response给spider,这样周而复始,知道scheduler没有东西爬取。
注意:scheduler爬取失败会再次尝试爬取
点text看一下
取body即可
直接用二进制就跟编码无关了,最好用一下编码,因为你打开也是要编码的,二进制存的话,你打开就要指定utf-8打开
这种更灵活,这样就按照response的encoding来存,这样就可以把爬取的页面保存
list先看看有什么能用的
重新来
大概流程,启动了lxml,还有twisted,openssl
读取了setting,在很早的时候就带上了user-agent
一些扩展和下载中间件
引擎,spider被打开了,200出来就是response是ok的
没有事情,spider就关闭了
最后把统计数据做一些综合显示
在爬取之间会爬取所有中间件,一旦开始爬取,downloader中间件开始启用了
编码utf-8是对的
现在准备读取,之前parse的解析都基于response
response是从这里来的
这个htmlresponse实际上是从scrapy,html 然后里面有htmlresponse
下面就需要去读取,点击进去查看源码该如何去写
如果有encodeing就pop掉,也就是可以指定encoding
textresponse是属于scrapy,http下的
set_body好像是保护方法不想给你用,body是个二进制的
这就是跟scrapy没什么关系了,现在用的直接导入的方式,用了缺失的url
这里是调用它的基类,点击__init__查看源码
这是调用response,基类写的很清楚,至少给一个url,body给一个bytes
没有内容,说明根本没读取
现在用二进制读进来,这样就完成了二进制的读取
因为有encoding,直接打印是没有问题的,现在内容拿到了,但是里面内容太多了
现在要进行分析了,从根开始找任意级li,这样就拿到了一个列表
告诉我们类型是它selectorlist,,本质上还是list,里面装满了你选中的selector
这个提供了很多方法,selector除了打印的时候有基本信息以外,还有data,这个里面就是想要的,extract就会把data从元素中抽取,但是我们extract是在selectorlist上做的,这个方法在list上还是没有的,是单独为这个类做的
遍历selectorlist然后把里面所有元素的data抽取出来,返回的依然是list。
上面是selector组成的列表,下面是把里面data抽取出来再封装成列表
看看遍历一下是什么,这里是string,
已经是string了,就不能再css了,数据已经抽出来了
这里遍历的就是selector,就可以继续在selector上做抽取,查看一下selectorlist
可以看看XPath代码里有什么
里面还有其他方法
有get和getall
看到etree就直达lxml里的东西
selector正好基于list
试试这个方法
get方法好在可以返回缺省值,extract_first的意思是拿到第一个
这样可以提取自己想要的内容,css不用写当前,XPath一定要写当前开始,找到一层层的li,下一级有h2,再往下有a
现在又变成了一个选择器的列表,XPath就是返回一个selectorlist
如果要提取内容就用extract,就变成普通的list了
现在需要把副标题也弄出来
css就不用相对路径还要在前面写什么相对了,直接告诉当前节点下找h2 找下一级a,用伪元素找,现在拿到的没什么区别
可以用first编码还是编码,副标题还是拿不到
这样就拿到副标题了
现在想把书名凑一下,遍历拿到元素就strip掉
下面要做的事情就是join到一块去,就可以不用map了,map还需要借助lambda表达式,这两个是一样的
这样就抽取出来,称为title
拿一下评分,看里面data,已经拿到span节点了
试试用XPath
把数据拿出来就用extract_first,把第一提取出来了
这样提取把selectorlist变成了list,first意思就是从list里面再抽取第一个出来
这两个等价
这样我们就拿到想要的结果了
我们可能还需要爬链接里的内容,并且要把链接交给scheduler里去,下回扔给downloader
这个页码有paginator
查看下页码,有些网页上下都有pagination,所以要自己试一下,大多数人都喜欢用XPath来写,结果只有一个就可以放心了
注意点:在第一页的时候前一页是没有的,第一页没有链接,也就是当前页都不给链接了
页数太多…,95,96,写一页又是20,抽取了这么多链接其实可以看到重复的,也就是下面要爬取页的时候,这些链接都抽取出来,明显看到有重复链接,组件里有scheduler有去重功能,我们可以不管,事实上可以不加思索把链接提取出来,engine给scheduler,然后scheduler负责去重,因为页面链接太多了(因为本页里有重复,2页里也有重复)
还有一种提取方式,第一页知道第二页在哪,第二页知道第三页在哪里,最后一页不知道下一页在哪里,就提取不到了。现在有很多网页都是虚的,点个几页就没了,一般情况不要倒着爬
现在要下一页,取href有两种方式来取,按元素来取,lxml可以用attrs,xpath可以直接写
现在就可以拿到下一页的url进行处理了
data就是我们要的东西。提取出来即可
这里还需要把url拼起来,response回来有url
这个url是输入的url
现在拼接起来有三种,以目前有拼接的url可能第二种更有可能
斜杠写在最前面是跟,如果是域名下,就是代表域名逻辑下的根
如果是逻辑上的跟,就直接是这个了
现在response有urljoin,是逻辑驱动器下的根,linux就没这个事情了
不让你这么改
写到上面去
现在这里就是得到的内容,从网站的跟开始,就是第二种
前面是斜杠是绝对路径,相当于写死了,从网站的根开始,如果是file协议,就是从当前根开始,没有斜杠就是相对路径
是第一种是因为c后面没加斜杠,就认为是个文件,是同级所以是第一种
在c后面加斜杠试试,认为这是个目录
有些地方避免出错,都会从根开始(网站都是从/根开始,拼接的时候要注意),当使用urljoin的时候,遵从了编程中相对路径和绝对路径概念
response是什么url管,但是里面的内容可以随你换
在spider中拼url,是没有什么大问题的,你把你提取的url一拼接即可
直接拼接即可
这里因为前面有/斜杠所以是绝对的
代码放开,现在url怎么提取也有了
现在要求我们只爬取前三页,<40就够了,就要a标签,span标签是前一页,下一页
现在就提取div下的这些,这里就拿到数据了
现在打印用extract即可,拿到了
现在要前三页,现在re前面拿到的是selectorlist,里面可以增强功能,是用正则表达式,必须要有这个东西,出来的是match,也就是match的东西打印出来了
start=数字后面任意匹配,是贪婪的,现在就是前半部分的问题,需要提取出来
需要加上前半部分
现在要前三页,特点是,0,20,40,正则表达式匹配2或4
前面返回的是selectorlist,用了re就是纯粹的list
正则表达式出来的是match,把match写好就行
也可以用XPath加谓语判断元素满足什么条件再输出
现在它的文本是否能进行比较,出来是selector
用extract就搞定了,这就是用的XPath的方式
如果搞定了item的提取,搞定了下一次链接的抽取,scrapy框架已经掌握差不多了,除了一些中间件不会用
准备对book里的spider进行改造,把title和rate凑成item扔出去,还要不断注入新的url,把这里的代码拿来
名字不好可以改一下
改一下名字
返回一个可迭代对象扔出去
需要借助request类
第一个是url,其他全是缺省值
刚才抽取的就是这样一个url,还需要join一下
还需要join一下,拼好之后,用request一封装,变成了一个生成器表达式返回一个生成器对象,然后yield一个个拿即可
这里所有走完之后,下面开始解析出我们想要的url,这个url又可以yield出去
都yield完,函数才算执行完,对于该response来讲,该yield出去的都yield出去了,在等下一个response来了
我们可以先把url准备好后,扔到scheduler里去
这里等于做完一大堆事情才可以开始爬取
**所以抛出的url靠前一点比较合适,如果读取的是next,就只有一个链接了,不需要yield from,用yield即可,如果是可迭代对象,在3.x用yield from是没问题 **
先把页码抽取出来,交给scheduler继续爬
如果是小于3,只有第一页和第二页
最后跑到pipeline里去
这里能写的就可以去官方文档
还可以写两个函数open_spider,close_spider,这样可以看到爬取了多少
在setting里去启用
这是pipeline的初始化过程
前面要加载完下载中间件,接着加载spider中间件,还要加载pipeline
加载完后可以运行了,数据到了downloader,response到了spider处理,在spider做大量解析,解析之后将提取的url
在spider做大量解析,解析之后将提取的url,由引擎交给scheduler,由它去重
item的数据最终到item pipeline,按照定义的pipeline一级级往下走,这个pipeline要初始化,打开后会调用open_spider,另一个会调用close_spider
官网上写了,前三个方法很常用
我们计数,最后把统计计数打印一下
2页应该显示40个左右
初始化,然后第一页的内容
打印response.url就能知道当前页是谁了,0是第一页
但是第二页又获取到了第一页的
第一页读取了两次就是60条
使用pipeline必须在settigs里配置,数字越小优先级越高,常用的open_spider,close_spider,官方没有提供init,所以init你也可以做一些初始化工作
这次仔细看一下过程
第一页确实是两次
这就是open_spider要做的事情
这里是pipeline
pipeline打开了就把spider也打开了
可以把数据写出去,模式w,encoding=utf-8,这样得到了一个file对象
现在是文本对象要写数据,序列化一下最合适,使用json
用dict把item对象包一下,dumps完加个换行
运行一下
把最后的不符合逗号删除,这样就把这一块内容写完了
现在用basic 模板做到,完全可以解决生产中的问题,但是在提取页码的时候会把start_url不算做去重的对象,也可以用正则表达式的re排除在外
这里是如何处理数据,如何解析数据
更多推荐
2020/04/12 02
发布评论