一個Python小白的5個小時爬蟲經歷

ADVERTISEMENT

復旦大資料

ID:FuDanBigData

前言

最近業餘在做一個基於.NETCore的搜尋項目,奈何基層程式碼寫好了,沒有看起來很華麗的資料供測試。很巧的也是部落格搜尋,於是乎想到了部落格園。C# 也能做做頁面資料抓取的,不過在部落格園看到的大部分都是python實現,所以就臨時想了一下看看python到底是什麼東東。

不看基礎語法,不看語言功能,直接上程式碼,哪裡不會搜哪裡。程式碼完成總共用時大概4個小時,其中搭建環境加安裝BeautifulSoup大概1個小時。解析HTML用時間最多了,邊看demo邊解析,大概2個小時,剩下的時間就是偵錯加儲存資料了。

環境搭建

既然用python,那麼自然少不了語言環境。於是乎到官網下載了3.5版本的。安裝完之後,隨機選擇了一個編輯器叫PyCharm,話說python編輯器還真挺多的。由於本人是小白,所以安裝事項不在過多贅述。

建好項目,開啟編輯器,直接開工。本來之前用C#寫的時候,大體思路就是獲取網頁內容,然後正則匹配。後來發現網上的帖子也很多。不過在搜尋過程中發現,不建議用正則來匹配HTML。有正好我的正則不太好,所以我就搜了一下HTML解析工具,果不其然,人家都做好了,直接拿來用吧。沒錯就是這個東東:BeautifulSoup。

安裝也很簡單,不過中間出了個小插曲,就是bs4沒有。繼續搜,然後需要用pip安裝一下就好了。(當然我並不知道bs4和pip是什麼鬼)

思路分析

部落格嗎,我當然就對準了部落格園,於是乎,進入部落格園首頁,檢視請求。

傳送請求

當然我不知道python是怎麼進行網路請求的,其中還有什麼2.0和3.0的不同,中間曲曲折折了不少,最終還是寫出了最簡單的一段請求程式碼。

importurllib.parse

importurllib.request

# params CategoryId=808 CategoryType=SiteHome ItemListActionName=PostList PageIndex=3 ParentCategoryId=0 TotalPostCount=4000

defgetHtml(url,values):

user_agent='Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'

headers =

data = urllib.parse.urlencode(values)

response_result = urllib.request.urlopen(url+'?'+data).read

html = response_result.decode('utf-8')

returnhtml

#獲取資料

defrequestCnblogs(index):

print('請求資料')

url ='http://www.cnblogs.com/mvc/AggSite/PostList.aspx'

value= {

'CategoryId':808

'CategoryType':'SiteHome'

'ItemListActionName':'PostList'

'PageIndex': index,

'ParentCategoryId'

:0

ADVERTISEMENT

'TotalPostCount':4000

}

result = getHtml(url,value)

returnresult

其實部落格園這個請求還是挺標準的,哈哈正好適合抓取。因為他返回的就是一段html。(如果返回json那不是更好。。。。)

資料解析

上文已經提到了,用到的是BeautifulSoup,好處就是不用自己寫正則,隻要根據他的語法來寫就好了,在多次的測試之後終於完成了資料的解析。

先上一段HTML。然後在對應下面的程式碼,也許看起來更輕鬆一些。

class="post_item"

class="digg"

class="diggit"onclick="DiggPost('hyper-xl'64177412812381)"

class="diggnum"id="digg_count_6417741"1

class="clear">

id="digg_tip_6417741"class="digg_tip">

class="post_item_body"

class="titlelnk"href="http://www.cnblogs.com/hyper-xl/p/6417741.html"target="_blank"Python 字元串格式化

class="post_item_summary"

href="http://www.cnblogs.com/hyper-xl/"target="_blank"

width="48"height="48"class="pfs"

src="//pic.cnblogs.com/face/795666/20160421231717.png"alt=""/>

轉載請註明出處 Python2.6+ 增加了str.format函數,用來代替原有的'%'操作符

。它使用比'%'更加直觀、靈活。下面詳細介紹一下它的使用方法。 下面是使用'%'的例子: 格式很像C語言的printf是不是?由於'%'是一個操作符,隻能在左右

兩邊各放一個參數,因此右邊多個值需要用元組或 ...

class="post_item_foot"

href=class="lightblue"新月的力量_141

釋出於 2017-02-19 23:07

class="article_comment"

href="http://www.cnblogs.com/hyper-xl/p/6417741.html#commentform"title=""class="gray"

評論(0)

class="article_view"

href=class="gray"

閱讀

(138)

class="clear">

通過上文的HTML程式碼可以看到幾點。首先每一條資料都在 div(class="post_item")下。然後 div("post_item_body")下有使用者資訊,標題,連結,簡介等資訊。逐一根據樣式解析即可。

程式碼如下:

ADVERTISEMENT

frombs4importBeautifulSoup

importrequest

importre

#解析最外層

defblogParser(index):

cnblogs = request.requestCnblogs(index)

soup =BeautifulSoup(cnblogs,'html.parser')

all_div = soup.find_all('div', attrs=, limit=20)

blogs =

#迴圈div獲取詳細資訊

foriteminall_div:

blog = analyzeBlog(item)

blogs.append(blog)

returnblogs

#解析每一條資料

defanalyzeBlog(item):

result = {}

a_title = find_all(item,'a''titlelnk')

ifa_titleisnotNone:

# 部落格標題

result["title"] = a_title[0].string

# 部落格連結

result["href"] = a_title[0]['href']

p_summary = find_all(item,'p''post_item_summary')

ifp_summaryisnotNone:

# 簡介

result["summary"] = p_summary[0].text

footers = find_all(item,'div''post_item_foot')

footer = footers[0]

# 作者

result["author"] = footer.a.string

# 作者url

result["author_url"] = footer.a['href']

str = footer.text

time = re.findall(r"釋出於 .+? .+? ", str)

result["create_time"] = time[0].replace('釋出於 ''')

ADVERTISEMENT

comment_str = find_all(footer,'span''article_comment')[0].a.string

result["comment_num"] = re.search(r'\d+', comment_str).group

view_str = find_all(footer,'span''article_view')[0].a.string

result["view_num"] = re.search(r'\d+', view_str).group

returnresult

deffind_all(item,attr,c):

returnitem.find_all(attr,attrs=,limit=1)

上邊一堆程式碼下來,著實花費了我不少時間,邊寫邊偵錯,邊百度~~不過還好最終還是出來了。等資料都整理好之後,然後我把它儲存到了txt檔案裡面,以供其他語言來處理。本來想寫個put直接put到ElasticSearch中,奈何沒成功。後邊在試吧,畢竟我的重點隻是導資料,不在抓取這裡。

importmatch

importos

importdatetime

importjson

defwriteToTxt(list_name,file_path):

try:

#這裡直接write item 即可,不要自己給序列化在寫入,會導致json格式不正確的問題

fp = open(file_path,"w+",encoding='utf-8')

l = len(list_name)

i =0

fp.write('[')

foriteminlist_name:

fp.write(item)

ifi1:

fp.write(',\n')

i +=1

fp.write(']')

fp.close

exceptIOError:

print("fail to open file")

#def getStr(item):

# return json.dumps(item).replace('\'','\"')+',\n'

defsaveBlogs:

foriinrange(12):

print('request for '+str(i)+'...')

blogs = match.blogParser(i,5)

#儲存到檔案

path = createFile

writeToTxt(blogs,path+'/blog_'+ str(i) +'.json')

print('第'+ str(i) +'頁已經完成')

return'success'

defcreateFile:

date = datetime.datetime.now.strftime('%Y-%m-%d')

path ='/'+date

ifos.path.exists(path):

returnpath

else:

os.mkdir(path)

returnpath

result = saveBlogs

print(result)

上邊呢,我取了一百頁的資料,也就是大概2000條做測試。

成果驗收

廢了好大勁終於寫完那些程式碼之後呢,就可以享受勝利的果實了,雖然是初學者,程式碼寫的很渣,這參考一下,那參考一下,不過還是有些收穫的。執行效果如下:

生成的檔案:

檔案內容:

總結

一個簡單的抓取程式就寫完了,python還真是TM的好用。以後有空再研究研究吧。程式碼行數算上空行和註釋總共100 (50+25+25)行。湊個整數好看點~~現在認識字我感覺就可以上手寫程式了。這裡百度一下,那裡google一下,問題就解決了,程式也出來了,大功告成。

是時候該和python暫時告別了,繼續我的。NET事業。話說上次做rss採集的時候,好多".NET要完蛋了","為什麼我們不招.NET" 是什麼鬼。

1:一百多篇大資料檔案下載!

2:超全資料分析資料免費下載!(包括SQL,R語言,SPSS,SAS,python,資料分析和資料挖掘)

3:清華大學資料科學院講座內容集錦免費下載!

4:Python超全資料分享!

» 復旦大資料

ADVERTISEMENT