1. 程式人生 > >python scrapy框架爬取知乎提問資訊

python scrapy框架爬取知乎提問資訊

前文介紹了python的scrapy爬蟲框架和登入知乎的方法.
這裡介紹如何爬取知乎的問題資訊,並儲存到mysql資料庫中.

首先,看一下我要爬取哪些內容:

如下圖所示,我要爬取一個問題的6個資訊:

  • 問題的id(question_id)
  • 標題(title)
  • 問題描述(intro)
  • 回答個數(answer_num)
  • 關注人數(attention_uv)
  • 瀏覽次數(read_pv) 

爬取結果我儲存到mysql資料庫中,表名為:zhihu_question
如下圖中,紅框裡的就是上圖是有人為我的穿著很輕浮,我該如何迴應?問題的資訊.
(回答個數,關注著和瀏覽次數資料不一致是因為我是在爬取文章資訊之後的一段時間才抽出來時間寫的文章,在這期間回答個數,關注著和瀏覽次數都會增長.)

爬取方法介紹

我用的是scrapy框架中自帶的選擇器selectors.
selectors通過特定的 XPath 或者 CSS 表示式來“選擇” HTML檔案中的某個部分。
XPath 是一門用來在XML檔案中選擇節點的語言,也可以用在HTML上。 CSS 是一門將HTML文件樣式化的語言。
XPath最最直觀的介紹:
例如:知乎問題頁面上的標題的XPath如下:
圖中紅框裡就是標題的XPath.(這只是一個直觀的介紹,還有一些細節可以在程式碼中看到)

爬取程式碼:

爬取問題的相關資訊只需要問題url即可,我這裡把收集的問題url寫到檔案中,爬蟲程式去遍歷檔案,然後依次爬取.
我是在登入成功知乎後的check_login

這個方法裡面構造的起始url,所以讀檔案的方法也在這裡,程式碼如下:

def check_login(self, response):
         # 驗證登入成功之後構造初始問題url
         file = open("/root/py_project/zhihu/zhihu/conf/start_questions.txt") 
         while 1:
            line = file.readline()
            line = line.strip('\n')  #去掉最後的換行 
            if not line:
                break
            if(line[0:1] == "#"):
                #如果是#開頭的url, 跳過
                print line
                pass
            else:
                print("current url :  " + line)
                yield scrapy.Request(line,callback=self.parse_question, headers=self.headers)
         file.close()

其中最重要的一行是:
yield scrapy.Request(line,callback=self.parse_question, headers=self.headers)

yield scrapy.Request 代表開始爬取一條url,如果有多個url就yield多次. 這裡的次數等同於start_question.txt中非#開頭的url
如下:

callback=self.parse_question 是請求url地址後,返回的response的回撥處理函式,也是整個爬取過程中最核心的程式碼.
如下:

    def parse_question(self,response):
        item = QuestionItem()
        url = response.url
        questionid=url[url.rindex("/")+1:]
        item['questionid']=questionid
        item['title']=response.selector.xpath('//*[@class="QuestionHeader-title"]/text()')[0].extract()
        descarr=response.selector.xpath('//span[@itemprop="text"]/text()')
        if len(descarr) > 0:
            item['desc']=descarr[0].extract()
        else:
            item['desc']="-"
        item['answer_num']=response.selector.xpath('//*[@id="QuestionAnswers-answers"]/div/div/div[1]/h4/span/text()[1]')[0].extract().replace(',','')
        item['attention_uv']=response.selector.xpath('//strong[@class="NumberBoard-itemValue"]/text()')[0].extract().replace(',','')
        item['read_pv']=response.selector.xpath('//strong[@class="NumberBoard-itemValue"]/text()')[1].extract().replace(',','')
        yield item

其中主要程式碼是用selectors.xpath選取我們需要的問題資訊(注意:這裡的路徑並不一定與 chrome的debug模式中複製的xpath一致,直接複製的xpath一般不太能用,自己看html程式碼結構寫的),
獲取到問題的資訊之後放到item.py中定義好的QuestionItem物件中,然後yield 物件 , 會把物件傳遞到配置的pipelines中.
pipelines一般是在配置檔案中配置,
因為這裡爬取問題只儲存到mysql資料庫,並不下載圖片,(而爬取答案需要下載圖片)所以各自在在爬蟲程式中定義的pipelines,如下:

 custom_settings = { 
        'ITEM_PIPELINES' : { 
         'zhihu.mysqlpipelines.MysqlPipeline': 5
         #'scrapy.pipelines.images.ImagesPipeline': 1,#這個是scrapy自帶的圖片下載pipelines
        }   
    }   

以上是爬取知乎問題的整個大致過程.
後文介紹爬取收藏夾下的回答 和 問題下的回答(包括內容和圖片).