5.scrapy数据建模与请求
5.1 数据建模,通常是在items.py文件中进行数据建模
- 为什么要数据建模?
- 1.定义item即提前规划好哪些字段需要抓,防止手误,因为定义好之后,在运行过程中,系统会自动检查
- 2.配合注释一起可以清晰的知道要抓取哪些字段,没有定义的字段不能抓取,在目标字段少的时候可以使用字段代替。
- 3.使用scrapy的一些特定组件需要item做支持,如scrapy的ImagesPipeline管道类
5.2 如何建模
-
在items.py文件中定义提取的字段
class MyspiderItem(scrapy.Item): name = scrapy.Field() # 讲师的名字 title = scrapy.Field() # 讲师的职称 desc = scrapy.Filed() # 讲师的介绍
5.3如何使用模板类
模板类定义以后需要在爬虫中导入并且实例化,之后的使用方法和使用的字典相同
from items import MyspiderItem
class SpiderSpider(scrapy.Spider):
name = 'spider'
# 2.检查允许的域名
allowed_domains = ['itcast.cn']
# 1.修改启始的urlrl
start_urls = ['url']
def parse(self, response):
# 获取所有教师节点
node_list = response.xpath('/html/body/div[1]/div[5]/div/div[2]/div/ul/li')
# print(len(node_list))
# 遍历节点列表
for node in node_list:
# temp = {}
item = MyspiderItem()
# xpath方法返回的是选择器对象列表,extract()用于从选择器对象中提取数据;如果只有一个值可以使用extract_first()
item['name'] = node.xpath('./div/h3/text()')[0].extract()
item['title'] = node.xpath('./div/h4/text()')[0].extract()
item['desc'] = node.xpath('./div/p/text()')[0].extract()
yield item
5.4 翻页请求的思路
回顾requests模块是如何实现翻页请求的:
- 1.找到下一页的URL地址
- 2.调用requests.get(url)
scrapy实现翻页的思路:
- 1.找到下一页的URL地址
- 2.构造url地址的请求对象,传递给引擎
5.5 构造Request对象,并发送请求
实现方法
- 1.确定url地址
- 2.构造请求,scrapy.Request(url,callback)
- callback:指定解析函数名称,表示该请求返回的响应使用哪一个函数进行解析
- 3.把请求交给引擎:yield scrapy.Request(url,callback)
create_time 创建时间
update_time 更新时间
id
title 标题
source 来源作者
digest 摘要
content 内容
click 浏览量
index_image_url 图片
category_id 分类id
user_id 用户id
status 发布状态 0是发布
reason 审核不通过的原因
5.6 scrapy.Request的更多参数
scrapy.Request(url[,callback,method='GET',headers,body,cookies,meta,dont_filter=False])
参数:
1.中括号中的参数为可选参数
2.callback:表示当前的url的响应交给哪个函数去处理
3.meta:实现数据在不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,请求深度等。常用在一条数据分布在不同结构的多个页面的情况下。
4.dont_filter:默认为False,会过滤请求的url地址,即请求过的url地址不会被继续请求,对需要重复请求的url地址可以把它设置为True,比如贴吧的翻页请求,页面的数据总是在变化;start_urls中的地址会被反复启动,否则程序吧会启动
5.method:指定POST或GET请求
6.headers:接收一个字典,其中不包括cookies
7.cookies:接收一个字典,专门放置cookies
8.body:接收json字符串,为POST的数据,发送payload_post请求时使用
5.7 meta参数的使用
meta的作用:meta可以实现数据在不同的解析函数中传递
在爬虫文件的parse方法中,提取详情页增加之前callback指定的parse_detail函数:
def parse(self,response)
注意:
- meta参数是一个字典
- meta字典中有一个固定的键proxy,表示代理ip
6.scrapy模拟登陆
6.1 scrapy携带cookies直接获取需要登陆后的页面
应用场景
- 1.cookies过期时间很长,常用于一些不规范的网站
- 2.能在cookie过去之前把所有的数据拿到
- 3.配合其他程序使用,比如其使用selenium把登陆之后的cookie获取到保存到本地,scrapy发送请求之前先读取本地cookie
6.2 实现:重构scrapy的starte_requests方法
scrapy中start_url是通过start_requests来进行处理的,其实现代码如下:
# -*- coding: utf-8 -*-
import scrapy
class Git1Spider(scrapy.Spider):
name = 'git1'
allowed_domains = ['github.com']
start_urls = ['https://github.com/exile-morganna']
def start_requests(self):
url = self.start_urls[0]
temp = '_octo=GH1.1.1665811615.1584509726; _device_id=c462397b76932627bdccfdc3c4ea4947; has_recent_activity=1; _ga=GA1.2.952245887.1584509769; _gat=1; tz=Asia%2FShanghai; user_session=IECJaL_KnLnVA4cAejtZZ1WvYIzGd0jcvrE_N7xlZX9fFa6I; __Host-user_session_same_site=IECJaL_KnLnVA4cAejtZZ1WvYIzGd0jcvrE_N7xlZX9fFa6I; logged_in=yes; dotcom_user=Wang-TaoTao; _gh_sess=Z%2BQ5enKqPJYFwKCmnzlOYZR0LP0slwnSj3sX25Y0oCRlf6NjrbV58qqgkxHjHXIQc4jQQdisVZVgzYD2v1QJH9ftzNfoCDvC0%2BjpVHq3xC%2Fi9Bh3WoHMeFWMGra%2FqoZb%2FsydtcWz%2F5fbwUZcm9aB%2F0tpHAg0ZgvjN40JNZMOs7egeIXIIC5AieiMghJ5vwSwjGURNAXJautIzgLDboHhqJ6eY3pmlBIW5KFj6XJea8DKpi33cQRMjBAhx8NkD31%2FNO2MUW43IbS5ZezQxw%2BW8tsaXwuwM46XGrsvKzFJYYMv36WEz6xJ%2B8lExVQGgJxkzNGj%2BEJy0hCbvGx72Z6O7WfBnPzCDYfX98yXJB%2BX9Xos3ALsB%2Bfsw%2FPIOKetkJJvRNjF7vgzCnvnmqBQYZATvji211GHptqBL3eVNkFIh8KMjqS6iwad%2BOMp9PPs3p7CrMW%2B0430GA2MTtyVtB%2F2mfhPMmPHWGwyGAoXFMY1jK%2BIg2bOdJxzeznPjEPmVlgH9Lr07scwz2ooos1CYnBYfZBGOlgTyzZmHeHa9n4TT6adksUD2DuehxYJWGganXnZsUPffjyiZaSGXG2Bfz%2Bej4h%2FDacqYj9Agk88%2FXIpRQzwYqD%2FHA%2FdqwKrLhaNtdMrAJyEb5y4SZpfcKrSyQPuLWSycOxLWxhzQmgRBngy4iY0ObCv3GpK%2FHUJOuKmfrOfEdwB%2F3AxZ%2BssUphsoWJvOi40S4mD24r4jHc6PF0U760L2TAXKOnkJc%2F0cEmFHZXMosJrXEJ3rZ6RqBIDxGGAfq4HpfZWGDlj76QrTQo6vnjrw2wc4iasYp26h%2F1GMqVK32yPM5iDmPIJA5Q1uEwulvpczN0NG3COqMnlnT1Tjom%2BIOSmYRnPTt9zHEZwr5LNszqb0sQ6AsI7TypDER6AhThJKDQzqwPsHj8vHHIjVH6YMBrkC9ETlBGbaxrmF46fpFdS1kwKiHGo1PDieZ5KAypbvbvHq21q7PlnCFOqAqDGAC8vjYLL58%2FdBgcOHeMWOuALOm2fHrKBVkWegIRuXib7cyrSrDUShlPbYO0ZvYRmfGHuyscn2F2%2Bzg%2FOcIuXZ6Z4KfiwPeeqP3%2FK1b%2BPLa5OYrzXDqA%2FPemLzOiHQppqGjq2%2F%2FP%2FmGl3c60uXTp%2BWY9vbfewuFovnLqb68OO%2BpRdJeujmu2C9a4O1%2BJ4%2BD1ArL59ZWQhaJao%2F1EfYvw6ARim%2F1GPhFGe6L%2Br%2F1KWHEZDjUYnd7ido%2F82GTr4JQxTq1v7HZ9RAUUnWITrl0NH6%2FnrNSFPrbToigPSQZrTOUq5qvDWa5IrItwZ7I7P60PJiHlV9XYeKSAN8BpZipusUjrjpTg0NKbfV0bvvxqUrbAXimvo3K%2Ba6c%2BuMWnlz9Iu3ou1OIVIVZ70WuhBd%2FOUuJsCgRJlUbIhuuAuRBLOGCRCVmtU6ZNfHYuHs9ceqxA1jGhJvjqhDav%2BRUq22mndYQRci%2BJA7PmAML0xw84c6iJ97tKt1SNUFlqkdbGG97jearqrVJec2JFk6XsdpSE%2FPU1bOMYJ32bKmbDpaWugeuQYPiE6O5fApdSByM04BnlebWF2GxQ9eizX2YNSXpbuIB5dpHGpTT8v4kjNJfOMh0AfHF2Xj4bgBNGixyJBjxnk6jCN%2ByE2vAyBknhl06opE9YWS3B7aCcinpP0I%2Fg29hu0ticECzJe9%2FHXlgAfA5rE94%2B36EMNkA3R0d74a02Dxg2Huyza242sGZEDIPWNUOAhr%2Be2VFlejL9xQTjJPDDX9E0%2Fvj79M2eLebcV2A8gXW5jqC2o%2BlSgo8yG%2FxAWd1aSyFvKpXR7yVrTG6B4Qn4SMJeIhzHq%2FiTCbNA5QxeqYuOE%2B3KCYfCxT%2B4nkSg%2BREg4H0MfCfWhSFqhz%2FHXzIFGig2hgNOUiYxk2zVKyFfpJlJ%2B7amXmqYqXoS%2BvGheI9mooxR7zrvGFutnEPKVJS5gqUPb1bFbhrjq1U8jqoU9SID40%2BqGEMhpPI6xMpovnJvLaXIA54x7%2FDN5e8Yg7ko%3D--btXUtFuRy5nay9NQ--TfgJy9iEhmV7Q8au%2FW3Jcw%3D%3D'
cookies = {data.split('=')[0] : data.split('=')[-1] for data in temp.split('; ')}
yield scrapy.Request(
url = url,
callback = self.parse,
cookies = cookies,
)
def parse(self, response):
print(response.xpath('/html/head/title/text()').extract_first())
注意:
- 1.scrapy中的cookie不能够放在headers中,在构造请求的时候有专门的cookies参数,能够接受字典形式的cookie
- 2.在settings中设置ROBOTS协议、USER_AGENT
6.3 scrapy.Request发送post请求
- 1.发送post请求
- 思路分析
- 1.找到post的url地址:点击登录按钮进行抓包,然后哦定位url地址为https://github.com/session
- 2.找到请求体的规律:分析post请求的请求体,其中包含的参数均在前一次的响应中
- 3.是否登录成功:通过请求个人主页,观察是否包含用户名
- 思路分析
git2代码:老版本,现在参数已经和以前的不一样,但逻辑大体相同
# -*- coding: utf-8 -*-
import scrapy
class Git2Spider(scrapy.Spider):
name = 'git2'
allowed_domains = ['github.com']
start_urls = ['https://github.com/login']
def parse(self, response):
# 从登录页面响应中解析出post数据
token = response.xpath('//input[@name="authenticity_token"]/@value').extract_first()
post_data = {
'commit':"Sign in",
'utf8':'√',
'authenticity_token':token,
'login':'Wang-TaoTao',
'password':'wangtaotao',
'webauthn-support':'supported',
}
# 针对登录url发送post请求
yield scrapy.FormRequest(
url = 'https://github.com/session',
callback=self.after_login,
formdata=post_data,
)
def after_login(self, response):
yield scrapy.Request('https://github.com/exile-morganna',callback=self.check_login)
def check_login(self, response):
print(response.xpath('//input[@name="authenticity_token"]/@value').extract_first())