我的個人微博早前有大量跟好友的頁面聊天數據,隨著時間增多,發的微博近乎上萬條,可是微博本身沒有提供數據備份功能,查看了一下API文檔,從官方提供的接口取得的數據也只是有限條,無法滿足需要,因此萌發了寫個爬蟲用模擬登錄的方式將所有發過的微博抓取下來。
一 、先分析一下微博網頁版的結構和流程:
首先是登錄,需要用戶名、密碼、驗證碼,登錄成功后進入個人微博主頁,在主頁右邊有一個年份側邊欄,從這里可以按時間查看所有發過的微博,這就是我主要的抓取對象了,再進一步查看頁面結構可知,微博按年月進行數據讀取,每一個月的微博有可能為0,也有可能有好幾頁,每一頁需要將頁面滾動到底部幾次才會完全加載出來。
二、然后準備好工具:
Python 3.6
selenium 3.3.3
火狐瀏覽器驅動 geckodriver-v0.15.0-win64
三、難點與重點:
1、模擬登錄過程
新浪微博的網頁版登錄過程比起別的有一點小曲折,它需要先輸入用戶名驗證后才會顯示驗證碼,不過既然是用selenium模擬,這些都不是問題。
verifyimg = browser.find_element_by_css_selector("img[node-type='verifycode_image']") //驗證碼圖片
num = 0
while verifyimg.get_attribute('src') == "about:blank":
num = num + 1
if num == 5:
logger.info("驗證碼無法加載,請重試!")
browser.quit()
return
userInput.click() //模擬點擊用戶輸入框以觸發驗證碼顯示
time.sleep(8)
pwInput.click()
time.sleep(5)
模擬登錄的重點是對驗證碼圖片進行截圖保存,用于后續人工識別輸入,這一行代碼我花了半天進行文檔查詢和編寫調試,目前是在火狐瀏覽器上調試成功,但是后面我將驅動換成phantomjs,截取下來的卻是整個頁面。
verifyimg.screenshot("verifycode.png")
2、用腳本將頁面拉到底部讀取數據
從selenium官方文檔上查到的方法,版本是3.3.3。
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
3、判斷某個年月的微博是否有下一頁
由于為了方便抓取,設置了多個參數,于是為了判斷下一頁,各種語句調試了一天,才整出下面這段代碼:
//pages:要下載的頁面數;page:當前第幾頁;pagecount:總頁面數
if (not pages) or (not isinstance(pages[0], int)) or (pages[0] > pagecount) or (pages[0] >= pagecount - page) or (pages[0] <= 0): #不傳翻頁數或者翻頁數參數錯誤
if page < pagecount:
page = page + 1
getWeiboHtml(datenum, url, count, page)
elif page == pagecount:
logger.info("保存完畢!")
return
elif (pages[0] > 0) and (pages[0] < pagecount - page):
if pages[0] == 1:
logger.info("保存完畢!")
return
else:
page = page + 1
flip = pages[0]-1
getWeiboHtml(datenum, url, count, page, flip)
else:
return
4、獲取到第一條微博和最新一條微博的日期
第一條微博日期是通過點擊微博主頁的時間線,獲取網址中的stat_date字段數據。
最新一條微博日期直接就從登錄后的微博主頁內容字段中解析。
5、日志系統
這次這個爬蟲項目,不光學到了selenium的使用,還學到了Python自帶的日志系統的使用,受益匪淺。
下面的函數使日志系統從文件里讀取配置。
def setup_logging(
default_path='logconfig.json',
default_level=logging.INFO,
env_key='LOG_CFG'):
path = default_path
value = os.getenv(env_key, None)
if value:
path = value
if os.path.exists(path):
with open(path, 'r') as f:
config = json.load(f)
logging.config.dictConfig(config)
else:
logging.basicConfig(level=default_level)
然后在程序中引入日志進行記錄:
import logging.config
logger = logging.getLogger(__name__)
6、selenium的安裝
裝selenium的時候并不順利,一開始是想用chrome瀏覽器的,但是下載了chrome的驅動后無法使用,折騰了好久最后改用了火狐。
四、進階
目前微博是以html文件的形式保存下來了,但是還需要繼續編寫解析器從html里面提取出結構化的數據,還有區別原創與轉發,對表情和圖片進行下載等,待以后有時間需要一一進行解決。
目前寫的爬蟲僅能在自己的機子上以命令行的形式運行,想要給朋友使用都不行,因此還要繼續學習Python的打包與界面化。