美文网首页python 爬虫 spider
selenium 实战爬取淘宝信息-excepted_condi

selenium 实战爬取淘宝信息-excepted_condi

作者: RevinDuan | 来源:发表于2018-08-29 16:54 被阅读0次

    selenium 高级用法--excepted_conditions和WebDriverWait
    看了崔静觅大大的博客,这里算是写出自己对内容的一些理解还有一个实操的小项目:
    selenium爬取淘宝商品
    另外附上另一篇
    selenium爬取京东商品

    环境: python3, pymongo, selenium, Chromedrive,chrome浏览器, pyquery,mongo数据库
    先说一下爬虫的思想:
    对于淘宝来说使用了js进行加密数据,我们这里使用可见即可爬的工具selenium进行爬取,过程如下:

    分析请求-> 找到目标信息-> 构造请求-> 提取信息-> 自动执行(翻页)

    整个小demo有4个函数:

    • save_to_mongo()
      储存数据的接口
    • get_products()
      获取每页商品的信息
    • index_page()
      判断是否加载,执行完成后推送给页面分析
      *main()
      实现翻页功能
      这里会详细介绍每行代码的意义,上代码:
    import pymongo
    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException  # 超时错误
    from selenium.webdriver.common.by import By   # 选择方式的模块
    from selenium.webdriver.support.wait import WebDriverWait  # 显示等待
    from selenium.webdriver.support import expected_conditions as EC # 条件支持
    from urllib.parse import quote  # 屏蔽特殊字符
    from pyquery import PyQuery as pq  # pyquery 查找分析节点
    
    # 创建一个谷歌浏览器对象
    browser = webdriver.Chrome()  
    # 设置等待时间最长为3s
    wait = WebDriverWait(browser, 3)
    # 搜索关键字,可以整合到config文件里
    KEYWORDS = 'iphone'
    # mongo的地址,这里可以使用远端的地址,实现分布式
    MONGO_URL = 'localhost'
    # 数据库名字
    MONGO_DB = 'taobao'
    # 数据库集合
    MONGO_COLLECTION = 'products'
    # 创建一个数据库对象
    client = pymongo.MongoClient(MONGO_URL, 27017)
    # 指定数据库名
    db = client.taobao
    # 指定爬取页码
    MAX_PAGE = 100
    
    
    def save_to_mongo(result):
        '''
        把结果保存起来
        :param result: 解析过后的商品信息
        :return:
        '''
        try:
            if db[MONGO_COLLECTION].insert(result):  # 这里使用了插入操作,更详细的应该是有去重回滚等操作这里不做演示
                print('save result successfully')
        except Exception:
            print('fail to save')
    
    
    def get_products():
        '''
        提取商品的数据
        :return:
        '''
        html = browser.page_source # 提取渲染过后的源码
        doc = pq(html)  # 创建pyquery对象,用于css选择器来提取信息
        items = doc('#mainsrp-itemlist .items .item').items()
        for item in items:
            # 提取商品的信息
            product = {  
                'image': item.find('.pic .img').attr('data-src'), 
                'price': item.find('.price').text(),
                'deal': item.find('.deal-cnt').text(),
                'title': item.find('.title').text(),
                'shop': item.find('.shop').text(),
                'location': item.find('.location').text()
            }
            print(product)
            # 传送给储存功能函数 
            save_to_mongo(product)
    
    
    def index_page(page):
        '''
        抓取索引页
        :param page:页码
        :return:
        '''
        print('正在爬取第{}页...'.format(page))
        url = 'https://s.taobao.com/search?q=' + quote(KEYWORDS)
        browser.get(url)
        print(page)
        if page > 1:
            print(page)
            input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager div.form > input')))  # 指定商品页面元素加载出来就继续往下执行,如果到时间没有加载会直接报错
            print(input)
            submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager div.form > span.btn.J_Submit'))) # 当选择的节点可以被点击的时候我们才继续往下走,超时报错
            input.clear() # 清理输入框
            input.send_keys(page) # 键入值
            submit.click() # 点击操作
            print('done')
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page))) # 等待指定的文本出现在某一个节点
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item')))
        get_products() # 等待指定的元素加载出来就可以继续往下执行否则报错
    
    
    
    def main():
        for i in range(1, MAX_PAGE + 1):
            index_page(i)
    
    
    if __name__ == '__main__':
    main()
    

    感兴趣的可以把这个在电脑上运行一下试试,看看会得到什么.
    另外 Chrome从59版本开始,支持无界面模式 Headless 模式,启用方式:

    chrome_options = wedriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    browser = webdriver.Chrome(chrome_options=chrome_options)
    

    感兴趣的同学可以把浏览器换成Firefox和PhantomJs试试,PhantomJs支持禁用图片加载功能,可以进一步提高爬虫效率

    SERVICE_ARGS = ['--load-images=false','--disk-cache=true']
    browser = webdriver.PhatomJs(service_args= SERVICE_ARGS)
    

    整个例子到这里结束了,我们来看下里面关于selenium等待的和条件判断的两个方法

    excepted_conditions
    selenium.webdriver.support.expected_conditions(模块)
    用于判断用户的传入的模块是否符合我们的需求,比如上面例子里写的,是否加载完成是否可见都可以作为判断标准,用于判断页面加载进度是否达到了我们的爬去需求.更多详细的方法看这里 第7点,关于等待的用法.

    WebDriverWait

    • 参数:
      WebDriverWait(driver, timeout, poll_frequency, ignored_exceptions)

    driver: 传入WebDriver实例,即我们上例中的driver
    timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间)
    poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒
    ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,
    则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。

    • 等待方式
      .until(method, message)
      until

    method: 在等待期间,每隔一段时间(init中的poll_frequency)调用这个传入的方法,直到返回值不是False
    message: 如果超时,抛出TimeoutException,将message传入异常

    not_until
    与上方信息操作相反
    这里注意的一点就是method参数,这个参数一定是可以调用的,一定要有 call() 方法,否则会抛出异常

    综上所写,那么完整的方式应该是下面的结构

    WebDriverWait(driver, timeout, poll_frequency, ignored_exceptions).until(method, message)

    具体的实现方式就像例子里一样, 等待配合判断来进行爬虫的操作可以,缩短爬虫的等待时间实现爬虫的效率的最大化,极大的提高爬虫的效率.

    感谢崔静觅大大的教程!

    相关文章

      网友评论

        本文标题:selenium 实战爬取淘宝信息-excepted_condi

        本文链接:https://www.haomeiwen.com/subject/zwfkwftx.html