DAY 91 爬虫05
1 切换frame,动作链
2 xpath选择:在xml中查找内容的一门语言
-.
-..
-/
-//
-@
3 自动登录12306
-打码平台使用:别人帮我们破解验证码
-使用selenium点击,滑动
-有的网站会校验是否使用了自动化测试软件:
-window.navigator.webdriver
-获取验证码
-验证码图片的位置和大小
-屏幕截图,pillow抠图
-base64编码,存成图片,前面有标志部分
-base64的解码和编码
4 scrapy
-pip3 install scrapy
-7个组件
-爬虫:spiders文件夹下的一个个py文件,爬取的地址,解析数据
-爬虫中间件:介于爬虫和引擎之间的
-引擎:大总管,负责数据的流动
-调度器:爬取地址的调度和去重
-下载中间件
-下载器:负责下载
-管道:存储,数据清洗
-创建项目,创建爬虫
-scrapy startproject 名字
-scrapy genspider 爬虫名 爬虫地址
-scrapy crawl 爬虫名
-目录结构
-数据解析
-xpath
-拿文本:'.//a/text()'
-拿属性:'.//a/@href'
-css
-拿文本:'a.link-title::text'
-拿属性:'img.image-scale::attr(src)'
-取一条;extract_first()
-取多条:extract()
1 setting中相关配置
1 是否遵循爬虫协议
ROBOTSTXT_OBEY = False
2 请求客户端类型
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
3 日志级别(比--nolog好在,如果出错,控制台会报错)
LOG_LEVEL='ERROR'
2 持久化方案
1 第一种方案,直接存(很少)
-解析函数返回列表套字典
-执行:scrapy crawl cnblogs -o 文件名(json,pkl,csv结尾)
2 第二种:通用方法(pipline)
-1 在items.py中写一个类,继承scrapy.Item
-2 在类中写属性
title = scrapy.Field()
-3 在爬虫中导入类,实例化得到对象,把要保存的数据放到对象中
item['title'] = title
-4 修改配置文件,指定pipline,数字表示优先级,越小越大
ITEM_PIPELINES = {
'crawl_cnblogs.pipelines.CrawlCnblogsPipeline': 300,
}
-5 写一个pipline:CrawlCnblogsPipeline
-open_spider:数据初始化,打开文件,打开数据库链接
-process_item:真正存储的地方
-一定不要忘了return item,交给后续的pipline继续使用
-close_spider:销毁资源,关闭文件,关闭数据库链接
3 全站爬取cnblogs文章(scrapy的请求传参)
3.1 request和response对象传递参数
1 在request对象中
Request(url=url, callback=self.parse_detail,meta={'item':item})
2 在response对象中
item=response.meta['item']
3.2 解析出下一页的地址并继续爬取
next='https://www.cnblogs.com'+response.css('.pager a:last-child::attr(href)').extract_first()
print(next)
# yield Request(url=next,callback=self.parse)
yield Request(url=next)
4 提高爬取效率
#1 增加并发:
默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。
#2 降低日志级别:
在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘INFO’
# 3 禁止cookie:
如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False
# 4 禁止重试:
对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False
# 5 减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s
5 爬虫中间件和下载中间件
1 爬虫和下载中间件要使用,需要在配置文件中
SPIDER_MIDDLEWARES = {
'crawl_cnblogs.middlewares.CrawlCnblogsSpiderMiddleware': 5,
}
DOWNLOADER_MIDDLEWARES = {
'crawl_cnblogs.middlewares.CrawlCnblogsDownloaderMiddleware': 5,
}
6 加代理,加cookie,加header,加selenium
0 在下载中间件的process_reqeust方法中
1 加cookie
# request.cookies['name']='lqz'
# request.cookies= {}
2 修改header
# request.headers['Auth']='asdfasdfasdfasdf'
# request.headers['USER-AGENT']='ssss'
3 加代理
request.meta['proxy']='http://103.130.172.34:8080'
4 fake_useragent模块,可以随机生成user-aget
from fake_useragent import UserAgent
ua = UserAgent()
print(ua.ie) #随机打印ie浏览器任意版本
print(ua.firefox) #随机打印firefox浏览器任意版本
print(ua.chrome) #随机打印chrome浏览器任意版本
print(ua.random) #随机打印任意厂家的浏览器
5 如果process_request返回的是Request对象
-会交给引擎,引擎把请求放到调度中,等待下次被调度
6 集成selenium
-在爬虫类中类属性
driver = webdriver.Chrome(executable_path='')
-在爬虫类中方法:
def close(spider, reason):
spider.driver.close()
-在中间件中的process_reqeust中
from scrapy.http import HtmlResponse
spider.driver.get(url=request.url)
response=HtmlResponse(url=request.url,body=spider.driver.page_source.encode('utf-8'),request=request)
return response
7 去重规则源码分析
1 使用了集合去重
2 默认使用的去重类:
DUPEFILTER_CLASS = 'scrapy.dupefilters.RFPDupeFilter'
3 后期你可以自己写一个类,替换掉内置的去重
-布隆过滤器:极小内存校验是否重复
-https://www.cnblogs.com/xiaoyuanqujing/protected/articles/11969224.html
4 生成指纹,会把下面两种地址生成一样的指纹(本质是把?后面的参数排序,再生成指纹)
www.baidu.com?name=lqz&age=18
www.baidu.com?age=18&name=lqz
#布隆过滤器
# python中使用
#https://www.lfd.uci.edu/~gohlke/pythonlibs/#bitarray
pip3 install bitarray-xx.whl
pip3 install pybloom_live
from pybloom_live import ScalableBloomFilter
bloom = ScalableBloomFilter(initial_capacity=100, error_rate=0.001, mode=ScalableBloomFilter.LARGE_SET_GROWTH)
url = "www.cnblogs.com"
url2 = "www.liuqingzheng.top"
bloom.add(url)
print(url in bloom)
print(url2 in bloom)
8 scrapy-redis实现分布式爬虫
1 安装scrapy-redis
2 在原来的基础上,爬虫类继承RedisSpider
class CnblogsSpider(RedisSpider):
name = 'cnblogs_redis'
allowed_domains = ['www.cnblogs.com']
redis_key = 'myspider:start_urls'
3 在setting中配置
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 默认就是本地6379
#REDIS_HOST = 'localhost'
#REDIS_PORT = 6379
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 400
}
4 在多台机器上启动scrapy,向redis中插入起始爬取地址
scrapy crawl cnblogs_redis
redis-cli lpush myspider:start_urls https://www.cnblogs.com/