爬虫笔记

一、bs4和lxml

 

 

 

 -------------------------------------------------------------------------------------------------------------

二、requests模块高级操作

 

 

 ——————注意代理参数格式是{ 'http/https'  : " ip:端口 “ }字典

 

 --------------------------------------------------------------

三、异步多任务爬虫(gevent是多协程)

3.1gevent多协程

 

 1 import uuid
 2  
 3 import gevent
 4 from gevent import monkey, pool
 5 import time, random
 6 import urllib.request
 7  
 8 monkey.patch_all()
 9  
10 jpg_num = 0
11  
12  
13 def down_load_img(img_uel, img_name):
14     global jpg_num
15     jpg_num += 1
16     print("正在下载第{}张".format(jpg_num))
17  
18     img = urllib.request.urlopen(img_uel)  # 设置网络连接
19     img_content = img.read()  # 读取网址信息
20     # 设置一个新的文件并将信息写入
21     with open(r"%s" % img_name, "wb") as f1:
22         f1.write(img_content)
23         time.sleep(random.random())
24     time.sleep(2)
25  
26  
27 def main():
28     p = pool.Pool(50)  # 创建协程池
29     url = 'https://www.google.com/imgres?imgurl=https%3A%2F%2Fpic2.cwuzx.com%2Fe390d4d07e852ebc2de3bbbbfd08bb31db705194-800.jpg&imgrefurl=https%3A%2F%2Fwww.cwuzx.com%2Fimage%2F24.html&tbnid=VTjovih6x09TsM&vet=12ahUKEwi4n_fHm5nqAhXwzIsBHWacBQ0QMygFegUIARCrAQ..i&docid=HC2ZQVVBJ4T2qM&w=650&h=432&q=%E7%8C%AB%E5%9B%BE%E7%89%87&ved=2ahUKEwi4n_fHm5nqAhXwzIsBHWacBQ0QMygFegUIARCrAQ'
30     ret_list = [url for i in range(0,1000)]
31  
32     # 重置列表
33     num = 0
34     my_list = []
35  
36     t_start = time.time()  # 设置开始时间
37     for img_url in ret_list:
38         my_list.append(p.spawn(down_load_img, img_url, "%s.jpg" % str(uuid.uuid4())))
39         if num == 100:  # 设置想要的下载文件数量
40             break
41         num += 1
42  
43     gevent.joinall(my_list)  # 添加任务到协程池
44     t_stop = time.time()  # 设置结束时间
45     print("下载文件一共用了:%.2f秒" % (t_stop - t_start))  # 计时
46  
47  
48 if __name__ == '__main__':
49     main()

 

3.2 async(参考:https://www.cnblogs.com/yoyoketang/p/16256696.html

 

 

import time
import asyncio


async def washing1():
    await asyncio.sleep(3)  # 第一台洗衣机,
    print('washer1 finished')  # 洗完了


async def washing2():
    await asyncio.sleep(8)
    print('washer2 finished')


async def washing3():
    await asyncio.sleep(5)
    print('washer3 finished')

if __name__ == '__main__':
    print('start main:')
    start_time = time.time()
    # step1 创建一个事件循环
    loop = asyncio.get_event_loop()
    # step2 将异步函数(协程)加入事件队列
    tasks = [
        washing1(),
        washing2(),
        washing3()
    ]
    # step3 执行事件队列 直到最晚的一个事件被处理完毕后结束
    loop.run_until_complete(asyncio.wait(tasks))
    end_time = time.time()
    print('-----------end main----------')
    print('总共耗时:{}'.format(end_time-start_time))



async def my_coroutine(task_name, duration):
    print(f"Task {task_name} started")
    await asyncio.sleep(duration)
    print(f"Task {task_name} finished")

async def main():
    tasks = []
    for i in range(3):
        task = asyncio.create_task(my_coroutine(f"Task-{i}", 2))
        tasks.append(task)

    await asyncio.gather(*tasks)

asyncio.run(main())

 

四、selenium在爬虫的应用

    4.1 工作原理

   4.2 元素定位

#示例如下
from selenium.webdriver.common.by import By
driver.find_element(By.ID,'元素id')
driver.find_element(By.name,'元素name')
driver.find_element(By.class,'元素class')

# 或
driver.find_element('id','元素id')
driver.find_element('name','元素name')
driver.find_element('class','元素class')

 

五、玩转scrapy框架的具体应用

  5.1 安装和基本使用(参考)

     pip install scrapy

    常见问题——————————————点击————————————————

——————————————————————手动请求发送(post and get)----------------------------------------------------------------------

 ---------------------------------------------------------------请求传参(meta传递item)-------------------------------------------

 ---------------------------------下载中间件-------------------------

 ---------------------------深度爬取-------------------------

CrawlSpider实现的深度爬取
    - 通用方式:CrawlSpider+Spider实现

selenium在scrapy中的使用
    - https://news.163.com/
    - 爬取网易新闻中的国内,国际,军事,航空,无人机这五个板块下所有的新闻数据(标题+内容)
- 分析
    - 首页没有动态加载的数据
        - 爬取五个板块对应的url
    - 每一个板块对应的页面中的新闻标题是动态加载
        - 爬取新闻标题+详情页的url(***)
    - 每一条新闻详情页面中的数据不是动态加载
        - 爬取的新闻内容

- selenium在scrapy中的使用流程
    - 1.在爬虫类中实例化一个浏览器对象,将其作为爬虫类的一个属性
    - 2.在中间件中实现浏览器自动化相关的操作
    - 3.在爬虫类中重写closed(self,spider),在其内部关闭浏览器对象

 -------------------------------------分布式爬虫----------------------------

 

分布式
- 实现方式:scrapy+redis(scrapy结合着scrapy-redis组件)
- 原生的scrapy框架是无法实现分布式
    - 什么是是分布式
        - 需要搭建一个分布式的机群,让后让机群中的每一台电脑执行同一组程序,让其对同一组资源
            进行联合且分布的数据爬取。
    - 为什么原生的scrapy框架无法实现分布式?
        - 调度器无法被分布式机群共享
        - 管道无法分布式机群被共享
    - 如何实现分布式:使用scrapy-redis组件即可
    - scrapy-redis组件的作用:
        - 可以给原生的scrapy框架提供共享的管道和调度器
        - pip install scrapy-redis
- 实现流程
    1.修改爬虫文件
        - 1.1 导包:from scrapy_redis.spiders import RedisCrawlSpider
        - 1.2 修改当前爬虫类的父类为:RedisCrawlSpider
        - 1.3 将start_url替换成redis_keys的属性,属性值为任意字符串
            - redis_key = 'xxx':表示的是可以被共享的调度器队列的名称,最终是需要将起始的url手动
            放置到redis_key表示的队列中
        - 1.4 将数据解析的补充完整即可
    2.对settings.py进行配置
        - 指定调度器
            # 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
            DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
            # 使用scrapy-redis组件自己的调度器
            SCHEDULER = "scrapy_redis.scheduler.Scheduler"
            # 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
            SCHEDULER_PERSIST = True
        - 指定管道
            ITEM_PIPELINES = {
                'scrapy_redis.pipelines.RedisPipeline': 400
            }
            - 特点:该种管道只可以将item写入redis
        - 指定redis
            REDIS_HOST = 'redis服务的ip地址'
            REDIS_PORT = 6379
    3.配置redis的配置文件(redis.window.conf)
        - 解除默认绑定
            - 56行:#bind 127.0.0.1
        - 关闭保护模式
            - 75行:protected-mode no
     4.启动redis服务和客户端
     5.执行scrapy工程(不要在配置文件中加入LOG_LEVEL)
        - 程序会停留在listening位置:等待起始的url加入
     6.向redis_key表示的队列中添加起始url
        - 需要在redis的客户端执行如下指令:(调度器队列是存在于redis中)
            - lpush sunQueue http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1

具体详情:https://www.cnblogs.com/Liu928011/p/14999692.html 

增量式
- 概念:监测网站数据更新的情况,以便于爬取到最新更新出来的数据。
- 实现核心:去重
- 实战中去重的方式:记录表
    - 记录表需要记录什么?记录的一定是爬取过的相关信息。
        - 爬取过的相关信息:每一部电影详情页的url
        - 只需要使用某一组数据,该组数据如果可以作为该部电影的唯一标识即可,刚好电影详情页的url
          就可以作为电影的唯一标识。只要可以表示电影唯一标识的数据我们统称为数据指纹。
- 去重的方式对应的记录表:
    - python中的set集合(不可以)
        - set集合无法持久化存储
    - redis中的set可以的
        - 可以持久化存储

- 数据指纹一般是经过加密
    - 当前案例的数据指纹没有必要加密。
    - 什么情况数据指纹需要加密?
        - 如果数据的唯一标识标识的内容数据量比较大,可以使用hash将数据加密成32位的密文。
            - 目的是为了节省空间。

  

 

 

posted on 2024-02-27 20:59  leiyunfeng  阅读(4)  评论(0编辑  收藏  举报