使用selenium實現簡單網絡爬蟲抓取MM圖片


  擼主聽說有個網站叫他趣,里面有個社區,其中有一項叫他趣girl,擼主點進去看了下,還真不錯啊,圖文並茂,宅男們自己去看看就知道啦~

  接下來當然就是爬取這些妹子的圖片啦,不僅僅是圖片,擼主發現里面的對話也很有意思,於是把對話也一並抓取下來好了。

  那么問題來了,用什么工具呢?在之前的練習中已經用過urllib2,正則表達式匹配實在麻煩,這次來點稍微高級的,試試selenium;

  selenium是什么?其實它是一個web自動化測試的工具,運行起來就跟我們自己操作瀏覽器差不多,廢話不多說,下面開始。

  工具:python2.7 + selenium2 python版

  1 首先導入需要的模塊,然后定義本地存放目錄

 1 # coding: utf-8
 2 
 3 from selenium import webdriver
 4 from selenium.common.exceptions import NoSuchElementException
 5 from time import *
 6 import os
 7 import urllib2
 8 
 9 # 文件保存路徑
10 file_path = r'F:\taqu'

  2 然后還是定義3個函數,分別用來為每個girl創建目錄,保存每個girl的圖片,保存每個girl的文本描述和對話;其中在保存圖片的時候還是用到了urllib2

# ------------定義3個函數,用來創建每個girl的目錄、保存圖片、寫入文本描述及對話----------------
def mkdir_for_girl(path, name):
    """
    創建以標題命令的目錄
    :param name: 目錄名稱
    :return: 返回創建的目錄路徑
    """
    path = os.path.join(path, name)
    if not os.path.exists(path):
        os.mkdir(path)
    return path


def save_pictures(path, url_list):
    """
    保存圖片到本地指定文件夾
    :param path: 保存圖片的文件夾,由mkdir_for_girl返回
    :param url_list: 待保存圖片的url列表
    :return: none
    """
    for (index, url) in enumerate(url_list):
        try:
            print u'%s 正在保存第%d張圖片' % (ctime(), index)
            pic_name = str(index) + '.jpg'
            file_name = os.path.join(path, pic_name)
            # 如果存在該圖片則不保存
            if os.path.exists(file_name):
                print u'%s 該圖片已經存在' % ctime()
                continue
            req = urllib2.Request(url, headers={'User-Agent':  r'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0'})
            data = urllib2.urlopen(req, timeout=30).read()
            f = open(file_name, 'wb')
            f.write(data)
            f.close()
        except Exception, e:
            print u'%s 第%d張圖片保存失敗,不處理,跳過繼續處理下一張' % (ctime(), index)


def write_text(path, info):
    """
    在path目錄中創建txt文件,將info信息(girl的文本描述和對話)寫入txt文件中
    :param path: 保存txt文件的目錄,由mkdir_for_girl返回
    :param info: 要寫入txt的文本內容
    :return: none
    """
    # 創建/打開info.txt文件,並寫入內容
    filename = os.path.join(path, 'info.txt')

    with open(filename, 'a+') as fp:
        fp.write(info.encode('utf-8'))
        fp.write('\n'.encode('utf-8'))
        fp.write('\n'.encode('utf-8'))

  3 定義webdirver,打開目標網頁,其中切換到目標頁面使用了超鏈接文本定位元素

# -----------------------打開頁面,設置超時時間,窗口最大化-----------------------
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.maximize_window()
driver.get(r'http://www.taqu.cn/community/')

# -----------------------切換到“他趣Girl”頁面-----------------------
driver.find_element_by_partial_link_text(u'他趣Girl').click()

  4 由於所有girl都在一個頁面中,但是這個頁面很長很長,真的很長,需要滑動很久才能滑到底部,為什么要滑動到底部呢?

因為瀏覽器獲取的HTML源碼,只有當前窗口已顯示元素的代碼,未顯示部分的代碼沒有,當然selenium也定位不到那些元素了;

所以說,如果要selenium能找到所有girl,先要把頁面滑動到底部,等所有girl都加載完,才能獲取到包含所有girl的HTML代碼。

  那么問題來了,怎么滑動頁面呢,通過瀏覽器的滾動條,但是滾動條不是HTML元素,selenium不能直接控制,這里就得借助

javascript了,在selenium中執行js代碼還是可以的,具體實現看代碼:

# -----------------------滑動到窗口最底部,以將所有的girl都刷新出來-----------------------
# 由於頁面很長,並且需要不斷下拉才會刷新,因此通過javascript來控制器滾動條向下滑動
# 但是一次滑動並不能到達底部,需要多次,那么需要多少次呢?這里采用的方式是不停的向下
# 滑動,每滑動一次,都查詢下是否到達底部,怎么查詢呢?這是通過查到底部的一個標志圖片來判斷,
# 如果沒找到標志,就說明還沒到達底部,需要繼續滑動,如果找到就跳出循環
# 為了快速滑動,先設置超時時間為1秒
driver.implicitly_wait(1)
# 不停的滑啊滑 while True: driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") try: # 定位頁面底部的一個圖片 driver.find_element_by_xpath(".//*[@id='waterfall-loading']/img[@src='/img/no-more.png']") # 如果沒拋出異常就說明找到了底部標志,跳出循環 break except NoSuchElementException as e: # 拋出異常說明沒找到底部標志,繼續向下滑動 pass # 將超時時間改回10秒 driver.implicitly_wait(10)

  5 獲取到整個完整的頁面后,就可以一次找出所有的girl封面圖片了,這些封面圖片是可以點擊的,一點就打開了該girl的所有圖片和對話,

  這里使用的是CSS選擇器,比起xpath,擼主更喜歡CSS一些

# -----------------------找到所有girl的封面圖片-----------------------
# 這些封面圖片是可點擊的,單擊都會彈出該girl的所有圖片和文字描述
girls = driver.find_elements_by_css_selector("div#container img")
num = len(girls)
print u"girl總數為:%d" % num

  6 最后一步了,遍歷所有的封面圖片,依次點擊,然后抓取保存每一個girl的圖片和對話,保存到本地

# -----------------------依次點擊每張封面,提取每個girl的信息-----------------------
for girl in girls:
    # 依次點擊每一個girl的封面
    girl.click()

    # 每點擊一個girl后,都再點擊一下彈出框,以更新driver,不然driver中的緩存還是上一個girl的
    # 一定要注意這一步啊,擼主當時沒有做這一步,折騰了好久
    driver.find_element_by_xpath("html/body/div[3]/div[2]").click()

    # 提取標題,由於標題中的字符:和|不能作為文件名,將他們替換了
    title = driver.find_element_by_css_selector("p.waterfall-detail-header-title").text
    title = title.encode('utf-8')
    title = title.replace(":", "")
    title = title.replace("|", "")
    title = title.decode('utf-8')

    # 在file_path目錄下,為該girl創建以標題命名的目錄
    path = mkdir_for_girl(file_path, title)

    # 提取該girl所有圖片的URL
    pics = driver.find_elements_by_css_selector("div.water-detail-content img")
    pic_url = [x.get_attribute('src') for x in pics]
    print u'該girl的圖片總數為:%d' % len(pic_url)

    # 保存圖片到本地以該girl標題命名的目錄中
    save_pictures(path, pic_url)

    # 提取girl的基本介紹,並寫入info.txt文件
    info = driver.find_element_by_xpath("html/body/div[3]/div[2]/div[2]/div[2]").text
    write_text(path, info)

    # 提取所有對話,寫入info.txt文件
    talks = driver.find_elements_by_css_selector("div.water-detail-content p")
    for t in talks:
        write_text(path, t.text)

    # 關閉該girl的圖片
    driver.find_element_by_xpath("html/body/div[3]/div[2]/div[1]/div/img").click()
    print u'該girl信息提取完成,繼續處理下一個'
    sleep(1)

# -----------------------所有girl信息提取完成-----------------------
driver.close()
print u'恭喜,所有girl信息提取完成!'

  7 試着運行下,看下輸出,是不是有點小激動

girl總數為:90
該girl的圖片總數為:12
Sat May 14 09:24:54 2016 正在保存第0張圖片
Sat May 14 09:24:54 2016 正在保存第1張圖片
Sat May 14 09:24:54 2016 正在保存第2張圖片
。
。省略很多
。
Sat May 14 09:33:36 2016 正在保存第9張圖片
Sat May 14 09:33:37 2016 正在保存第10張圖片
Sat May 14 09:33:37 2016 正在保存第11張圖片
該girl信息提取完成,繼續處理下一個
恭喜,所有girl信息提取完成!

  8 再看下本地目錄,是不是很激動?

 

  說明:上面的代碼是完整的,將所有的分段合並在一起就可以運行了。這里可以看到,selenium是很強大的,不僅僅是web自動化工具哦,

還是爬蟲利器呢;但是,但是這里有個缺點就是,selenium會打開瀏覽器UI,這樣操作起來就有點偏慢了,有沒有更好的解決方案呢?---有的!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM