爬虫基础总结

1. 爬虫流程?
  1. 准备url列表
  2. 发起请求、获得响应
  3. 提取数据,提取url放入url列表
  4. 保存数据

聚焦爬虫的流程
注意:提取的数据以url对应的响应为准,浏览器element只能作为参考

2. requests的使用
`pip install requests`

2.1 基本使用

resp = request.get(url,headers,params)
resp = request.post(url,data,headers)
# 原始数据,bytes类型
resp.content
resp.content.decode()
# 根据响应信息进行有规律的推测网页的编码
resp.text
resp.encoding="utf-8"

2.2 保持会话

  1. session类
    session = requests.sesssion() # Session()
    session.get()
    session.post()
    # 每次请求后,会读取响应头的set——cookies,并在下次请求时自动携带
  1. Cookie字符串
    从浏览器的请求头中复制一份Cookie
    headers = {
        Cookie:"xxxx"
    }
    requests.get(url,headers=headers)
  1. cookies参数
    参数类型:dict
    cookies_dict = {}
    requests.get(url, headers=headers, cookies=cookies_dict)

2.3 设置UA,设置代理

    headers = {
        "User-Agent":"xxx"
    }
    requests.get(url, headers=headers)
    
    proxies = {
        "http":"http://192.168.1.1:80",
        "http":"http://192.168.1.1:80"
    }
    requests.get(url, headers=headers, proxies=proxies)
3. xpath提取数据
`pip install lxml`

3.1 xpath语法

//a[@class='next'] 通过属性值定位标签
//a[text()='下一页'] 通过文本定位标签
//a[contains(@class,'next')] 定位class属性包含next的所有a标签
//a[not(@class or @name)] 定位所有不包含class属性和name属性的a标签

/div//text() 提取div下面的所有文本
/a/@href  提取属性值
/a/text() 提取文本值

/div/a div下面的a标签,a是div的子结点
/div//a  div下面所有的a标签,a是div的后代结点

/a/follow-sibling::*[2] 获取a标签下面的所有兄弟结点的第二个
/a/follow-sibling::ul[1] 获取a标签下面所有ul的兄弟结点的第一个

3.2 lxml模块的使用

from lxml import etree
el = etree.HTML(str or bytes) # 参数可以是str或者bytes类型网页源代码
el.xpath("//a[@class='next']") # 返回是元素类型为element对象的列表
# element 具有xpath方法
el.xpath("//a/@href") # 返回元素类型为str的列表
4. scray框架

4.1 scrapy框架流程

  1. 调用start_requests()方法,将start_urls中所有的url构造成request对象,并放入调度器
  2. 引擎从调度器的请求队列中取出一个request,通过下载器中间件process_request()方法,交给下载器
  3. 下载器发起请求,获得响应,通过下载器中间件process_response()方法,到达引擎,再通过爬虫中间件的process_response()交给爬虫
  4. 爬虫提取数据
    3.1 提取出来的是数据,通过引擎交给管道
    3.2 提取出来的是url,构造请求,通过爬虫中间件的process_request()方法,交给调度器
  5. 管道进行数据清洗、数据保存

4.2 scrapy的基本使用

  • scrapy startproject myspider
  • cd myspider
  • scrapy genspider (-t crawl) bd baidu.com
    yield scrapy.Request(url,callback,meta,dont_filter) # url不会补全
    # callback 将来url响应的处理函数
    # dont_filter 默认false,过滤请求,重复的请求会被过滤
    
    yield reponse.follow(url,....) # url会自动补全
    
    def parse(self,repsonse):
        item = response.meta['item']
        response.xpath("").extract()
        response.xpath("").extract_first()

4.3 管道

  1. 开启管道
    在settting中,添加管道的路径
    ITEM_PIPELINES = {
       'suning.pipelines.SuningPipeline': 300, # 设置管道获取数据的优先级,数字越低,优先级越高
    }
  1. 方法
    process_item(item,spdier)
        if spider.name = "itcast" # spider当前传递item的爬虫对象
            item...
        return item # 如果下一个管道需要数据,必须返回item
    
    open_spdier(spider) # 每个爬虫开启的时候会执行一次
        # 数据库的连接初始化
    
    close_spdier(spider) # 每个爬虫关闭的时候执行一次
        # 数据库的关闭

4.4 中间件

  1. 开启中间件
    # SPIDER_MIDDLEWARES = {
    #    'suning.middlewares.SuningSpiderMiddleware': 543,
    # }
    
    DOWNLOADER_MIDDLEWARES = {
        'suning.middlewares.SeleniumMiddleware': 544,
    }
  1. 中间件的两个方法
    process_request(request,spider):
        return None # 1. 继续请求,
        return Request # 2. 请求不再继续,而是放入调度器
        return Response # 3. 请求不再下载,交给爬虫提取数据
    
    process_response(request,response,spdier):
        return Request # 1. 请求放入调度器
        return Response # 2. 继续经过其他中间件的process_response,或者到达引擎,后续交给爬虫处理
  1. 中间件的功能
  2. 设置UA
    process_request(request,spider):
        request.headers['User-Agent'] = random('UA')
  1. 设置代理
    process_request(request,spider):
        request.meta['proxy'] = 'http://192.168.1.1:80'
  1. 设置cookies(主要是为了反反爬)
    process_request(request,spider):
        request.cookies = cookies# 可以从cookies池随机取出一个
  1. scrpay集成selenium
    open_spdier(spider):
        if spider.name = "itcast":
            spider.driver = webdirver.Chrome()
    
    close_spider(spider);
        if spider.name = "itcast":
            spider.driver.quit()
    
    process_request(request,spdier);
        if spider.name = "itcast":
            spdier.dirver.get(request.url)
            return TextResponse(body=spdier.dirver.page_source,request=request,encoding="utf-8",url=spider.dirver.current_url)

4.5 post请求

    scrapy.FormRequest(url,callback,formdata)
    scrapy.FormRequest.from_response(response,fromdata,callback)

scrapy中默认开启的cookies传递,即本地请求获得的cookies,会在下次请求自动携带

    # Disable cookies (enabled by default)
    # COOKIES_ENABLED = False
  1. scrapy_redis

scrapy_redis 是scrapy框架的一个扩展组件,实现了两个功能:

  • 增量式爬虫
  • 分布式爬虫

实质:就是将请求队列和指纹集合进行了持久化存储

在seeeting.py中继续配置

    # 指定了去重的类
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    # 制定了调度器的类
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    # 调度器的内容是否持久化
    SCHEDULER_PERSIST = True
    REDIS_URL = "redis://127.0.0.1:6379"

5.1 如何去重

1.请求生成指纹

    fp = hashlib.sha1()
    fp.update(to_bytes(request.method))
    fp.update(to_bytes(canonicalize_url(request.url)))
    fp.update(request.body or b'')
    return fp.hexdigest()

利用hashlib的sha1,对request的请求体、请求url、请求方法进行加密,返回一个40位长度的16进制的字符串,称为指纹

  1. 进队
    def enqueue_request(self, request):
        if not request.dont_filter and self.df.request_seen(request):
            self.df.log(request, self.spider)
            return False
        self.queue.push(request)
        return True
  1. 如果请求需要过滤,并且当前请求的指纹已经在指纹集合中存在了,就不能进入队列了
  2. 如果不需要过滤,直接进入队列
  3. 如果请求需要过滤,并且请求的指纹是一个新的指纹,进入队列

5.2 实现分布式爬虫

类需要继承自 RedisSpider、RedisCrawlSpider
redis_key:表示,在redis数据库中存储start_urls的键的名称
  1. 数据去重

  2. 中间件去重

    process_response(request,response,spider):
        #set可以是内存set集合,也可以是redis的set
        ret = set.add(md5(response.body))
        if ret == 0:
            return request
        else
            return response
  1. 建立复合索引
    # 复合索引,加速和去重
    stu.ensure_index([("hometown", 1), ("age", 1)], unique=True)
    # 根据数据的特征,在mongodb中 对指定字段建立复合索引,所有字段值相同时就无法二次插入了
  1. 布隆过滤器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值