python使用selenium爬取InCites中journal数据

  • selenium的基本使用方法:
感谢博主静觅的文章,里面有详细的python中selenium的用法。需要提醒的是implicitly_wait()的用法:设置的隐性等待时间是适用全局的,因此值不宜设置太大,会严重拖慢爬虫程序的速度。

  • 关于selenium实践时的二三问题:
任务目标是爬取每一年的每个分类的journal数据,因此就有两个重要的列表需要爬取,年份列表和分类列表。
2.1  时间列表的定位
虽然列表用find_elements方法很容易获取到一个大列表,但是这种操作的弊端在与很容易遇到在遍历时某个元素不在DOM资源中的异常。这里给出的解决方法是用Xpath 每次定位到具体的某个元素,而不是获取列表来进行遍历。
2.2 分类列表的定位
分类列表的获取我在实验时发现一个很神奇的现象,在程序中第一次获取的时候是一个长度为227的列表,经过一番操作之后列表长度居然变化了,变...化...了...,必须经历了一些操作才会变化,并且重新刷新也没有办法改正。不仅大小变化了,列表的顺序也有所不同。由于对网页了解程度不够,因此没有分析出到底原因在哪里。但是解决方法还是有的。第一获取的长为227的列表应该是全面的,因此抽取出所有目录的名称,存在一个列表里面。通过每一个列表的遍历来依次选中每一个分类。那要怎么根据字符串去定位这个元素呢?
如图,名称列表记录的是里面分类的简称,也就是里面name和value的值,通过cssselector就能够确定。具体代码为
driver.find_element_css_selector("input[value=\"%s\"]"%categoriesList[i])
对应例子中categoriesList[i]的值为CN。
可能通过这种方法还是有特定的分类就是定位不到,这个时候需要进行异常处理,将它写入一个error文件里面记录下来,等程序运行完之后再进一步处理。或者再程序末端加上相关处理的代码。虽然运行时的确会遇到这样的问题,但是刷新或者重新获取页面之后这种问题就解决了。异常处理可以大大增加爬虫程序的鲁棒性。关于异常处理部分感谢博主汪海的实验室的文章。
2.3 关于判定是否有数据
在网站中有的分类对应有的年份的数据是缺失的。由于对数据的获取是直接点击网站提供的下载按钮,因此需要在操作下载按钮之前确定是否存在数据,以免导致网站弹窗错误窗口。当没有数据时网站会显示响应的提示只要在一定时间内看是否出现该提示即可。对于这种情况需要使用WebDriverWait()等待一个较短时间即可。如果没有使用的话就会等待implicitly_wait()中的时间,导致爬虫效率降低。这个问题也可以通过弹窗处理来解决。笔者采用最简单的解决方法,但是时间效率上低了一些。

  • 关于源码:
  • # -*- coding: cp936 -*-
    from selenium import webdriver;
    from selenium.webdriver.common.by import By;
    from selenium.webdriver.support.ui import WebDriverWait
    #from selenium.webdriver.common.exceptions import TimeOutException
    from selenium.webdriver.support import expected_conditions as EC
    import time;
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8');
    ##对自动下载文件进行设置##
    
    fp=webdriver.FirefoxProfile();
    
    fp.set_preference("browser.download.folderList",2);#设置参数2为指定路径,设置Firefox的默认 下载 文件夹。0是桌面;1是“我的下载”;2是自定义。
    
    fp.set_preference("browser.download.dir","C:\\Users\\YonghaoFu\\Desktop\\data4");#设置数据存放的位置
    
    fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream, application/vnd.ms-excel, text/csv, application/zip"); 
    #设置可下载文件的类型
    fp.set_preference("browser.download.manager.showWhenStarting",False);
    
    
    driver = webdriver.Firefox(fp);
    
    driver.get("https://jcr.incites.thomsonreuters.com/");
    driver.implicitly_wait(3);
    ########
    def get_cate_ele(num):
        ele_cates=driver.find_elements_by_id("id");
        return ele_cates[num];
    #####
    
    ##获取年份的个数##
    WebDriverWait(driver,30).until(lambda driver: driver.find_element_by_id("ext-gen1097")).click();
    ele_years=driver.find_elements_by_css_selector("li[role=\"option\"]");
    times=3;
    while times>0 and len(ele_years) != 20:
        ele_years=driver.find_elements_by_css_selector("li[role=\"option\"]");
        times=times-1;
        time.sleep(3);
    if times==0:
        print "can't select the year!!";
    year_list=[];
    error_list=[];
    time.sleep(10);
    
    year_num=len(ele_years);
    
    for k in range(0,year_num):
        ele_years=driver.find_elements_by_css_selector("li[role=\"option\"]");
        year_list.append(ele_years[k].text);
    
    WebDriverWait(driver,30).until(lambda driver: driver.find_element_by_id("ext-gen1097")).click();
    #######获取分类的个数#####
    driver.find_element_by_css_selector("i[class=\"checkbox-categories icon icon-arrow-blue\"]").click();
    cates=driver.find_elements_by_id("id")
    cate_num=len(cates);
    cate_list=[];
    for each in cates:
        cate_list.append(each.find_element_by_tag_name("span").get_attribute("id"));
    print cate_list;
    #driver.find_element_by_css_selector("i[class=\"checkbox-categories icon icon-arrow-blue\"]").click();
    ####开始进行循环操作#####
    print cate_num,year_num
    flag=1;
    for i in range(0,cate_num):
        driver.find_element_by_css_selector("a[href=\"javascript:catClear()\"]").click();#下一次选择cate前进行清空操作
        try:
            WebDriverWait(driver,30).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[value=\"%s\"]"%cate_list[i]))).click();
        except:
            error_list.append(cate_list[i]);
            continue;
        for j in range(0,year_num):###进行循环操作
            driver.find_element_by_id("ext-gen1097").click();#打开年份列表
            ele_year=WebDriverWait(driver,20).until(lambda driver: driver.find_element_by_xpath("//ul[@class='x-list-plain']/li[%s]"%str(j+1)));
            print ele_year.text;
            WebDriverWait(driver,30).until(EC.visibility_of(ele_year)).click();#选中第几年
            driver.find_element_by_css_selector("a[href=\"javascript:catSubmit()\"]").click();#提交数据进行刷新
            if(len(driver.find_element_by_class_name("content-body").find_elements_by_class_name("x-grid-empty"))==0):
                driver.find_element_by_id("gridcolumn-1028-titleEl").click();#全选操作
                driver.find_element_by_css_selector("a[title=\"Download\"]").click();#点击下载按钮
                time.sleep(1);
                driver.find_elements_by_class_name("popup-action-content")[1].find_element_by_css_selector("li[οnclick=\"exportCSV()\"]").click();#开始下载数据
    f=open("C:\\Users\\YonghaoFu\\Desktop\\errorList",'w');
    for error in error_list:
        f.write(error+"\n");
    f.close();


你可能感兴趣的:(Python)