Python爬蟲實戰六之抓取愛問知識人問題並保存至資料庫

大家好,本次為大家帶來的是抓取愛問知識人的問題並將問題和答案保存到資料庫的方法,涉及的內容包括:

  • Urllib的用法及異常處理
  • Beautiful Soup的簡單應用
  • MySQLdb的基礎用法
  • 正則表達式的簡單應用

環境配置

在這之前,我們需要先配置一下環境,我的Python的版本為2.7,需要額外安裝的庫有兩個,一個是Beautiful Soup,一個是MySQLdb,在這裡附上兩個庫的下載地址,

Beautiful SoupMySQLdb

大家可以下載之後通過如下命令安裝

python setup.py installn

環境配置好之後,我們便可以開心地擼爬蟲了

框架思路

首先我們隨便找一個分類地址,外語學習 – 愛問知識人,打開之後可以看到一系列的問題列表。

我們在這個頁面需要獲取的東西有:

總的頁碼數,每一頁的所有問題鏈接。

接下來我們需要遍歷所有的問題,來抓取每一個詳情頁面,提取問題,問題內容,回答者,回答時間,回答內容。

最後,我們需要把這些內容存儲到資料庫中。

要點簡析

其實大部分內容相信大家會了前面的內容,這裡的爬蟲思路已經融匯貫通了,這裡就說一下一些擴展的功能

1.日誌輸出

日誌輸出,我們要輸出時間和爬取的狀態,比如像下面這樣:

[2015-08-10 03:05:20] 113011 號問題存在其他答案 我個人認為應該是櫻桃溝很美的

[2015-08-10 03:05:20] 保存到資料庫,此問題的ID為 113011

[2015-08-10 03:05:20] 當前爬取第 2 的內容,發現一個問題 百度有一個地方,花兒帶著芳香,水兒流淌奔騰是什麼意思 多多幫忙哦 回答數量 1

[2015-08-10 03:05:19] 保存到資料庫,此問題的ID為 113010

所以,我們需要引入時間函數,然後寫一個獲取當前時間的函數

import timenn#獲取當前時間ndef getCurrentTime(self):nreturn time.strftime([%Y-%m-%d %H:%M:%S],time.localtime(time.time()))nn#獲取當前時間ndef getCurrentDate(self):nreturn time.strftime(%Y-%m-%d,time.localtime(time.time()))n

以上分別是獲取帶具體時間和獲取日期的函數,在輸出時,我們可以在輸出語句的前面調用這函數即可。

然後我們需要將緩衝區設置輸出到log中,在程序的最前面加上這兩句即可

f_handler=open(out.log, w) nsys.stdout=f_handlern

這樣,所有的print語句輸出的內容就會保存到out.log文件中了。

2.頁碼保存

爬蟲爬取過程中可能出現各種各樣的錯誤,這樣會導致爬蟲的中斷,如果我們重新運行爬蟲,那麼就會導致爬蟲從頭開始運行了,這樣顯然是不合理的。所以,我們需要把當前爬取的頁面保存下來,比如可以保存到文本中,假如爬蟲中斷了,重新運行爬蟲,讀取文本文件的內容,接著爬取即可。

大家可以稍微參考一下函數的實現:

#主函數ndef main(self):n f_handler=open(out.log, w) n sys.stdout=f_handlern page = open(page.txt, r)n content = page.readline()n start_page = int(content.strip()) - 1n page.close() nprint self.getCurrentTime(),"開始頁碼",start_pagenprint self.getCurrentTime(),"爬蟲正在啟動,開始爬取愛問知識人問題"n self.total_num = self.getTotalPageNum()nprint self.getCurrentTime(),"獲取到目錄頁面個數",self.total_num,"個"nif not start_page:n start_page = self.total_numnfor x in range(1,start_page):nprint self.getCurrentTime(),"正在抓取第",start_page-x+1,"個頁面"ntry:n self.getQuestions(start_page-x+1)nexcept urllib2.URLError, e:nif hasattr(e, "reason"):nprint self.getCurrentTime(),"某總頁面內抓取或提取失敗,錯誤原因", e.reasonnexcept Exception,e: nprint self.getCurrentTime(),"某總頁面內抓取或提取失敗,錯誤原因:",enif start_page-x+1 < start_page:n f=open(page.txt,w)n f.write(str(start_page-x+1))nprint self.getCurrentTime(),"寫入新頁碼",start_page-x+1n f.close()n

這樣,不管我們爬蟲中途遇到什麼錯誤,媽媽也不會擔心了

3.頁面處理

頁面處理過程中,我們可能遇到各種各樣奇葩的HTML代碼,和上一節一樣,我們沿用一個頁面處理類即可。

import renn#處理頁面標籤類nclass Tool:nn#將超鏈接廣告剔除n removeADLink = re.compile(<div class="link_layer.*?</div>)n#去除img標籤,1-7位空格, n removeImg = re.compile(<img.*?>| {1,7}| )n#刪除超鏈接標籤n removeAddr = re.compile(<a.*?>|</a>)n#把換行的標籤換為nn replaceLine = re.compile(<tr>|<div>|</div>|</p>)n#將表格製表<td>替換為tn replaceTD= re.compile(<td>)n#將換行符或雙換行符替換為nn replaceBR = re.compile(<br><br>|<br>)n#將其餘標籤剔除n removeExtraTag = re.compile(<.*?>)n#將多行空行刪除n removeNoneLine = re.compile(n+)nndef replace(self,x):n x = re.sub(self.removeADLink,"",x)n x = re.sub(self.removeImg,"",x)n x = re.sub(self.removeAddr,"",x)n x = re.sub(self.replaceLine,"n",x)n x = re.sub(self.replaceTD,"t",x)n x = re.sub(self.replaceBR,"n",x)n x = re.sub(self.removeExtraTag,"",x)n x = re.sub(self.removeNoneLine,"n",x)n#strip()將前後多餘內容刪除nreturn x.strip()n

我們可以用一段含有HTML代碼的文字,經過調用replace方法之後,各種冗餘的HTML代碼就會處理好了。

比如我們這麼一段代碼:

<article class="article-content">n<h2>前言</h2>n<p>最近發現MySQL服務隔三差五就會掛掉,導致我的網站和爬蟲都無法正常運作。自己的網站是基於MySQL,在做爬蟲存取一些資料的時候也是基於MySQL,數據量一大了,MySQL它就有點受不了了,時不時會崩掉,雖然我自己有網站監控和郵件通知,但是好多時候還是需要我來手動連接我的伺服器重新啟動一下我的MySQL,這樣簡直太不友好了,所以,我就覺定自己寫個腳本,定時監控它,如果發現它掛掉了就重啟它。</p>n<p>好了,閑言碎語不多講,開始我們的配置之旅。</p>n<p>運行環境:<strong>Ubuntu Linux 14.04</strong></p>n<h2>編寫Shell腳本</h2>n<p>首先,我們要編寫一個shell腳本,腳本主要執行的邏輯如下:</p>n<p>顯示mysqld進程狀態,如果判斷進程未在運行,那麼輸出日誌到文件,然後啟動mysql服務,如果進程在運行,那麼不執行任何操作,可以選擇性輸出監測結果。</p>n<p>可能大家對於shell腳本比較陌生,在這裡推薦官方的shell腳本文檔來參考一下</p>n<p><a href="http://wiki.ubuntu.org.cn/Shell%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80" data-original-title="" title="">Ubuntu Shell 編程基礎</a></p>n<p>shell腳本的後綴為sh,在任何位置新建一個腳本文件,我選擇在 /etc/mysql 目錄下新建一個 listen.sh 文件。</p>n<p>執行如下命令:</p>n

經過處理後便會變成如下的樣子:

前言n最近發現MySQL服務隔三差五就會掛掉,導致我的網站和爬蟲都無法正常運作。自己的網站是基於MySQL,在做爬蟲存取一些資料的時候也是基於MySQL,數據量一大了,MySQL它就有點受不了了,時不時會崩掉,雖然我自己有網站監控和郵件通知,但是好多時候還是需要我來手動連接我的伺服器重新啟動一下我的MySQL,這樣簡直太不友好了,所以,我就覺定自己寫個腳本,定時監控它,如果發現它掛掉了就重啟它。n好了,閑言碎語不多講,開始我們的配置之旅。n運行環境:UbuntuLinux14.04n編寫Shell腳本n首先,我們要編寫一個shell腳本,腳本主要執行的邏輯如下:n顯示mysqld進程狀態,如果判斷進程未在運行,那麼輸出日誌到文件,然後啟動mysql服務,如果進程在運行,那麼不執行任何操作,可以選擇性輸出監測結果。n可能大家對於shell腳本比較陌生,在這裡推薦官方的shell腳本文檔來參考一下nUbuntuShell編程基礎nshell腳本的後綴為sh,在任何位置新建一個腳本文件,我選擇在/etc/mysql目錄下新建一個listen.sh文件。n執行如下命令:n

經過上面的處理,所有亂亂的代碼都會被處理好了。

4.保存到資料庫

在這裡,我們想實現一個通用的方法,就是把存儲的一個個內容變成字典的形式,然後執行插入語句的時候,自動構建對應的sql語句,插入數據。

比如我們構造如下的字典:

#構造最佳答案的字典ngood_ans_dict = {n"text": good_ans[0],n"answerer": good_ans[1],n"date": good_ans[2],n"is_good": str(good_ans[3]),n"question_id": str(insert_id)n }n

構造sql語句並插入到資料庫的方法如下:

#插入數據ndef insertData(self, table, my_dict):ntry:n self.db.set_character_set(utf8)n cols = , .join(my_dict.keys())n values = "," .join(my_dict.values())n sql = "INSERT INTO %s (%s) VALUES (%s)" % (table, cols, "+values+")ntry:n result = self.cur.execute(sql)n insert_id = self.db.insert_id()n self.db.commit()n#判斷是否執行成功nif result:nreturn insert_idnelse:nreturn 0nexcept MySQLdb.Error,e:n#發生錯誤時回滾n self.db.rollback()n#主鍵唯一,無法插入nif "key PRIMARY" in e.args[1]:nprint self.getCurrentTime(),"數據已存在,未插入數據"nelse:nprint self.getCurrentTime(),"插入數據失敗,原因 %d: %s" % (e.args[0], e.args[1])nexcept MySQLdb.Error,e:nprint self.getCurrentTime(),"資料庫錯誤,原因%d: %s" % (e.args[0], e.args[1])n

這裡我們只需要傳入那個字典,便會構建出對應字典鍵值和鍵名的sql語句,完成插入。

5.PHP讀取日誌

我們將運行結果輸出到了日誌里,那麼怎麼查看日誌呢?很簡單,在這裡提供兩種方法

方法一:

PHP倒序輸出所有日誌內容

<html>n<head>n<meta charset="utf-8">n<meta http-equiv="refresh" content = "5"> n</head>n<body>n<?phpn$fp = file("out.log");nif ($fp) {nfor($i = count($fp) - 1;$i >= 0; $i --) necho $fp[$i]."<br>";n }n?>n</body>n</html>n

此方法可以看到所有的輸入日誌,但是如果日誌太大了,那麼就會報耗費內存太大,無法輸出。為此我們就有了第二種方法,利用linux命令,輸出後十行內容。

方法二:

<html>n<head>n<meta charset="utf-8">n<meta http-equiv="refresh" content = "5"> n</head>n<body>n<?php n$ph = popen(tail -n 100 out.log,r);nwhile($r = fgets($ph)){necho $r."<br>";n }n pclose($ph);n?>n</body>n</html>n

上面兩種方法都是5秒刷新一次網頁來查看最新的日誌。

源代碼放送

好了,閑言碎語不多講,直接上源碼了

spider.pyn

# -*- coding:utf-8 -*-nnimport urllibnimport urllib2nimport renimport timenimport typesnimport pagenimport mysqlnimport sysnfrom bs4 import BeautifulSoupnnclass Spider:nn#初始化ndef __init__(self):n self.page_num = 1n self.total_num = Nonen self.page_spider = page.Page()n self.mysql = mysql.Mysql()nn#獲取當前時間ndef getCurrentTime(self):nreturn time.strftime([%Y-%m-%d %H:%M:%S],time.localtime(time.time()))nn#獲取當前時間ndef getCurrentDate(self):nreturn time.strftime(%Y-%m-%d,time.localtime(time.time()))nn#通過網頁的頁碼數來構建網頁的URLndef getPageURLByNum(self, page_num):n page_url = "http://iask.sina.com.cn/c/978-" + str(page_num) + ".html"nreturn page_urlnnn#通過傳入網頁頁碼來獲取網頁的HTMLndef getPageByNum(self, page_num):n request = urllib2.Request(self.getPageURLByNum(page_num))ntry:n response = urllib2.urlopen(request)nexcept urllib2.URLError, e:nif hasattr(e, "code"):nprint self.getCurrentTime(),"獲取頁面失敗,錯誤代號", e.codenreturn Nonenif hasattr(e, "reason"):nprint self.getCurrentTime(),"獲取頁面失敗,原因", e.reasonnreturn Nonenelse:n page = response.read().decode("utf-8")nreturn pagenn#獲取所有的頁碼數ndef getTotalPageNum(self):nprint self.getCurrentTime(),"正在獲取目錄頁面個數,請稍候"n page = self.getPageByNum(1)n#匹配所有的頁碼數,下一頁是下一頁的UTF8編碼n pattern = re.compile(u<span class="more".*?>.*?<span.*?<a href.*?class="">(.*?)</a>s*<a.*?下一頁</a>, re.S)n match = re.search(pattern, page)nif match:nreturn match.group(1)nelse:nprint self.getCurrentTime(),"獲取總頁碼失敗"nn#分析問題的代碼,得到問題的提問者,問題內容,回答個數,提問時間ndef getQuestionInfo(self, question):nif not type(question) is types.StringType:n question = str(question)n#print questionn pattern = re.compile(u<span.*?question-face.*?>.*?<img.*?alt="(.*?)".*?</span>.*?<a href="https://ask.hellobi.com/(.*?)".*?>(.*?)</a>.*?answer_num.*?>(d*).*?</span>.*?answer_time.*?>(.*?)</span>, re.S)n match = re.search(pattern, question)nif match:n#獲得提問者n author = match.group(1)n#問題鏈接n href = match.group(2)n#問題詳情n text = match.group(3)n#回答個數n ans_num = match.group(4)n#回答時間n time = match.group(5)n time_pattern = re.compile(d{4}-d{2}-d{2}, re.S)n time_match = re.search(time_pattern, time)nif not time_match:n time = self.getCurrentDate()nreturn [author, href, text, ans_num, time]nelse:nreturn Nonenn#獲取全部問題ndef getQuestions(self, page_num):n#獲得目錄頁面的HTMLn page = self.getPageByNum(page_num)n soup = BeautifulSoup(page)n#分析獲得所有問題n questions = soup.select("div.question_list ul li")n#遍歷每一個問題nfor question in questions:n#獲得問題的詳情n info = self.getQuestionInfo(question)nif info:n#得到問題的URLn url = "http://iask.sina.com.cn/" + info[1]n#通過URL來獲取問題的最佳答案和其他答案n ans = self.page_spider.getAnswer(url)nprint self.getCurrentTime(),"當前爬取第",page_num,"的內容,發現一個問題",info[2],"回答數量",info[3]n#構造問題的字典,插入問題n ques_dict = {n"text": info[2],n"questioner": info[0],n"date": info[4],n"ans_num": info[3],n"url": urln }n#獲得插入的問題的自增ID n insert_id = self.mysql.insertData("iask_questions",ques_dict)n#得到最佳答案n good_ans = ans[0]nprint self.getCurrentTime(),"保存到資料庫,此問題的ID為",insert_idn#如果存在最佳答案,那麼就插入nif good_ans:nprint self.getCurrentTime(),insert_id,"號問題存在最佳答案",good_ans[0]n#構造最佳答案的字典n good_ans_dict = {n"text": good_ans[0],n"answerer": good_ans[1],n"date": good_ans[2],n"is_good": str(good_ans[3]),n"question_id": str(insert_id)n }n#插入最佳答案nif self.mysql.insertData("iask_answers",good_ans_dict):nprint self.getCurrentTime(),"保存最佳答案成功"nelse:nprint self.getCurrentTime(),"保存最佳答案失敗"n#獲得其他答案n other_anses = ans[1]n#遍歷每一個其他答案nfor other_ans in other_anses:n#如果答案存在nif other_ans:nprint self.getCurrentTime(),insert_id,"號問題存在其他答案",other_ans[0]n#構造其他答案的字典n other_ans_dict = {n"text": other_ans[0],n"answerer": other_ans[1],n"date": other_ans[2],n"is_good": str(other_ans[3]),n"question_id": str(insert_id)n }n#插入這個答案nif self.mysql.insertData("iask_answers",other_ans_dict):nprint self.getCurrentTime(),"保存其他答案成功"nelse:nprint self.getCurrentTime(),"保存其他答案失敗"nn#主函數ndef main(self):n f_handler=open(out.log, w) n sys.stdout=f_handlern page = open(page.txt, r)n content = page.readline()n start_page = int(content.strip()) - 1n page.close() nprint self.getCurrentTime(),"開始頁碼",start_pagenprint self.getCurrentTime(),"爬蟲正在啟動,開始爬取愛問知識人問題"n self.total_num = self.getTotalPageNum()nprint self.getCurrentTime(),"獲取到目錄頁面個數",self.total_num,"個"nif not start_page:n start_page = self.total_numnfor x in range(1,start_page):nprint self.getCurrentTime(),"正在抓取第",start_page-x+1,"個頁面"ntry:n self.getQuestions(start_page-x+1)nexcept urllib2.URLError, e:nif hasattr(e, "reason"):nprint self.getCurrentTime(),"某總頁面內抓取或提取失敗,錯誤原因", e.reasonnexcept Exception,e: nprint self.getCurrentTime(),"某總頁面內抓取或提取失敗,錯誤原因:",enif start_page-x+1 < start_page:n f=open(page.txt,w)n f.write(str(start_page-x+1))nprint self.getCurrentTime(),"寫入新頁碼",start_page-x+1n f.close()nnspider = Spider()nspider.main() n

page.pyn

# -*- coding:utf-8 -*-nimport urllibnimport urllib2nimport renimport timenimport types nimport toolnfrom bs4 import BeautifulSoupnn#抓取分析某一問題和答案nclass Page:nndef __init__(self):n self.tool = tool.Tool()nn#獲取當前時間ndef getCurrentDate(self):nreturn time.strftime(%Y-%m-%d,time.localtime(time.time()))nn#獲取當前時間ndef getCurrentTime(self):nreturn time.strftime([%Y-%m-%d %H:%M:%S],time.localtime(time.time()))nn#通過頁面的URL來獲取頁面的代碼ndef getPageByURL(self, url):ntry:n request = urllib2.Request(url)n response = urllib2.urlopen(request)nreturn response.read().decode("utf-8") nexcept urllib2.URLError, e:nif hasattr(e, "code"):nprint self.getCurrentTime(),"獲取問題頁面失敗,錯誤代號", e.codenreturn Nonenif hasattr(e, "reason"):nprint self.getCurrentTime(),"獲取問題頁面失敗,原因", e.reasonnreturn Nonennn#傳入一個List,返回它的標籤里的內容,如果為空返回Nonendef getText(self, html):nif not type(html) is types.StringType:n html = str(html)n#提取出<pre>標籤里的內容n pattern = re.compile(<pre.*?>(.*?)</pre>, re.S)n match = re.search(pattern, html)n#如果匹配成功nif match:nreturn match.group(1)nelse: nreturn Nonenn#傳入最佳答案的HTML,分析出回答者和回答時間ndef getGoodAnswerInfo(self, html):n pattern = re.compile("answer_tip.*?<a.*?>(.*?)</a>.*?<span class="time.*?>.*?|(.*?)</span>, re.S)n match = re.search(pattern, html)n#如果匹配,返回回答者和回答時間nif match:n time = match.group(2)n time_pattern = re.compile(d{2}-d{2}-d{2}, re.S)n time_match = re.search(time_pattern, time)nif not time_match:n time = self.getCurrentDate()nelse:n time = "20"+timenreturn [match.group(1),time]nelse:nreturn [None,None]nn#獲得最佳答案ndef getGoodAnswer(self, page):n soup = BeautifulSoup(page)n text = soup.select("div.good_point div.answer_text pre")nif len(text) > 0:n#獲得最佳答案的內容n ansText = self.getText(str(text[0]))n ansText = self.tool.replace(ansText)n#獲得最佳答案的回答者信息n info = soup.select("div.good_point div.answer_tip")n ansInfo = self.getGoodAnswerInfo(str(info[0]))n#將三者組合成一個Listn answer = [ansText, ansInfo[0], ansInfo[1],1]nreturn answernelse:n#如果不存在最佳答案,那麼就返回空nreturn Nonenn#傳入回答者HTML,分析出回答者,回答時間ndef getOtherAnswerInfo(self, html):nif not type(html) is types.StringType:n html = str(html)n pattern = re.compile("author_name.*?>(.*?)</a>.*?answer_t">(.*?)</span>, re.S)n match = re.search(pattern, html)n#獲得每一個回答的回答者信息和回答時間nif match:n time = match.group(2)n time_pattern = re.compile(d{2}-d{2}-d{2}, re.S)n time_match = re.search(time_pattern, time)nif not time_match:n time = self.getCurrentDate()nelse:n time = "20"+timenreturn [match.group(1),time]nelse:nreturn [None,None]nnn#獲得其他答案ndef getOtherAnswers(self, page):n soup = BeautifulSoup(page)n results = soup.select("div.question_box li.clearfix .answer_info")n#所有答案,包含好多個List,每個List包含了回答內容,回答者,回答時間n answers = []nfor result in results:n#獲得回答內容n ansSoup = BeautifulSoup(str(result))n text = ansSoup.select(".answer_txt span pre")n ansText = self.getText(str(text[0]))n ansText = self.tool.replace(ansText)n#獲得回答者和回答時間n info = ansSoup.select(".answer_tj")n ansInfo = self.getOtherAnswerInfo(info[0])n#將三者組合成一個Listn answer = [ansText, ansInfo[0], ansInfo[1],0]n#加入到answersn answers.append(answer)nreturn answersnn#主函數ndef getAnswer(self, url):nif not url:n url = "http://iask.sina.com.cn/b/gQiuSNCMV.html"n page = self.getPageByURL(url)n good_ans = self.getGoodAnswer(page)n other_ans = self.getOtherAnswers(page)nreturn [good_ans,other_ans]nnnpage = Page()npage.getAnswer(None)n

tool.pyn

#-*- coding:utf-8 -*-nimport renn#處理頁面標籤類nclass Tool:nn#將超鏈接廣告剔除n removeADLink = re.compile(<div class="link_layer.*?</div>)n#去除img標籤,1-7位空格, n removeImg = re.compile(<img.*?>| {1,7}| )n#刪除超鏈接標籤n removeAddr = re.compile(<a.*?>|</a>)n#把換行的標籤換為nn replaceLine = re.compile(<tr>|<div>|</div>|</p>)n#將表格製表<td>替換為tn replaceTD= re.compile(<td>)n#將換行符或雙換行符替換為nn replaceBR = re.compile(<br><br>|<br>)n#將其餘標籤剔除n removeExtraTag = re.compile(<.*?>)n#將多行空行刪除n removeNoneLine = re.compile(n+)nndef replace(self,x):n x = re.sub(self.removeADLink,"",x)n x = re.sub(self.removeImg,"",x)n x = re.sub(self.removeAddr,"",x)n x = re.sub(self.replaceLine,"n",x)n x = re.sub(self.replaceTD,"t",x)n x = re.sub(self.replaceBR,"n",x)n x = re.sub(self.removeExtraTag,"",x)n x = re.sub(self.removeNoneLine,"n",x)n#strip()將前後多餘內容刪除nreturn x.strip()n

mysql.pyn

# -*- coding:utf-8 -*-nnnimport MySQLdbnimport timennclass Mysql:nn#獲取當前時間ndef getCurrentTime(self):nreturn time.strftime([%Y-%m-%d %H:%M:%S],time.localtime(time.time()))nn#資料庫初始化ndef __init__(self):ntry:n self.db = MySQLdb.connect(ip,username,password,db_name)n self.cur = self.db.cursor()nexcept MySQLdb.Error,e:nprint self.getCurrentTime(),"連接資料庫錯誤,原因%d: %s" % (e.args[0], e.args[1])nn#插入數據ndef insertData(self, table, my_dict):ntry:n self.db.set_character_set(utf8)n cols = , .join(my_dict.keys())n values = "," .join(my_dict.values())n sql = "INSERT INTO %s (%s) VALUES (%s)" % (table, cols, "+values+")ntry:n result = self.cur.execute(sql)n insert_id = self.db.insert_id()n self.db.commit()n#判斷是否執行成功nif result:nreturn insert_idnelse:nreturn 0nexcept MySQLdb.Error,e:n#發生錯誤時回滾n self.db.rollback()n#主鍵唯一,無法插入nif "key PRIMARY" in e.args[1]:nprint self.getCurrentTime(),"數據已存在,未插入數據"nelse:nprint self.getCurrentTime(),"插入數據失敗,原因 %d: %s" % (e.args[0], e.args[1])nexcept MySQLdb.Error,e:nprint self.getCurrentTime(),"資料庫錯誤,原因%d: %s" % (e.args[0], e.args[1])n

資料庫建表SQL如下:

CREATE TABLE IF NOT EXISTS `iask_answers` (n`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,n`text` text NOT NULL COMMENT 回答內容,n`question_id` int(18) NOT NULL COMMENT 問題ID,n`answerer` varchar(255) NOT NULL COMMENT 回答者,n`date` varchar(255) NOT NULL COMMENT 回答時間,n`is_good` int(11) NOT NULL COMMENT 是否是最佳答案,n PRIMARY KEY (`id`)n) ENGINE=InnoDB DEFAULT CHARSET=utf8;nnCREATE TABLE IF NOT EXISTS `iask_questions` (n`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 問題ID,n`text` text NOT NULL COMMENT 問題內容,n`questioner` varchar(255) NOT NULL COMMENT 提問者,n`date` date NOT NULL COMMENT 提問時間,n`ans_num` int(11) NOT NULL COMMENT 回答數量,n`url` varchar(255) NOT NULL COMMENT 問題鏈接,n PRIMARY KEY (`id`)n) ENGINE=InnoDB DEFAULT CHARSET=utf8;n

運行的時候執行如下命令即可

nohup python spider.py &n

代碼寫的不好,僅供大家學習參考使用,如有問題,歡迎留言交流。

運行結果查看

我們把PHP文件和log文件放在同一目錄下,運行PHP文件,便可以看到如下的內容:

小夥伴們趕快試一下吧。

Python爬蟲實戰一之爬取糗事百科段子

Python爬蟲實戰二之爬取百度貼吧帖子

Python爬蟲實戰三之實現山東大學無線網路掉線自動重連

Python爬蟲實戰四之抓取淘寶MM照片

Python爬蟲實戰五之模擬登錄淘寶並獲取所有訂單

作者:崔慶才

出處:崔慶才的個人博客

最近很多人私信問我問題,平常知乎評論看到不多,如果沒有及時回復,大家也可以加小編微信:tszhihu,進知乎大數據分析挖掘交流群,可以跟各位老師互相交流。謝謝。


推薦閱讀:

python selenium模塊使用出錯,這個怎麼改?
P 站非會員查看人氣作品
突破漢字點選驗證碼,實現熊貓TV自動領竹子

TAG:Python | Python开发 |