本次將從stack overflow網站上爬取一些信息。
先來看一下網站的python頁面(https://stackoverflow.com/questions/tagged/python)
待爬數據.png
這個頁面中包含了今天要爬取的所有信息,主要有:
<question,asker,answers_num, votes, views, tags, post_dates, brief>
讓我們開始吧。
在shell中使用Selectors
為了方便起見,我將網頁的html代碼放到一個本地文件里,取名為tagged-python.html。可以先在scrappy shell中練習下XPath的用法。
使用如下命令進入大shell界面:
scrapy shell './tagged-python.html'
進入shell后我們可以使用response進行相關操作。利用response.text查看下是否載入正確。核實好后就可以開始我們的信息選取工作了。
先分析下頁面html,利用瀏覽器自帶的檢查功能(右鍵,檢查),我們可以看到如下界面:
子模塊.png
這里面包含了所有需要的數據。讓我們對照這個列表逐一提取吧。
獲取擁有本頁所有問題的子模塊,在此基礎上逐步獲取我們所需的信息。
xpath可以為: //*[@id="questions"]
questions = response.xpath("http://*[@id='questions']")
為了加快查找速度,我們其實可以借助于瀏覽器自帶的xpath功能。
copy_xpath.png
點擊Copy XPath,顯示如下:
//*[@id="questions"]
獲取問題title
使用命令行
titles = questions.xpath("http://*[@class='question-summary']/div[2]/h3/a/text()").extract()
我們得到一個list,如下:
In [15]: titles
Out[15]:
[u'\u201cLeast Astonishment\u201d and the Mutable Default Argument',
u'How do I test multiple variables against a value?',
u"Understanding Python's slice notation",
u'Asking the user for input until they give a valid response',
u'How to clone or copy a list?',
u'List of lists changes reflected across sublists unexpectedly',
u'How do you split a list into evenly sized chunks?',
u'How do I pass a variable by reference?',
u'How do I create a variable number of variables?',
u'Remove items from a list while iterating',
u'Making a flat list out of list of lists in Python',
u'What does the \u201cyield\u201d keyword do?',
u'How can I read inputs as integers?',
u'What does ** (double star/asterisk) and * (star/asterisk) do for parameters?',
u'Short Description of the Scoping Rules?']
包含了所有的titles信息。
獲取其它信息
其它的與此類似,在此就不一一展開了。直接給出代碼:
titles = questions.xpath("http://*[@class='question-summary']/div[2]/h3/a/text()").extract()
askers = questions.xpath("http://*[@class='question-summary']/div[2]/div[3]/div/div[3]/a/text()").extract()
answers_nums = questions.xpath("http://*[@class='question-summary']/div[1]/div[2]/div[2]/strong/text()").extract()
votes = questions.xpath("http://*[@class='question-summary']/div[1]/div[2]/div[1]/div/span/strong/text()").extract()
views = questions.xpath("http://*[@class='question-summary']/div[1]/div[3]/text()").extract()
tags = questions.xpath("http://*[@class='question-summary']/div[2]/div[2]/a[@class='post-tag']/text()").extract()
post_dates = questions.xpath("http://*[@class='question-summary']/div[2]/div[3]/div/div[1]/span/text()").extract()
briefs = questions.xpath("http://*[@class='question-summary']/div[2]/div[1]/text()").extract()
其中需要注意的是tags項,由于一個問題存在多個tag,如果用上面的代碼實現對tag進行抓取,就沒辦法區分tag與問題的聯系。可以改為:
questions = response.xpath("http://*[@class='question-summary']")
tags = []
for question in questions:
tag = question.xpath("./div[2]/div[2]/a/text()").extract()
tags.append(tag)
views = [v.strip() for v in views]
post_dates = [p.strip() for p in post_dates]
創建project,保存數據到json文件
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from scrapy import Spider
class stackoverflow(Spider):
name = 'stackoverflow'
start_urls = [
'https://stackoverflow.com/questions/tagged/python'
]
def parse(self, response):
questions = response.xpath("http://*[@class='question-summary']")
for question in questions:
yield {
'titles': question.xpath("./div[2]/h3/a/text()").extract(),
'askers': question.xpath("./div[2]/div[3]/div/div[3]/a/text()").extract(),
'answers_nums': question.xpath("./div[1]/div[2]/div[2]/strong/text()").extract(),
'votes': question.xpath("./div[1]/div[2]/div[1]/div/span/strong/text()").extract(),
'views': question.xpath("./div[1]/div[3]/text()").extract(),
'tags': question.xpath("./div[2]/div[2]/a[@class='post-tag']/text()").extract(),
'post_dates': question.xpath("./div[2]/div[3]/div/div[1]/span/text()").extract(),
'briefs': question.xpath("./div[2]/div[1]/text()").extract(),
}