爬虫笔记
xpath 工具,获取HTML元素
节点修饰符
/ 根节点,(最外层元素标签)
// 子节点(相对路劲)
. 当前路径
.. 上一次路径
@xx 获取节点的属性
text() 获取值
包含语法(contains),包含部分就能够查找所有 //div[contains(@id,"qiushi_tag_")] (糗事百科)
数据解析方法
主要有结构化和非结构化分类
结构化:
json数据(高拼出现)
json 模块
re 模块
jsonpath模块
xml 数据 (低频出现)
re 模块
lxml 模块
非结构化
html
re 模块
lxml模块
服务器反爬的原因
1 爬虫占的PV(页面的访问次数, 每打开刷新一个页面的话,就占一个pv)总数较高,浪费资源
2 三月爬虫 , 毕业生在写论文的时候,会进行爬取一些网站数据,在进行分析
3 法律的灰色地带
爬虫反反爬机制
1 设置 headers 请求头(异步请求等) 和 设置 referew字段(从哪来发起的请求)
2 通过cookie来进行反爬
3 通过请求的参数来进行反爬
1根据html文件提取
2 通过发送请求获取数据
3 通过js来生成参数 (分析js,通过js2py获取js执行结果,或使用selenium)
4 验证码 (打码平台)
4 更换ip代理
scrapy 框架
- 1 scrapy 框架 是python开源 编写一个网络爬虫框架
网络爬虫的流程
流程:
1 首先我们有起始的url
2 拿到起始的url后放到URL队列,从队列中拿到URL发送网络请求获取响应
3 拿到请求响应后进行 解析响应内容,如果解析的是数据,那么将数据保存, 如果解析的 是url的话 返回给url队列,进行一个循环操作
scrapy 框架工作流程
简易理解
工作流程步骤:
1首先拿到起始的url 通过 scrapy 引擎(中间件)传递 到url队列中
2 从url 队列 拿出起始的url 给 发送请求获取响应(下载器), 得到响应对象之后 通过 scrapy 引擎 (中间件)传递给解析响应对象
3 解析响应对象,如果解析出新的URL对象之后 会再次给 url队列中,如果解析的是数据的 话 会拿给 scrapy 引擎(中间件)item poplin (管道)做 数据的保存或过滤
抽象讲 scrapy 工作原理
scrapy Engine (引擎)负责调度 各种模块的运行
Scheduler(调度器)接收引擎发送过来的request请求
spiders (爬虫) 负责处理解析出所有的数据和url,并将解析到新的URL提交给引擎,再次进入Scheduler(调度器)
Downloader (下载器)接收scrapy引擎发送过来的 url 进行发送请求获取响应
item pipeline (管道)负责处理 spiders 发送的过来的数据,进行保存。
scrapy 中每个模块的作用
创建项目
创建爬虫项目
scrapy startproject [项目名]
创建爬虫
cd 进入 爬虫项目
scrapy genspider [爬虫名字] [域名]
运行爬虫命令
scrapy crawl [爬虫名字]
定义元素以及提取数据,属性值的方法
从xpath 对象中提取数据 extract() 和 extract_first()
解析response并获取scrapy爬虫中的数据: 利用xpath规则字符串进行定位和提取
response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
提取数据:
额外方法extract():返回一个包含有字符串的列表
额外方法extract_first():返回列表中的第一个字符串,列表为空没有返回None
response响应对象的常用属性:
response.url:当前响应的url地址
response.request.url:当前响应对应的请求的url地址
response.headers:响应头
response.request.headers:当前响应的请求头
response.body:响应体,也就是html代码,byte类型
response.status:响应状态码
注意: 如果要存储数据的话,需要通过pipeline来保存数据。
函数中的yield能够传递的对象只能是:BaseItem, Request, dict, None
2 建模 可以通过items.py中建立所需的字段。然后在spider 中调用在使用.
3 meta:实现数据在不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,请求深度等
在爬虫文件的parse方法中,提取详情页增加之前callback指定的parse_detail函数:
def parse(self,response):
...
yield scrapy.Request(detail_url, callback=self.parse_detail,meta={"item":item})
...
def parse_detail(self,response):
#获取之前传入的item
item = resposne.meta["item"]
特别注意
- meta参数是一个字典
- meta字典中有一个固定的键
proxy
,表示代理ip,关于代理ip的使用我们将在scrapy的下载中间件的学习中进行介绍
scrape 获取cookie模拟登陆
第一种方法,使用的是直接获取cookie登录
第二种方法 通过scrapy.FormRequest能够发送post请求,同时需要添加fromdata参数作为请求体,以及callback
# 模拟登陆 GitHub,使用的是scrapy框架
import re
import scrapy
class GithubSpider(scrapy.Spider):
name = 'github'
allowed_domains = ['github.com']
start_urls = ['http://github.com/login']
# tARzc847MynkgK1DIeayOZMQHNNN22tj0usmHmGy4BjZ0gvpjWfxDefFqqf9BL9pgKGwJq2DTUHZG6itMmxdMA==
def parse(self, response):
token = response.xpath("//*[@id='login']/form/input[1]/@value").extract_first()
# 获取登录响应解析post的数据
data = {
"commit": "Sign in",
"authenticity_token": token,
"login": "xiaohua439912875",
"password": "kongguanghua520",
"webauthn-support": "supported"
}
# 2 根据url进行post请求
yield scrapy.FormRequest(
url="http://github.com/session",
formdata=data,
callback=self.parse_login
)
def parse_login(self, response):
match = re.search(r'"user-login" content="(.*?)"', response.text)
user_name = match.group(1)
print('UserName:', user_name)