爬取msdn.itellyou.cn网站

来源:互联网 发布:测试手机信号强度软件 编辑:程序博客网 时间:2024/05/22 13:51

最近一直在琢磨爬虫,从最早的BeautifulSoup爬取游民福利图,后来要爬取的动态网页多了,就逐渐过渡到了selenium+chromedriver/phantomJs的爬虫组合。偶然间听基友说有个msdn.itellyou.cn里收集了各种微软程序的ed2k安装包,因此便开始了对它的爬取之旅。

这个网站的页面结构还是挺复杂的。通过观察,发现软件的名称和地址都在右侧内容项中的label>checkbox中,名称为label的值,而地址为checkbox的data-url属性。且右侧的具体内容是通过div的动态加载来实现的,只有在点击了左侧的具体目录项才会出现;对于多语言的软件,每个子标签中的软件的xpath中的id又是不同的,因此需要动态获得每个子标签的id。最后,该网站会时不时地弹出呼吁捐赠的对话框,也会对爬虫造成影响。

由于采用selenium+chromedriver,且网站的各个资源项的id也摸不到规律,只能用最笨的方法——模拟点击法来获取所有软件的地址,即将目录项一个一个点开后再依次点击右侧的语言栏(若有的话);同时,在点击时还要处理随时可能弹出的捐款对话框。此外,有很多目录项里头其实没有数据,但也要花费一定时间点击。总的来说,这个爬虫效率是比较低的,若大家有更高效率的方法,欢迎提出。


源代码如下:

# -*- coding=utf-8 -*-from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitimport timefrom selenium.common.exceptions import NoSuchElementException,ElementNotVisibleException,WebDriverException,TimeoutExceptionimport xlwt#左侧目录的xpathcatalogue_list = ['//*[@id="accordion"]/div[1]/div[1]/h4/a',                  '//*[@id="accordion"]/div[2]/div[1]/h4/a',                  '//*[@id="accordion"]/div[3]/div[1]/h4/a',                  '//*[@id="accordion"]/div[4]/div[1]/h4/a',                  '//*[@id="accordion"]/div[5]/div[1]/h4/a',                  '//*[@id="accordion"]/div[6]/div[1]/h4/a',                  '//*[@id="accordion"]/div[7]/div[1]/h4/a',                  '//*[@id="accordion"]/div[8]/div[1]/h4/a'                  ]catalogue_name = [u'企业解决方案',                  u'MSDN技术资源库',                  u'工具和资源',                  u'应用程序',                  u'开发人员工具',                  u'操作系统',                  u'服务器',                  u'设计人员工具'                  ]count = 0software_name_list = []software_url_list = []def builddriver(kind):    chromedriver_path = 'D:\\WebDrivers\\chromedriver_win32\\chromedriver.exe'    phantomjs_path = 'D:\\WebDrivers\\phantomjs\\bin\\phantomjs.exe'    if kind == 'Chrome':        driver = webdriver.Chrome(executable_path=chromedriver_path)    elif kind == 'Phantomjs':        driver = webdriver.PhantomJS(executable_path=phantomjs_path)    return driver#关闭弹出的捐款对话框def clickdialog():    global driver    try:        dialog_close_button = driver.find_element_by_xpath('/html/body/div[2]/div/div/div[1]/button')        if dialog_close_button:            dialog_close_button.click()            time.sleep(3)    except NoSuchElementException:        pass    except ElementNotVisibleException:        pass#通过该函数调用所有的点击功能,防止对话框干扰def click_when_dialog(target_item):    try:        target_item.click()    except WebDriverException:        clickdialog()        target_item.click()    except NoSuchElementException, e:        raise e    except TimeoutException:        time.sleep(2)        target_item.click()    # 处理某灵异bug……    except WebDriverException:        time.sleep(2)        target_item.click()    finally:        time.sleep(4)def get_one_kind_software(kind_name_selector, type_name):    global software_name_list, software_url_list    software_file = open(type_name + '.txt', 'w')    kind_name = driver.find_element_by_xpath(kind_name_selector)    click_when_dialog(kind_name)    kind_id = kind_name.get_attribute('data-target')[1:]    software_item = driver.find_elements_by_xpath('//*[@id="' + kind_id + '"]/div/ul/li')  # 目录下的软件列表项    # 顺序点击每个目录项    for i in range(0, len(software_item)):        click_when_dialog(software_item[i])        # 获取右侧数据        # 多语言:        # 获取多语言列表        multi_languate_list = driver.find_elements_by_xpath('//*[@id="view_data_container"]/ul/li/a')        if multi_languate_list:            for j in range(0, len(multi_languate_list) - 1):                software_id = 'lang_' + multi_languate_list[j].get_attribute('data-id')                try:                    click_when_dialog(multi_languate_list[j])                except NoSuchElementException:                    continue                # 获取具体内容                try:                    software_name = driver.find_element_by_xpath('//*[@id="' + software_id + '"]/ul/li/div/label').text                    software_url = driver.find_element_by_xpath(                        '//*[@id="' + software_id + '"]/ul/li/div/label/input').get_attribute('data-url')                except NoSuchElementException:                    # 可能未加载完,但实际有                    time.sleep(4)                    try:                        software_name = driver.find_element_by_xpath(                            '//*[@id="' + software_id + '"]/ul/li/div/label').text                        software_url = driver.find_element_by_xpath(                            '//*[@id="' + software_id + '"]/ul/li/div/label/input').get_attribute('data-url')                    # 这个真没有……                    except NoSuchElementException:                        continue                software_name_list.append(software_name)                software_url_list.append(software_url)    for i in range(0, len(software_name_list)):        software_file.write(software_name_list[i] + '    ' + software_url_list[i] + '\n')    print type_name + '已爬取完成。\n'    # 清空已写入至文件的列表    software_name_list = []    software_url_list = []    software_file.close()def file_to_excel():    global count    workbook = xlwt.Workbook()    sheet_list = []    for sheet_name in catalogue_name:        sheet = workbook.add_sheet(unicode(sheet_name), cell_overwrite_ok=True)        sheet_list.append(sheet)    # 依次打开文件并写入对应的sheet    for i in range(0, len(catalogue_name)):        count = 0        software_file = open(unicode(catalogue_name[i]) + '.txt', 'r')        for line in software_file:            sheet_list[i].write(count, 0, unicode(line.split('    ')[0]))            sheet_list[i].write(count, 1, unicode(line.split('    ')[1]))            count += 1        software_file.close()    print u'软件存储完成'    workbook.save('software.xls')driver = builddriver('Chrome')if __name__ == "__main__":    global driver    driver.get('http://msdn.itellyou.cn/')    time.sleep(5)    for k in range(0, len(catalogue_list)):        get_one_kind_software(catalogue_list[k], catalogue_name[k])    driver.close()    file_to_excel()


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">此网站共分为8个目录,这段程序将每个目录的结果分别存为一个txt文件,最后再将其整理成一个excel文件。</span>

代码中的所谓“灵异bug”,是指在爬取操作系统那一目录时,经常到MS-DOS西班牙语之后会弹出异常:Other element would receive click:<nav class="balabala ……></nav>,且有时出现在这里,有时出现在爬取完Win7处,单步也抓不到。因此只能抛出一个WebdDriverException,处理方法是等2s后再试一次。

爬取后的成果:


个人感觉,用selenium+chromedriver/phantomjs爬取网页的效率实在是不高,但是碰到动态网页似乎又没有其他更好的办法。若有高人知道高效爬取动态网页的方法,还请不吝赐教。

0 0
原创粉丝点击