一个Python小白5个小时爬虫经历,分享一下
最近業(yè)余在做一個(gè)基于.NET Core的搜索項(xiàng)目,奈何基層代碼寫好了,沒有看起來很華麗的數(shù)據(jù)供測試。很巧的也是博客搜索,于是乎想到了博客園。C#也能做做頁面數(shù)據(jù)抓取的,不過在博客園看到的大部分都是python實(shí)現(xiàn),所以就臨時(shí)想了一下看看python到底是什么東東,不看基礎(chǔ)語法,不看語言功能,直接上代碼,哪里不會搜哪里。代碼完成總共用時(shí)大概4個(gè)小時(shí),其中搭建環(huán)境加安裝BeautifulSoup大概1個(gè)小時(shí)。解析HTML用時(shí)間最多了,邊看demo邊解析,大概2個(gè)小時(shí),剩下的時(shí)間就是調(diào)試加保存數(shù)據(jù)了。
環(huán)境搭建
既然用python,那么自然少不了語言環(huán)境。于是乎到官網(wǎng)下載了3.5版本的。安裝完之后,隨機(jī)選擇了一個(gè)編輯器叫PyCharm,話說python編輯器還真挺多的。由于本人是小白,所以安裝事項(xiàng)不在過多贅述。
建好項(xiàng)目,打開編輯器,直接開工。本來之前用C#寫的時(shí)候,大體思路就是獲取網(wǎng)頁內(nèi)容,然后正則匹配。后來發(fā)現(xiàn)網(wǎng)上的帖子也很多。不過在搜索過程中發(fā)現(xiàn),不建議用正則來匹配HTML。有正好我的正則不太好,所以我就搜了一下HTML解析工具,果不其然,人家都做好了,直接拿來用吧。沒錯(cuò)就是這個(gè)東東:BeautifulSoup 。安裝也很簡單,不過中間出了個(gè)小插曲,就是bs4沒有。繼續(xù)搜,然后需要用pip安裝一下就好了。(當(dāng)然我并不知道ps4和pip是什么鬼)
思路分析
博客嗎,我當(dāng)然就對準(zhǔn)了博客園,于是乎,進(jìn)入博客園首頁,查看請求。
發(fā)送請求
當(dāng)然我不知道python是怎么進(jìn)行網(wǎng)絡(luò)請求的,其中還有什么2.0和3.0的不同,中間曲曲折折了不少,最終還是寫出了最簡單的一段請求代碼。
import urllib.parse import urllib.request# params CategoryId=808 CategoryType=SiteHome ItemListActionName=PostList PageIndex=3 ParentCategoryId=0 TotalPostCount=4000 def getHtml(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 = {'User-Agent':user_agent}data = urllib.parse.urlencode(values)response_result = urllib.request.urlopen(url+'?'+data).read()html = response_result.decode('utf-8')return html#獲取數(shù)據(jù) def requestCnblogs(index):print('請求數(shù)據(jù)')url = 'http://www.cnblogs.com/mvc/AggSite/PostList.aspx'value= {'CategoryId':808,'CategoryType' : 'SiteHome','ItemListActionName' :'PostList','PageIndex' : index,'ParentCategoryId' : 0,'TotalPostCount' : 4000}result = getHtml(url,value)return result
其實(shí)博客園這個(gè)請求還是挺標(biāo)準(zhǔn)的,哈哈正好適合抓取。因?yàn)樗祷氐木褪且欢蝖tml。(如果返回json那不是更好。。。。)
數(shù)據(jù)解析
上文已經(jīng)提到了,用到的是BeautifulSoup,好處就是不用自己寫正則,只要根據(jù)他的語法來寫就好了,在多次的測試之后終于完成了數(shù)據(jù)的解析。先上一段HTML。然后在對應(yīng)下面的代碼,也許看起來更輕松一些。
<div class="post_item"><div class="digg"><div class="diggit" onclick="DiggPost('hyper-xl',6417741,281238,1)"><span class="diggnum" id="digg_count_6417741">1</span></div><div class="clear"></div><div id="digg_tip_6417741" class="digg_tip"></div></div><div class="post_item_body"><h3><a class="titlelnk" href="http://www.cnblogs.com/hyper-xl/p/6417741.html" target="_blank">Python 字符串格式化</a></h3><p class="post_item_summary"><a href="http://www.cnblogs.com/hyper-xl/" target="_blank"><img width="48" height="48" class="pfs"src="//pic.cnblogs.com/face/795666/20160421231717.png" alt="" /></a> 轉(zhuǎn)載請注明出處 Python2.6+ 增加了str.format函數(shù),用來代替原有的'%'操作符。它使用比'%'更加直觀、靈活。下面詳細(xì)介紹一下它的使用方法。 下面是使用'%'的例子: 格式很像C語言的printf是不是?由于'%'是一個(gè)操作符,只能在左右兩邊各放一個(gè)參數(shù),因此右邊多個(gè)值需要用元組或 ...</p><div class="post_item_foot"><a href="http://www.cnblogs.com/hyper-xl/" class="lightblue">新月的力量_141</a>發(fā)布于 2017-02-19 23:07<span class="article_comment"><a href="http://www.cnblogs.com/hyper-xl/p/6417741.html#commentform" title="" class="gray">評論(0)</a></span><span class="article_view"><a href="http://www.cnblogs.com/hyper-xl/p/6417741.html" class="gray">閱讀(138)</a></span></div></div><div class="clear"></div> </div>通過上文的HTML代碼可以看到幾點(diǎn)。首先每一條數(shù)據(jù)都在 div(class="post_item")下。然后 div("post_item_body")下有用戶信息,標(biāo)題,鏈接,簡介等信息。逐一根據(jù)樣式解析即可。代碼如下:
from bs4 import BeautifulSoup import request import re#解析最外層 def blogParser(index):cnblogs = request.requestCnblogs(index)soup = BeautifulSoup(cnblogs, 'html.parser')all_div = soup.find_all('div', attrs={'class': 'post_item_body'}, limit=20)blogs = []#循環(huán)div獲取詳細(xì)信息for item in all_div:blog = analyzeBlog(item)blogs.append(blog)return blogs#解析每一條數(shù)據(jù) def analyzeBlog(item):result = {}a_title = find_all(item,'a','titlelnk')if a_title is not None:# 博客標(biāo)題result["title"] = a_title[0].string# 博客鏈接result["href"] = a_title[0]['href']p_summary = find_all(item,'p','post_item_summary')if p_summary is not None:# 簡介result["summary"] = p_summary[0].textfooters = find_all(item,'div','post_item_foot')footer = footers[0]# 作者result["author"] = footer.a.string# 作者urlresult["author_url"] = footer.a['href']str = footer.texttime = re.findall(r"發(fā)布于 .+? .+? ", str)result["create_time"] = time[0].replace('發(fā)布于 ','')comment_str = find_all(footer,'span','article_comment')[0].a.stringresult["comment_num"] = re.search(r'\d+', comment_str).group()view_str = find_all(footer,'span','article_view')[0].a.stringresult["view_num"] = re.search(r'\d+', view_str).group()return resultdef find_all(item,attr,c):return item.find_all(attr,attrs={'class':c},limit=1)上邊一堆代碼下來,著實(shí)花費(fèi)了我不少時(shí)間,邊寫邊調(diào)試,邊百度~~不過還好最終還是出來了。等數(shù)據(jù)都整理好之后,然后我把它保存到了txt文件里面,以供其他語言來處理。本來想寫個(gè)put直接put到ElasticSearch中,奈何沒成功。后邊在試吧,畢竟我的重點(diǎn)只是導(dǎo)數(shù)據(jù),不在抓取這里。
import match import os import datetime import jsondef writeToTxt(list_name,file_path):try:#這里直接write item 即可,不要自己給序列化在寫入,會導(dǎo)致json格式不正確的問題fp = open(file_path,"w+",encoding='utf-8')l = len(list_name)i = 0fp.write('[')for item in list_name:fp.write(item)if i<l-1:fp.write(',\n')i += 1fp.write(']')fp.close()except IOError:print("fail to open file")#def getStr(item): # return json.dumps(item).replace('\'','\"')+',\n'def saveBlogs():for i in range(1,2):print('request for '+str(i)+'...')blogs = match.blogParser(i,5)#保存到文件path = createFile()writeToTxt(blogs,path+'/blog_'+ str(i) +'.json')print('第'+ str(i) +'頁已經(jīng)完成')return 'success'def createFile():date = datetime.datetime.now().strftime('%Y-%m-%d')path = '/'+dateif os.path.exists(path):return pathelse:os.mkdir(path)return pathresult = saveBlogs() print(result)如果大家對Python感興趣的話,可以加一下我們的學(xué)習(xí)交流摳摳群哦:649825285,免費(fèi)領(lǐng)取一套學(xué)習(xí)資料和視頻課程喲~
上邊呢,我取了一百頁的數(shù)據(jù),也就是大概2000條做測試。
成果驗(yàn)收
廢了好大勁終于寫完那些代碼之后呢,就可以享受勝利的果實(shí)了,雖然是初學(xué)者,代碼寫的很渣,這參考一下,那參考一下,不過還是有些收獲的。運(yùn)行效果如下:
生成的文件:
文件內(nèi)容:
總結(jié)
一個(gè)簡單的抓取程序就寫完了,python還真是TM的好用。以后有空再研究研究吧。代碼行數(shù)算上空行和注釋總共?100?(50+25+25) 行。湊個(gè)整數(shù)好看點(diǎn)~~現(xiàn)在認(rèn)識字我感覺就可以上手寫程序了。這里百度一下,那里google一下,問題就解決了,程序也出來了,大功告成。
總結(jié)
以上是生活随笔為你收集整理的一个Python小白5个小时爬虫经历,分享一下的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TypeError: 'function
- 下一篇: pycharm弹出提示信息Server'