網路爬蟲——用Python爬取新浪新聞材料
來自專欄小人物數據分析師
微信公眾號:數據分析與統計學習
如有問題或建議,請公眾號留言最近更新時間:2018-7-8
最近一個星期都在學習網路爬蟲,秉著有學習輸入就要有學習輸出(學以致用)的原則,把整個學習過程記錄下來,並分享給大家。
一、 爬蟲前的準備工作
我是在Windows系統下用Python的Anaconda集成開發環境實現網路爬取新浪新聞項目。用Anaconda實現網路爬蟲有如下幾個好處:第一,該軟體是免費的;第二,該集成開發環境已經具備網路爬蟲所需的庫,不需要我們安裝第三方庫。
下載谷歌瀏覽器的一個第三方插件SelectorGadget,主要是用來輔助定位網頁元素的位置以及查找出各網頁元素的共同規律。具體用法可以上網搜索。二、 網路爬蟲流程說明
一個輕量級的網路爬蟲項目,應該具備如下兩個步驟。第一,獲取網頁上的目標鏈接(URL);第二,目標網頁解析,從網頁中提取我們所需要的數據。
三、 網路爬蟲代碼實現
在敲擊鍵盤編寫代碼實現爬蟲項目的過程中,主要用到Python中三個第三方庫——requests 、BeautifulSoup和json以及用於存儲數據的pandas庫。
requests庫主要用途獲取目標網頁的內容,爬蟲過程中主要用到它的get方法,接受參數URL,就返回一個包含目標內容的Response對象。詳細用法請參考requests庫的中文文檔。鏈接如下:
http://docs.python-requests.org/zh_CN/latest/user/quickstart.htmlBeautifulSoup庫主要用途是解析目標網頁內容,接受一個網頁內容的參數,返回一個BeautifulSoup對象。主要用到該庫的find_all,find,select等方法。詳細用法請參考BeautifulSoup庫的中文文檔。鏈接如下:
https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/json庫主要用來從網頁中提取json格式的數據。json格式數據轉換後,變成Python的字典。
1、今天我要爬取的網頁是新浪新聞國內新聞的最新消息一欄,先打開新浪新聞國內新聞網頁,如下圖所示:
2、然後在網頁空白地方點擊右鍵,選擇「檢查」,然後選擇『element』選項卡,利用谷歌瀏覽器插件SelectorGadget,點擊各新聞標題,尋找各新聞標題元素的位置。找到各新聞標題元素的位置後,尋找共同規律。我發現這些新聞標題的位置均在屬性class=「newsitem」,並且這些新聞標題的鏈接都存儲在標籤<a>中href屬性。具體代碼如下:
import requestsfrom bs4 import BeautifulSoupdef urls_download(url): #定義下載這些新聞標題鏈接的函數 r = requests.get(url) #傳入參數,獲取參數所代表的網頁 r.encoding = utf-8 #顯性設定編碼為utf-8 bsobj = BeautifulSoup(r.text,lxml) #接收目標網頁內容,解析網頁 alinks = bsobj.select(.news-item) #返還含有新聞標題元素的列表 newsurls = [] #收集新聞標題的鏈接 for alink in alinks: hrefs = alink.select(a) if hrefs: #排除新聞標題鏈接為空的情況 newsurls.append(hrefs[0][href])return newsurls #返回目標網頁鏈接列表
3、獲取目標網頁鏈接列表後,對每個鏈接的網頁進行解析,從中提取目標新聞網頁的的數據,包括標題、時間、來源、編輯者、文章內容,評論數、關鍵詞。具體實現代碼如下;
import jsonimport requestsfrom bs4 import BeautifulSoupdef getNewsDetails(url): r = requests.get(url) r.encoding = utf-8 bsobj = BeautifulSoup(r.text,lxml) result = {} #收集目標網頁的數據 result[main_title] = bsobj.select(.main-title)[0].text result[date] = bsobj.select(.date)[0].text try: #異常處理,處理標籤<a>中href屬性不存在的情況 result[source] = bsobj.select(.source)[0].text result[source_link] = bsobj.select(.source)[0][href] except KeyError: print("has no key") result[show_author] = bsobj.select(.show_author)[0].text.lstrip(責任編輯:) result[keywords] = bsobj.select(.keywords)[0][data-wbkey][:-3] texts = [] #收集新聞的具體內容 for i in range(len(bsobj.select(p))-5): texts.append(bsobj.select(p)[i].text.replace(uu3000,u)) #去除每段的首行兩個空白字元 result[article] = texts news_id = url.split(/)[-1].rstrip(.shtml).lstrip(doc-i) commenturl = http://comment5.news.sina.com.cn/page/info?version=1&format=json&channel=gn&newsid=comos-{}&group=undefined&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=3&t_size=3&h_size=3&thread=1 comments = requests.get(commenturl.format(news_id)) #評論數是json格式的數據 comment = comments.text jd = json.loads(comment) #轉換json格式的數據 result[comment_num] = jd[result][count][total] return result #返回所需的數據
上面只是一個網頁的,因為一個新聞網頁肯定有許多頁,需要翻頁看,如果想獲取不同分頁下的網頁鏈接,就要重新編寫代碼,具體代碼:
def parseListLinks(url): #定義獲取不同分頁下的新聞標題鏈接函數 newsDetail= [] r = requests.get(url) jsondata = r.text.strip().lstrip(newsloadercallback().rstrip();) jd = json.loads(jsondata) for i in range(len(jd[result][data])): newsDetail.append(getNewsDetails(jd[result][data][i][url])) #調用前面獲取新聞數據的函數,獲取每個分頁下所有新聞的數據 return newsDetail 返回所有分頁下的新聞數據#不同分頁的URL鏈接url = http://api.roll.news.sina.com.cn/zt_list? channel=news&cat_1=gnxw&cat_2==gdxw1||=gatxw||=zs-pl||=mtjj&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page={}&callback=newsloadercallback&_=1531402221318 news_total = [] #手機所有新聞數據的列表for i in range(1,5): news_list = parseListLinks(url.format(i)) news_total.extend(news_list) #把爬取的數據下載下來,把數據存儲到csvimport pandas as pddf = pd.DataFrame(news_total) #列錶轉換為數據框df.to_csv(news.csv) #存儲到名為news格式為csv的表中
四、後記
這只是一個簡單的網路爬蟲,後面還有更多的內容需要學習,我也會把自己學到的最新的網路爬蟲知識分享給大家。希望大家繼續保持關注,也希望大家積極留言指出我的錯誤,教學相長。
下面的是我的公眾號二維碼圖片,歡迎關注我。
http://weixin.qq.com/r/uji0rG-EOzJErSvP922o (二維碼自動識別)
推薦閱讀:
※爬取《The Hitchhiker』s Guide to Python!》python進階書並製成pdf
※python爬取網頁圖片
※python爬取搜狗熱搜榜