zoukankan      html  css  js  c++  java
  • 爬虫-实现思路

    实现爬虫的思路

    # 准备url
    -- start_url (url地址规律不明显,总数不确定,通过代码提取下一页)
    	xpath
        找url,部分参数在当前响应中
    -- url_list (页码总是明确,url地址规律)
    # 发送请求,获取响应
    -- 添加随机的user-agent
    -- 添加随机的代理ip
    -- 添加更多的headers字段,包括cookie
    -- cookie可以使用session解决,self.session = requests.Session()
    -- 准备一堆能用的cookie组成cookies池,存储respoonse中的cookies,下一次请求的时候,使用之前列表中的cookie来请求
    -- 如果要登录,准备多个账号,使用程序获取每个账号的cookie
       之后请求登录之后才能访问的网站随机的选择cookie
        
    # 提取数据
    -- 确定数据的位置
    	1. 数据在当前的url地址请求结果中
        	- 提取的是列表也数据
            - 提取的是详情页的数据(确定url,发请求,提取数据)
            
        2. 数据不再当前的url地址中
        	- 在network中从上往下找
            - 使用chrome中的过滤条件,选择除了css,img之外的
            - 使用chrome中的search all file,搜索数字和英文(如果中文搜不到)
    -- 提取数据
    	1. xpath (可提取整块数据)
        2. 正则
        3. json
    
    # 保存数据
    -- 保存到本地
    -- 保存到数据库
    

    注意要点

    # 尽量减少请求次数
    1. 能抓列表页就不抓详情页
    2. 保存获取到的html页面
    # 关注网站的所有类型
    1. wap页面,触屏版页面
    2. H5页面
    3. APP
    # 多伪装
    1. 动态UA
    2. 代理IP
    3. 不使用cookie
    # 多线程,分布式
    

    多线程实现爬虫模板

    
    '''
    思路:每个方法不同的线程,传递参数,使用队列(线程安全)
    Queue.join  # 让主线程阻塞,
    Queue.put   # 计数加一
    Queue.get
    Queue.task_done   # 与get连用才会计数减一
    '''
    from queue import Queue
    import requests
    from lxml import etree
    from threading import Thread
    
    class QiuShiSpider(object):
        def __init__(self):
            self.base_url = ''
            self.headers={}
            self.url_list_queue = Queue()
            self.parse_html_queue = Queue()
            self.content_list_queue = Queue()
    
        def get_url_list(self):
            for i in range(14):
                self.url_list_queue.put(self.base_url.format(i))
    
        def parse_url(self):
            while True:   # 多次执行
                url = self.url_list_queue.get()
                res = requests.get(url,headers=self.headers)
                self.parse_html_queue.put(res.content.decode())
                self.url_list_queue.task_done()
    
        def get_content_list(self):
            while True:
                html_str = self.parse_html_queue.get()
                html = etree.HTML(html_str)
                div_list = html.xpath('//div[@id="content-left"]/div')
                content_list = []
                for div in div_list:
                    # 内容在div的span标签下
                    item = {}
                    # 内容多行是个列表
                    item['content'] = div.xpath(".//div[@class='content']/span/text()")
                    item['gender'] = div.xpath(".//div[contains(@class,'articleGender')]/@class")
                    item['gender'] = item['gender'][0].split(' ')[-1].replace("Icon","") if len(item['gender'])>0 else None
                    content_list.append(item)
    
                self.content_list_queue.put(content_list)
                self.parse_html_queue.task_done()
    
        def save_data(self):
            while True:
                content_list = self.content_list_queue.get()
                for i in content_list:
                    pass
                self.content_list_queue.task_done()
    
        def run(self):
            thread_list = []
            # 获取url_list
            get_url_list = Thread(target=self.get_url_list())
            thread_list.append(get_url_list)
    
            #发送请求,获得相应,速度慢可以起多个线程
            for i in range(3):
                parse_url = Thread(target=self.parse_url())
                thread_list.append(parse_url)
    
            # 提取数据
            for i in range(2):
                get_content_list = Thread(target=self.get_content_list())
                thread_list.append(get_content_list)
    
            # 保存
            save_data = Thread(target=self.save_data())
            thread_list.append(save_data)
    
            # 所有的线程都是while true,不会结束,所以设置子线程为守护线程
            for t in thread_list:
                t.setDaemon(True)
                t.start()
    
            # 子线程执行完了以后,主线程再结束,join方法
            for q in [self.url_list_queue,self.parse_html_queue,self.content_list_queue]:
                q.join()
            print('q.join()可以等队列任务完成,主线程再结束')
    
    
  • 相关阅读:
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Apache Commons Lang的StringUtils.isEmpty(STR)和StringUtils.isBlank(STR)
    随记MySQL的时间差函数(TIMESTAMPDIFF、DATEDIFF)、日期转换计算函数(date_add、day、date_format、str_to_date)
    jquery,checkbox无法用attr()二次勾选
    随笔记:如何使用Python连接(/操作)Oracle数据库(Windows平台下)
    MySQL获取随机数
    Python的模块调用
  • 原文地址:https://www.cnblogs.com/Afrafre/p/11700767.html
Copyright © 2011-2022 走看看