- 安装:
- mac\ linux:
- pip install jquery
- windows:
- pip install wheel
- 下载twisted
- https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
- pip install Twisted-20.3.0-cp36-cp36m-win_amd64.whl
- pip install pywin32
- pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple
- 使用豆瓣镜像似乎安装不了。
- mac\ linux:
- 基本使用
- scrapy startproject 工程名
- spiders :爬虫文件夹
- 必须存放一个爬虫源文件
- settings.py:工程的配置文件
- 更改 USER_AGENT
- spiders :爬虫文件夹
- cd 工程名
- 创建爬虫文件夹 : 可以创建多个
- scrapy genspider spiderNAME www.xxx.com
- 编写对应的代码 在爬虫文件中
- parse 函数
- scrapy xpath 返回的是一个 selector 对象 数据用 extract或者 extract_first解析
- parse 函数
- 执行工程 :scrapy crawl spiderName
- 默认会输出所有的日志信息
- settings.py
- LOG_LEVEL = “ERROR” # 指定错误类型日志输出 减少cpu使用
- ROBOTSTXT_OBEY = False 禁止robots协议
- CONCURRENT_REQUESTS = 100 : 并发线程数
- 禁止cookie: COOKIES_ENABLED = False ;减少cpu使用
- 禁止重试: RETRY_ENABLED=False
- 禁止请求异常时中间件的修改操作
- 减少下载超时:
- DOWNLOAD_TIMEOUT =10 # 单位是秒
- settings.py
- 默认会输出所有的日志信息
- 创建爬虫文件夹 : 可以创建多个
- scrapy startproject 工程名
- 持久化存储:
- 1 基于终端指令的持久化存储
- 将 parse 的返回值保存的文件中
- scrapy crawl spiderName -o 文件
- 文件有格式要求
- csv 、json、jxml、marshal、。。。。
- 文件有格式要求
- 2 基于管道的持久化存储
- 在爬虫文件中进行数据解析
- 在items.py中定义相关属性
- 步骤一解析出几个属性,定义几个属性
- name = scrapy.Field()
- 步骤一解析出几个属性,定义几个属性
- 在爬虫文件中将解析的数据存储封装到Item类型的对象中
- 将Item类型的对象提交给管道
- yield item
- 在管道文件(pipelines.py)中接受爬虫文件提交过来的item类型对象,且对其进行任意形式的持久化存储操作
- open_spider(self, spider):
- 爬行器被打开时,执行
- close_spider(self, spider):
- 爬行器被结束时,执行
- open_spider(self, spider):
- 在配置文件中开启管道机制
- 基于管道实现数据的备份
- 将爬取的数据分别存储到不同的载体
- 一份存入 mysql 一份存入 redis
- 新建一个管道类
- 在settings.py 的 ITEM_PIPELINES 加入
- 类的位置:优先级(数字)
- 优先级高的类 的 process_item(self, item, spider):要返回 item
- return 是将item 传递给下一个将要执行的管道类
- 将爬取的数据分别存储到不同的载体
- 1 基于终端指令的持久化存储
请求传参
- 重写请求方法
- scrapy.Request(url=url, callback=self.parse) get请求
- scrapy.FormRequest(url=url, callback=self.parse) post请求
多页爬取
class DomeSpider(scrapy.Spider):
name = 'dome' # 爬虫文件的唯一标识
# 运行的域名
# allowed_domains = ['www.baidu.com']
# 起始url列表:只可以储存url
# 作用 列表中储存的url都会被进行get请求的发送
start_urls = ['http://xxx/1.html']
# 第一页
page = 1
# 数据解析
# start_urls的url请求成功一次 parse就会调用一次
# response 请求的结果
def parse(self, response):
title_content_list = response.xpath('//section//main/article')
for title_content in title_content_list:
# xpath 返回的是一个 selector 对象 数据用 extract或者 extract_first解析
title = title_content.xpath('./div[1]/h1/a/text()').extract_first()
content = title_content.xpath('./div[2]/p/text()').extract_first()
item = Dome1SacrpyItem()
item["title"] = title
item["content"] = content
yield item
if self.page < 5:
self.page += 1 # 页数叠加
url = f"http://duanziwang.com/category/{self.page}/index.html"
yield scrapy.Request(url=url, callback=self.parse)
深度爬取
class DomeSpider(scrapy.Spider):
name = 'dome' # 爬虫文件的唯一标识
# 运行的域名
# allowed_domains = ['www.baidu.com']
# 起始url列表:只可以储存url
# 作用 列表中储存的url都会被进行get请求的发送
start_urls = ['http://duanziwang.com/category/经典段子/index.html']
# 数据解析
# start_urls的url请求成功一次 parse就会调用一次
# response 请求的结果
page = 1
def parse(self, response):
title_content_list = response.xpath('//section//main/article')
for title_content in title_content_list:
# xpath 返回的是一个 selector 对象 数据用 extract或者 extract_first解析
# 商品
title = title_content.xpath('./div[1]/h1/a/text()').extract_first()
item = Dome1SacrpyItem()
item["title"] = title
# 商品详情页url
new_url = title_content.xpath('./div[2]/p/text()').extract_first()
# meta 就是 ==> 请求传参 --------------------------------------
yield scrapy.Request(url=new_url, callback=self.parse_xqy, meta={"item": item})
if self.page < 5:
self.page += 1 # 页数叠加
url = f"http://duanziwang.com/category/{self.page}/index.html"
yield scrapy.FormRequest(url=url, callback=self.parse)
# 详情页解析
def parse_xqy(self, response):
content = response.xpath('./div[2]/p/text()').extract_first()
item = response.meta["item"]
item["content"] = content
yield item
- 重写请求方法
中间件 <==>middlewares.py
- 爬虫中间件
- 下载中间件
- process_request(self, request, spider): 拦截请求
- 篡改请求UA
- 篡改url
- 篡改cookie
- process_response(self, request, response, spider): 拦截响应
- 篡改响应数据
- process_exception(self, request, exception, spider):拦截异常
- 修正错误url,重新发起请求
- 代理修改 proxy
- url 修改
- 修正错误url,重新发起请求
- process_request(self, request, spider): 拦截请求
大文件下载
- 图片、音频、视频 可以在管道类中进行请求
- 原始的管道类是没有这个条件的
scrapy 有封装好的管道类
- from scrapy.pipelines.images import ImagesPipeline
- 在settings.py中设置图片存放的文件夹路径
- IMAGES_STORE = “./image/“
- 通过继承,在改写下面的三个方法,可以实现文件下载的功能
- item 中必须有 image_urls,images 两个参数 ```python class ImgPipeline(ImagesPipeline):
请求图片数据
def get_media_requests(self, item, info): yield scrapy.Request(url=item[“src”], meta={item: “item”})
得到图片名称
def file_path(self, request, response=None, info=None, *, item=None): item = request.meta[“item”] return item[“filename”]
将item 给下一个管道类
def item_completed(self, results, item, info): return item ```
CrawlSpider
- 作用:全网页爬取
- 爬取网页上符合规则的url,通过当前爬取下一页的url
- 直到全部url获取到
- 创建方式
1. scrapy startproject 工程名
1. cd 工程名
1. scrapy genspider -t crawl 爬虫文件 www.xxx.com
1. scrapy crawl 爬虫文件
- 实例
- xxx
分布式
- 建立一个分布式机群,让机群中的每一台电脑执行同一程序,让其对同一组资源进行
- 联合且分布的数据爬取
- 通过scrapy-redis 组件
- 共享 调度器和管道
- pip install scrapy-redis -i https://pypi.tuna.tsinghua.edu.cn/simple
- 使用
- 建立工程
- 。。。。。
- ①:修改爬虫文件
- from scrapy_redis.spiders import RedisCrawlSpider
- 修改爬虫父类为 RedisCrawlSpider
- 添加 redis_key 属性 : redis_key = “xxx”,注释调allowed_domains,start_urls两个属性
- 正常解析
- ②:对seetings.py进行配置 (配置文件中不要加 LOG_LEVEL)
- 指定调度器
- 使用scrapy-redis组件中封装好的可以被共享的管道。
- ITEM_PIPELINES = { ‘scrapy_redis.pipelines.RedisPipeline’: 400, }
- 管道默认会连接且将数据存储到本机的redis服务中,如果想要连接存储到其他redis服务中需要在settings.py中进行如下配置
- 修改ua和关闭robots协议
- USER_AGENT = ‘XXXX’ # 伪装请求载体身份
- ROBOTSTXT_OBEY = False # 不遵从门户网站robots协议,避免某些信息爬取不到
- ③:redis数据库设置 :修改 redis.windows.conf
- ④:启动redis服务器和客服端
- redis-server 开启服务器
- redis-cli 开启客户端
- ⑤:执行工程
- scrapy crawl 工程名
- ⑥:向redis_kiy 中加入起始url
- redis 客户端 :lpush xxx www.xxxx.com
- 建立工程
查看redis
概念:检测网站数据更新情况,以便于爬取到最新更新的数据
- 核心:去重
- 方式: 记录表
- 实现
- redis 的 set
补充:
- 添加 cookie:
- 将settings.py 的 COOKIES_ENABLED 改为 True
- 在下载中间件(MfwDownloaderMiddleware)的 process_request 里面添加:
- request.cookies = { key:value}
- 在下载中间件(MfwDownloaderMiddleware)的 process_request 里面添加:
- 将settings.py 的 COOKIES_ENABLED 改为 Flase
- 重构 Spider 的 start_requests 函数
- cookie = { key:value}
- headers = { “User-Agent”=””, “Referer”: “”,}
- def start_requests(self):
yield scrapy.Request(url=self.start_url_custom, cookies=self.cookie, headers=self.headers, callback=self.parse, dont_filter=True)
- 重构 Spider 的 start_requests 函数
- 将settings.py 的 COOKIES_ENABLED 改为 True
scrapy+selenium:
在爬虫类中实例化一个浏览器驱动对象
- def init(self):
self.driver = self.googleinterface()
super()._init() - def google_interface(self, proxies=None): options = Options()
options.add_argument(“—headless”) # 添加无头浏览器** options.add_argument(“—disable-gpu”)
options.add_argument(“disable-infobars”)
# js注册 跳过浏览器检测
if proxies:
options.add_argument(f”—proxy-server={proxies}”) #添加代理** options.add_argument(“start-maximized”)
options.add_experimental_option(“excludeSwitches”, [ “enable-automation”])
options.add_experimental_option(“useAutomationExtension”, False)
google_diver = WebDriver(“chromedriver.exe”, options=options)
with open(“stealth.min.js”) as f:
js = f.read()
google_diver.execute_cdp_cmd(“Page.addScriptToEvaluateOnNewDocument”, {
“source”: js
})
# 最大化
google_diver.maximize_window()
return **google_diver- def init(self):
2在下载中间件的 process_response 函数中修改
- def process_response(self, request, response, spider):
# Called with the response returned from the downloader.
# Must either;
# - return a Response object
# - return a Request object
# - or raise IgnoreRequest
if “/i/“ in request.url:
spider.driver.get(request.url)
time.sleep(7)
# 页面下拉的最下面
- def process_response(self, request, response, spider):
spider.driver.execute_script(“window.scrollTo(0,document.body.scrollHeight);”) ** time.sleep(2)
spider.driver.execute_script(“window.scrollTo(0,document.body.scrollHeight);”)
time.sleep(2)
spider.driver.execute_script(“window.scrollTo(0,document.body.scrollHeight);”)
time.sleep(2)
first_half = spider.driver.page_source
return HtmlResponse(url=request.url, body=first_half, encoding=”utf8”, request=request)
return response
- 在 setting文件中 添加:
- DOWNLOADER_MIDDLEWARES = {
‘MFW.middlewares.MfwDownloaderMiddleware’: 543,
}
- DOWNLOADER_MIDDLEWARES = {