Python爬蟲Csdn系列II
來源:程序員人生 發(fā)布時間:2015-04-30 08:20:23 閱讀次數(shù):3107次
Python爬蟲Csdn系列II
By 白熊花田(http://blog.csdn.net/whiterbear) 轉(zhuǎn)載需注明出處,謝謝。
說明:
在上1篇文章中,我們已知道了只要將程序假裝成閱讀器就可以訪問csdn網(wǎng)頁。在這篇文章中,我們將想法獲得某個csdn用戶的所有文章的鏈接。
分析:
打開1個某1個的csdn用戶的的專欄,可以選擇目錄視圖(如:http://blog.csdn.net/whiterbear?viewmode=contents)和摘要視圖(比如:http://blog.csdn.net/whiterbear?viewmode=list)。兩個視圖都可以顯示用戶的文章列表。
注意:這里我們選擇摘要視圖,不要選擇目錄視圖,文章最后會解釋為何。
打開摘要視圖查看網(wǎng)頁源代碼,我們發(fā)現(xiàn),在id為’article_list’的div中,每個子div都代表著1篇文章,如圖:

每個子div中都包括1篇文章的標題,鏈接,瀏覽次數(shù),是不是為原創(chuàng),評論數(shù)等信息,我們只需要取出標題和鏈接就夠了。如何取出不難,學(xué)過正則表達式應(yīng)當都會。我們再使用個數(shù)組將界面中所有的文章名及其鏈接保存便可。
這里需要注意的是,如果博客有分頁怎樣辦,我們還需要獲得分頁的下1頁中的文章的鏈接?
我嘗試了兩種方法,第1種方法是設(shè)定1個article_list字典,字典成員為‘下1頁鏈接和是不是已被訪問標識鍵值對’,初始放入首頁鏈接,每處理1個界面時將該鏈接的值設(shè)為訪問,以后查找下1頁的鏈接,如果其不在字典里,就將其加入并設(shè)訪問標識為0。
比如初始字典為article_list={‘/pongba/article/list/1’:False},在處理/pongba/article/list/1這個界面時設(shè)值為True,此時又發(fā)現(xiàn)了/pongba/article/list/2和/pongba/article/list/3。此時,我們判斷字典(has_key())中是沒有這兩個鍵的,就加入,并設(shè)其值為False。以后遍歷(keys())字典,如果有值為0的鏈接,則訪問該鏈接,重復(fù)。
第2種方法:在分頁的html代碼中給出了分頁的頁數(shù),我們提取出頁數(shù)pagenum,結(jié)合/pongba/article/list/num,num為頁數(shù),值為[1,pagenum]。通過這個鏈接便可取出該作者的所有文章了。

我代碼中采取了第2種方法,第1種方法試了,也能夠。
代碼介紹:
CsdnArticle類(article.py),封裝成1篇文章必須的東西,便于保存和訪問1個文章的屬性。
我重寫了__str__()方法,便于輸入。
#-*- coding:utf⑻ -*-
class CsdnArticle(object):
def __init__(self):
#作者
self.author = ''
#博客文章名
self.title = ''
#博客鏈接
self.href = ''
#博客內(nèi)容
self.body = ''
#字符串化
def __str__(self):
return self.author + ' ' + self.title + ' ' + self.href + ' ' + self.body
CsdnCrawler類。封裝了爬取csdn博客所有鏈接的操作。
#-*- coding:utf⑻ -*-
import sys
import urllib
import urllib2
import re
from bs4 import BeautifulSoup
from article import CsdnArticle
reload(sys)
sys.setdefaultencoding('utf⑻')
class CsdnCrawler(object):
#默許訪問我的博客
def __init__(self, author = 'whiterbear'):
self.author = author
self.domain = 'http://blog.csdn.net/'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'}
#存儲文章對象數(shù)組
self.articles = []
#給定url,得到所有的文章lists
def getArticleLists(self, url= None):
req = urllib2.Request(url, headers=self.headers)
response = urllib2.urlopen(req)
soup = BeautifulSoup(''.join(response.read()))
listitem = soup.find(id='article_list').find_all(attrs={'class':r'list_item article_item'})
#鏈接的
正則表達式,可以匹配鏈接
href_regex = r'href="(.*?)"'
for i,item in enumerate(listitem):
enitem = item.find(attrs={'class':'link_title'}).contents[0].contents[0]
href = re.search(href_regex,str(item.find(attrs={'class':'link_title'}).contents[0])).group(1)
#我們將獲得的1篇文章信息封裝成1個對象,然后存入數(shù)組中
art = CsdnArticle()
art.author = self.author
art.title = enitem.lstrip()
art.href = (self.domain + href[1:]).lstrip()
self.articles.append(art)
def getPageLists(self, url= None):
url = 'http://blog.csdn.net/%s?viewmode=list'%self.author
req = urllib2.Request(url, headers=self.headers)
response = urllib2.urlopen(req)
soup = BeautifulSoup(''.join(response.read()))
num_regex = '[1⑼]d*'
pagelist = soup.find(id='papelist')
self.getArticleLists(url)
#如果該作者博客多,有分頁的話
if pagelist:
pagenum = int(re.findall(num_regex, pagelist.contents[1].contents[0])[1])
for i in range(2, pagenum + 1):
self.getArticleLists(self.domain + self.author + '/article/list/%s'%i)
def mytest(self):
for i,url in enumerate(self.articles):
print i,url
def main():
#可以將pongba換成你的博客名,也能夠不填,為空,這樣默許是訪問我的博客
csdn = CsdnCrawler(author='pongba')#'pongba'
csdn.getPageLists()
csdn.mytest()
if __name__ == '__main__':
main()<span style="font-family:Verdana;font-size:18px;">
</span>
結(jié)果:

輸出了126條數(shù)據(jù)。
選擇摘要視圖的解釋:當某用戶文章多有分頁時,訪問目錄視圖界面中的下1頁鏈接時會跳轉(zhuǎn)到摘要視圖的下1頁鏈接中。我這么說你可能不太明白,舉個例子吧。
我使用劉未鵬學(xué)長(我崇拜的)的博客為例子吧,地址:http://blog.csdn.net/pongba。他的文章很多,有分頁。選擇他界面中的目錄視圖后,翻到分頁鏈接出。以下圖:

其中的分頁鏈接值為:

可以看出下1頁的鏈接為:http://blog.csdn.net +/pongba/article/list/2.
當我們在閱讀器輸入這個網(wǎng)址回車后是出現(xiàn)這個結(jié)果的:

可以看到第1篇文章為“斯托克代爾悖論與底線思考法”
但是,當我們使用程序打開的結(jié)果卻是:

而這個結(jié)果卻和摘要視圖的第2頁結(jié)果1樣:

所以,如果你試圖用程序使用http://blog.csdn.net/pongba/article/list/2這個鏈接訪問,得到的結(jié)果卻其實不是目錄視圖的結(jié)果。我沒能理解為何,糾結(jié)了好久程序為何出錯了,后來換成摘要視圖了。
未完待續(xù)。
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進行捐贈