1. 程式人生 > >微信文章爬蟲demo -- 綜合實驗和練習

微信文章爬蟲demo -- 綜合實驗和練習

  這周最主要的是寫各種小爬蟲,像京東商城圖片抓取爬蟲、糗事大百科抓取爬蟲、微信文章爬蟲,這些是跟著韋瑋老師的書走的。不同的是,我比較喜歡按自己的思路做實現,然後再對比韋瑋老師書中的實現,找到自己的不足和差距。
  這周做下來,發現小爬蟲的框架差距不大,基本就是反爬繞過 –> 頁面資料抓取 –> 正則提取目標元素 –> 儲存資料,所以上面這幾個爬蟲的實現主要是正則和一小部分流程不同,大體一致。不過相信這也是我目前還沒真正入門進到真正爬蟲導致,相信後面學習的過程,將會接觸更多好玩的東西。
  這次分享的是我寫的一個微信文章爬蟲,具備了以下功能,我還會進一步迭代和優化,希望這個玩意做得好玩一些。也希望大家吐槽下這個實現,給些建議交流下,感謝。

  1. 自動抓取代理IP和更新
  2. Cookie自動儲存重灌載
  3. 部分簡單的容錯處理
  4. 通過搜狗引擎查詢並抓取微信文章

  下面的code可以看出有一些函式沒做實現,比如圖片儲存、頁面連結自動產生等。我這週末事情多,所以才沒整完。原計劃是實現url儲存成mhtml格式,這樣抓取到的文章和圖片能一起儲存下來,我爭取這周做出來,然後分享。
  上週的練習也讓我看到自身不少薄弱的地方,所以後續會想辦法加強起來,才能提高code質量和價值。

#!/usr/local/bin/python3
#-*- coding: utf-8 -*-
__author__ = 'donald.zhuang'
import urllib.request import http.cookiejar import random import re import os import socket # for collecting proxy address Url_ProxyAddr = 'http://www.xicidaili.com/nn' '''抓取代理ip地址的正則''' RegExp_ProxyAddr= '<tr class=.*?<td>(.*?)</td>\s+<td>(.*?)</td>.*?(HTTPS?)</td>' # for Article
UrlTemp = 'http://weixin.sogou.com/weixin?query=%s&type=2&page=%d' KeyWd_Page = 1 KeyWd_Query = 'Crawler' '''抓取微信文章連結和標題的正則''' RegExp_UrlTitle = '(?<=<a target="_blank" href=")(https?://[^\s\(\)<>"]*).*?>(.*?)</a>' # request header Headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36', } # cookie Cookie = None CookieFile = 'cookie.txt' # global Varibles setProxyAddr = [] def Get_ProxyAddr(): '''獲取代理IP地址,採用的是http://www.xicidaili.com/nn,不過質量略差''' global setProxyAddr try: req = urllib.request.Request(Url_ProxyAddr, None, Headers) except: print('[DBG ERR ] Get proxy address error.') return setProxyAddr data = urllib.request.urlopen(req).read().decode('utf-8') AllProxyAd = re.compile(RegExp_ProxyAddr, re.S).findall(data) for proxy in AllProxyAd: if proxy[2] == 'HTTP': setProxyAddr.append(proxy[0]+':'+proxy[1]) return setProxyAddr def Build_CookieAndProxy(ProxyAddr=None): '''cookie自動處理和代理IP地址設定''' global Cookie, CookieFile CookieProcessor = None ProxyHandler = None '''根據是否傳入檔名以及檔案是否存在決定載入方式''' if (CookieFile == None) or not(os.path.exists(CookieFile)): print("[DBG INFO] Make a New File to store the cookie") Cookie = http.cookiejar.MozillaCookieJar(CookieFile) else: '''若指定的檔案存在則直接載入''' print("[DBG INFO] Load %s to save cookie"%CookieFile) Cookie = http.cookiejar.MozillaCookieJar() Cookie.load(filename = CookieFile, ignore_discard = True, ignore_expires = True) CookieProcessor = urllib.request.HTTPCookieProcessor(Cookie) Cookie.save(CookieFile, ignore_discard = True, ignore_expires = True) '''設定代理ip,這個蟲子抓的是http協議的,所以配置如下''' print("[DBG INFO] Proxy address: %s" % ProxyAddr) if ProxyAddr != None: ProxyHandler = urllib.request.ProxyHandler({'http':ProxyAddr}) else: ProxyHandler = urllib.request.ProxyHandler({}) '''安裝全域性opener,這樣可以直接採用urllib相關實現,方便些''' Opener = urllib.request.build_opener(CookieProcessor,ProxyHandler) urllib.request.install_opener(Opener) def Change_Proxy(): '''改變代理IP地址''' proxyaddr = random.choice(setProxyAddr) Build_CookieAndProxy(proxyaddr) pass def Generate_PageUrl(): pass def Find_UrlAndTitleOnPage(PageUrl): '''抓取搜尋引擎頁面中的微信文章名和連結,也加入各種容錯檢測-->主要是方便了解情況,可以簡化掉''' global Cookie, CookieFile try: req = urllib.request.Request(PageUrl, None, Headers) content = urllib.request.urlopen(req, timeout = 30) # set Timeout as 10s except urllib.error.URLError as UrlErr: print('[DBG ERR ] URLError ', end = '') if hasattr(UrlErr, 'code'): print('Error Code: ', UrlErr.code) if hasattr(UrlErr, 'reason'): print('Error Reason: ', UrlErr.reason) return except socket.error as SocketErr: print('[DBG ERR ] Sokect Error: ', SocketErr) return except requests.exceptions.RequestException as ReqErr: print('[DBG ERR ] RequestException') return else: print('[DBG INFO] Get Title Url Here') data = content.read().decode('utf-8') Cookie.save(CookieFile, ignore_discard = True, ignore_expires = True) setUrl = re.compile(RegExp_UrlTitle,re.S).findall(data) return setUrl def Fix_UrlAndTitle(Url, Title): '''修正正則匹配到的連結和文章名''' UrlTitle = [] if (Url != None) and (Title != None): Url = Url.replace( 'amp;', '' ) Title = Title.replace( '<em><!--red_beg-->', '' ).replace( '<!--red_end--></em>', '' ) UrlTitle.append(Url) UrlTitle.append(Title) print('[DBG INFO] Title: %s\r\n Url:%s'%(Title, Url)) else: print('[DBG ERR ] Url or Title is None type') return UrlTitle def Save_Article(Url,Title): '''儲存連結指定的文章,文章名作為檔名 --> 對於有/這類符號的會出現bug,下面有提示''' global Cookie, CookieFile req = urllib.request.Request(Url, None, Headers) data = urllib.request.urlopen(req).read().decode('utf-8') Cookie.save(CookieFile, ignore_discard = True, ignore_expires = True) with open(Title+'.html', 'w') as hFile: # TODO: title name may cause some fault hFile.write(data) def Save_Photo(TitleUrl): pass def Main_Func(): '''主函式,主要是一個測試的demo''' Url = UrlTemp % (KeyWd_Query, KeyWd_Page) setText = Find_UrlAndTitleOnPage(Url) # Get the set of Text while setText is None: Change_Proxy() setText = Find_UrlAndTitleOnPage(Url) for i in setText: i = Fix_UrlAndTitle(i[0], i[1]) Save_Article(i[0], i[1]) if __name__ == '__main__': Get_ProxyAddr() Change_Proxy() # Build_CookieAndProxy() Main_Func()