多進(jìn)程+多線程+redis 構(gòu)建簡(jiǎn)單分布式程序

前言

最近把目光投向了,妹子圖(你一看見這三個(gè)字是不是頭都大了, 怎么又是這個(gè)網(wǎng)站,被這幫搞爬蟲的都爬爛了吧),先不要著急,別人爬過不代表你也能爬,每個(gè)人寫爬蟲的思路都是不一樣的。 重要的是自己動(dòng)手做一遍。整體看這個(gè)網(wǎng)站的爬取難度并不大,而且還有福利,為啥不試試呢。單線程的畢竟是太慢了,那么多進(jìn)程+多線程+redis ,做一個(gè)簡(jiǎn)易的分布式程序?qū)⑹俏医酉聛頂⑹龅闹攸c(diǎn)。

程序雖小,也要五臟俱全。

全軍出擊

抓取流程整理:
網(wǎng)站首頁(yè):

網(wǎng)站首頁(yè)

抓取的方式就不多敘述了,使用瀏覽器抓取工具可以很容易獲取到,如下圖:

源碼分析

之后點(diǎn)擊標(biāo)題,多點(diǎn)擊幾個(gè)分頁(yè),分析url生成規(guī)律,便于程序拼接網(wǎng)址鏈接,之后查看圖片的地址,分析抓取規(guī)則,便于程序下載:

標(biāo)題詳情

在該頁(yè)面下,主要做兩個(gè)分析,一個(gè)是分析該套標(biāo)題下,一共有多少?gòu)垐D片,也就是圖片中的64要抓下來,還有就是圖片的鏈接地址,也要抓下來。

好了網(wǎng)站基本分析完了,開始寫程序。

代碼解析

下面只是部分主要的代碼完整代碼請(qǐng)見文后地址。
抓取所有的標(biāo)題,并入庫(kù):
<pre>
def get_page_count(self ,url):
'''
根據(jù)首頁(yè)地址,獲取標(biāo)題頁(yè)面的總數(shù),并拼接標(biāo)題頁(yè)網(wǎng)址
:param url:
:return:
'''
html = download(url)
soup = BeautifulSoup(html.text, 'lxml')
pageNum = soup.find('div', class_='nav-links').find_all('a')[-2].get_text()
for page in range(1 ,int(pageNum)+1):
url = 'http://www.mzitu.com/page/{}/'.format(page)
self.download_html(url)
def download_html(self ,url):
'''
下載單個(gè)頁(yè)面
:param url:
:return:
'''
print 'download : %s ' % url
html = download(url)
self.parse_html(html.text)
def parse_html(self ,html):
'''
解析html,并入庫(kù)
:param html:
:return:
'''
soup = BeautifulSoup(html, 'lxml')
li_list = soup.find('ul', id='pins').find_all('li')
valus = dict()
for li in li_list:
a = li.find('span').find('a')
valus[a.get('href')] = a.get_text()
self.save_in_hash('mzitu' ,valus)
</code></pre>
從redis獲取信息,并完成下載保存:
<pre>
def getdownloadUrl(self):
'''
從redis 獲取鏈接地址
:return:
'''
while True:
url = self.client.pop()
print 'download url : %s' % url
if not url:
break
html = download(url)
soup = BeautifulSoup(html.text, 'lxml')
a_list = soup.find('div', class_='pagenavi').find_all('span')[-2].get_text()
self.download_page(a_list ,url )
def download_page(self ,pageNum ,url):
'''
下載標(biāo)題詳情頁(yè)面,創(chuàng)建保存圖片文件夾,啟用多線程下載圖片
:param pageNum:
:param url:
:return:
'''
title = self.client.get_hashvalue(url)
path = title.strip().replace('?', '').replace(' ', '').decode('utf-8')
self.mkdir(path)
for page in range(1 ,int(pageNum)+1):
page_url = url+"/"+str(page)
time.sleep(0.8)
thread = threading.Thread(target=self.mutliprocess, args=(page_url ,))
thread.start()
def mutliprocess(self , page_url):
'''
多線程下載圖片
:param page_url:
:return:
'''
page_html = download(page_url)
imgurl = BeautifulSoup(page_html.text, 'lxml').find('div', class
='main-image').find('img')['src']
self.down_img(imgurl)
def down_img(self , imgurl):
'''
保存圖片
:param imgurl:
:return:
'''
with open(imgurl[-9:] ,'wb') as f :
f.write(download(imgurl).content)
</pre>
多進(jìn)程啟動(dòng)程序:
<pre>
start = time.time()
proc_list = []
for num in range(5):
proc = Process(target=run, args=())
proc_list.append(proc)
for p in proc_list:
p.start()
for p in proc_list:
p.join()
end = time.time()
print end -start
</pre>

程序框架

簡(jiǎn)易框架圖

運(yùn)行效果

效果圖

源碼地址

github:https://github.com/topyuluo/MZiTu_Distributed
代理池:http://www.itdecent.cn/p/fd92ca79c9c7



少年聽雨歌樓上,紅燭昏羅帳。  
壯年聽雨客舟中,江闊云低,斷雁叫西風(fēng)。
感謝支持!
                                        ---起個(gè)名忒難

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容