构造请求对象
一般的使用requests时,会先获取到下一页的url然后再执行requests.het(url)的操作
Scrapy中也是这样,找到下一页的url将url构造成一个请求对象,然后发送给Engine
实现步骤
1.获取到url
2.使用scrapy.Request(url,callback)方法callback为回调函数,即将url交给那个函数进行解析
默认为self.parse3.返回对象 yield scrapy.Request(url,callback)
其他的参数response.Request(url,callback,method,body,headers,cookies,meta,dont_filter=False)
url:传递要解析的url
callback:回调函数,默认为self.parse
method:请求方法,Get,Post,默认为Get
body:传递json字符串,在请求方式为Post时,传递的参数
headers:不包含cookies的字典
cookies:传递字典,指网站上的cookies
meta:实现数据再不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,请求深度等。
dont_filter:是否检查请求重复的url,默认为False,指的是检查,对url进行过滤
meta的使用
当请求到一条数据时,需要对其子网站进行访问,对其数据进行爬取,我们就可以用到meta方法
def parse(self,response):
...
yield response.Request(
url,
callback=self.parse_html,
meta={'item':item}
)
...
def parse_html(self,response):
# 通过response.meta['key']的方法来获取传递过来的数据
item = response.meta['item']
# 然后就可以对item进行增加数据了,这样的数据就添加到一个对象中了
...
yield item
cookies的使用
该类中有start-request的方法
所以我们要加上cookies来访问链接,就要在主spider文件中重写make_requests_from_url
这样即可
发送POST请求
可以使用Request中的设置method值为Post
也可以使用Scrapy内置的方法FormRequest(url,callback,formdata)
formdata为字典类型,即为传递的值构成的字典。
管道的使用
之前就实现了简单的文件写入
process_item(self,item.spider)
:
管道类中必须的函数
实现对item数据的处理
必须return item
我们还使用了__init__(self)和__del__(self)
这样是不常见的写法
scrapy中有内置的方法open_spider(self,spider)和close_spider(self,spider)
分别为爬虫开始的时候运行一次,和爬虫结束的时候运行一次
实例
当一个项目中存在两个爬虫文件,返回Item时,而管道文件中有多条管道,即写了不同的类来处理来自spider的数据,这样就不知道数据实际要传递到那个管道中去处理了。
解决方法,就是在管道前面加上if判断,因为open_spider和close_spider以及process_spider中都传递了spider的参数,他们都可以调用对应的spider类中的属性,这样就可以判断具体的书数据是来自那个爬虫文件的了。
crawlspider类
CrawlSpider类定义了一些规则(rule)来提供跟进link的方便的机制,从爬取的网页中获取link并继续爬取的工作更适合。
创建方法:
scrapy genspider -t crawl 爬虫名称 爬虫链接
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class Itcast3Spider(CrawlSpider):
name = 'Itcast3'
allowed_domains = ['www.itcast.cn']
start_urls = ['http://www.itcast.cn/']
rules = (
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
def parse_item(self, response):
item = {}
#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
#item['name'] = response.xpath('//div[@id="name"]').get()
#item['description'] = response.xpath('//div[@id="description"]').get()
return item
进入LinkExtractor查看方法
我们主要编写的就是allow()
继续看Rule()其中的callback赋值为一个字符串?
以前的callback回调函数赋值应该是一个函数名称才对啊
这是因为Rule是在类对象创建之后才进行引用的。
我们来简单实现一下
实现对腾讯软件管家中的软件url进行爬取获取详情页的url
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class Itcast3Spider(CrawlSpider):
name = 'Itcast3'
allowed_domains = ['pc.qq.com']
start_urls = ['https://pc.qq.com/category/c0.html']
rules = (
Rule(LinkExtractor(allow=r'/detail/.*?/detail_.*?.html'), callback='parse_item', follow=True),
)
def parse_item(self, response):
print(response.url)
item = {}
#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
#item['name'] = response.xpath('//div[@id="name"]').get()
#item['description'] = response.xpath('//div[@id="description"]').get()
return item
这样就可以获取到对应的url,在callback的函数中实现对其进行打印的代码
这个方法通常在一个页面中采集数据,当在多条页面中中采集数据使用Spider类比较好。
中间件
1.下载器中间件:Downloader middleware
2.爬虫中间件:Spider middleware
作用:实现对request和response的预处理
实现步骤:
1.在middlewares.py中编写中间件类
对于下载器中间件
有两种process_request()和process_response()方法其中的process_request方法为从engine到下载器模块的中间件方法,返回值有三个
1.return None:直接交给下载器模块
2.return request :交给调度器模块
3.return response:直接交给spider模块
其中的process_response方法为完成了Http请求返回到engine的方法,返回值只有两个
1.return request :返回给调度器
2.return response: 返回给spider模块
2.在settings文件中开启中间件的使用
后面的数值越大优先级越低
简单实现一下随机UA
在setting中创建UA池
在middleware中的downloadmiddleware实现最request的headers的User-ahent的设置
这里要return None使得请求能够到达download
在settings中打开中间件
实现动态加载
selenium的使用
页面中的数据不是瞬时加载的,就需要用到selenium来模拟浏览器登录