一個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的不同,中間曲曲折折了不少,最終還是寫出了最簡單的一段請求程式碼。

  1. importurllib.parse

  2. importurllib.request

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

  4. defgetHtml(url,values):

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

  6. headers =

  7. data = urllib.parse.urlencode(values)

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

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

  10. returnhtml

  11. #獲取資料

  12. defrequestCnblogs(index):

  13. print('請求資料')

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

  15. value= {

  16. 'CategoryId':808

  17. 'CategoryType':'SiteHome'

  18. 'ItemListActionName':'PostList'

  19. 'PageIndex': index,

  20. 'ParentCategoryId'

    ADVERTISEMENT
    :

  21. 'TotalPostCount':4000

  22. }

  23. result = getHtml(url,value)

  24. returnresult

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

資料解析

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

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

  1. class="post_item"
  2. class="digg"
  3. class="diggit"onclick="DiggPost('hyper-xl'64177412812381)"
  4. class="diggnum"id="digg_count_6417741"1

  • class="clear">
    ADVERTISEMENT

  • 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")下有使用者資訊,標題,連結,簡介等資訊。逐一根據樣式解析即可。

    程式碼如下:

    1. frombs4importBeautifulSoup

    2. importrequest

    3. importre

    4. #解析最外層

    5. defblogParser(index):

    6. cnblogs = request.requestCnblogs(index)

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

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

    9. blogs =

    10. #迴圈div獲取詳細資訊

    11. foriteminall_div:

    12. blog = analyzeBlog(item)

    13. blogs.append(blog)

    14. returnblogs

    15. #解析每一條資料

    16. defanalyzeBlog(item):

    17. result = {}

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

    19. ifa_titleisnotNone:

    20. # 部落格標題

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

    22. # 部落格連結

    23. result["href"] = a_title[]['href']

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

    25. ifp_summaryisnotNone:

    26. # 簡介

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

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

    29. footer = footers[]

    30. # 作者

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

    32. # 作者url

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

    34. str = footer.text

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

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

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

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

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

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

    41. returnresult

    42. deffind_all(item,attr,c):

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

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

    1. importmatch

    2. importos

    3. importdatetime

    4. importjson

    5. defwriteToTxt(list_name,file_path):

    6. try:

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

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

    9. l = len(list_name)

    10. i =

    11. fp.write('[')

    12. foriteminlist_name:

    13. fp.write(item)

    14. ifi1:

    15. fp.write(',\n')

    16. i +=1

    17. fp.write(']')

    18. fp.close

    19. exceptIOError:

    20. print("fail to open file")

    21. #def getStr(item):

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

    23. defsaveBlogs:

    24. foriinrange(12):

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

    26. blogs = match.blogParser(i,5)

    27. #儲存到檔案

    28. path = createFile

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

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

    31. return'success'

    32. defcreateFile:

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

    34. path ='/'+date

    35. ifos.path.exists(path):

    36. returnpath

    37. else:

    38. os.mkdir(path)

    39. returnpath

    40. result = saveBlogs

    41. print(result)

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

    成果驗收

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

    生成的檔案:

    檔案內容:

    總結

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

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

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

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

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

    4Python超全資料分享!


    » 復旦大資料

    ADVERTISEMENT
    ADVERTISEMENT