Scrapy教程——博客園前3000名文章列表抓取

Scrapy 文章 Word 鏡音雙子 達人科技 2017-06-14

一、前3000名人員列表頁

1)進入首頁,找到博客園積分列表。如下圖:然後我們就找到前3000名大神的博客地址了。通過,詞雲分析了下,好多大神的博客都遷移到個人博客上了。

Scrapy教程——博客園前3000名文章列表抓取Scrapy教程——博客園前3000名文章列表抓取

2)分析頁面結構:每一個td都是,一個人員。

第一個small為排名

第二個a標籤是暱稱和用戶名,以及首頁的博客地址。用戶名通過地址截取獲取

第四個small標籤是,博客數量以及積分,通過字符串分離後可以逐個獲取到。

3)代碼:使用xpath獲取標籤及相關的內容,獲取到首頁博客地址後,發送請求。

def parse(self, response):
        for i in response.xpath("//table[@width='90%']//td"):
 top = i.xpath(
 "./small[1]/text").extract[0].split('.')[-2].strip
 nickName = i.xpath("./a[1]//text").extract[0].strip
 userName = i.xpath(
 "./a[1]/@href").extract[0].split('/')[-2].strip
 totalAndScore = i.xpath(
 "./small[2]//text").extract[0].lstrip('(').rstrip(')').split(',')
 total = totalAndScore[0].strip
 score = totalAndScore[2].strip
# print(top)
# print(nickName)
# print(userName)
# print(total)
# print(score)
# return
 yield scrapy.Request(i.xpath("./a[1]/@href").extract[0], meta={'page': 1, 'top': top, 'nickName': nickName, 'userName': userName, 'score': score},
 callback=self.parse_page)

二、各人員博客列表頁

1)頁面結構:通過分析,每篇博客的a標籤id中都包含“TitleUrl”,這樣就可以獲取到每篇博客的地址了。每頁面地址,加上default.html?page=2,page跟著變動就可以了。

Scrapy教程——博客園前3000名文章列表抓取

2)代碼:置頂的文字會去除掉。

def parse_page(self, response):
        #         print(response.meta['nickName'])
        #//a[contains(@id,'TitleUrl')]
        urlArr = response.url.split('default.aspx?')
        if len(urlArr) > 1:
 baseUrl = urlArr[-2]
        else:
 baseUrl = response.url
        list = response.xpath("//a[contains(@id,'TitleUrl')]")
        for i in list:
 item = CnblogsItem
 item['top'] = int(response.meta['top'])
 item['nickName'] = response.meta['nickName']
 item['userName'] = response.meta['userName']
 item['score'] = int(response.meta['score'])
 item['pageLink'] = response.url
 item['title'] = i.xpath(
 "./text").extract[0].replace(u'[置頂]', '').strip
 item['articleLink'] = i.xpath("./@href").extract[0]
 yield item
        if len(list) > 0:
 response.meta['page'] += 1
 yield scrapy.Request(baseUrl + 'default.aspx?page=' + str(response.meta['page']), meta={'page': response.meta['page'], 'top': response.meta['top'], 'nickName': response.meta['nickName'], 'userName': response.meta['userName'],  'score': response.meta['score']}, callback=self.parse_page)

3)對於每篇博客的內容,這裡沒有抓取。也很簡單,分析頁面。繼續發送請求,找到id為cnblogs_post_body的div就可以了。

Scrapy教程——博客園前3000名文章列表抓取

三、數據存儲MongoDB

這一部分沒什麼難的。記著安裝pymongo,pip install pymongo。總共有80+萬篇文章。

from cnblogs.items import CnblogsItem
import pymongo


class CnblogsPipeline(object):

    def __init__(self):
        client = pymongo.MongoClient(host='127.0.0.1', port=27017)
        dbName = client['cnblogs']
        self.table = dbName['articles']
        self.table.create

    def process_item(self, item, spider):
        if isinstance(item, CnblogsItem):
 self.table.insert(dict(item))
 return item
Scrapy教程——博客園前3000名文章列表抓取

四、代理及Model類

scrapy中的代理,很簡單,自定義一個下載中間件,指定一下代理ip和端口就可以了。

def process_request(self, request, spider):
        request.meta['proxy'] = 'http://117.143.109.173:80'

Model類,存放的是對應的字段。

class CnblogsItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field
    # 排名
    top = scrapy.Field
    nickName = scrapy.Field
    userName = scrapy.Field
    # 積分
    score = scrapy.Field
    # 所在頁碼地址
    pageLink = scrapy.Field
    # 文章標題
    title = scrapy.Field
    # 文章鏈接
    articleLink = scrapy.Field

五、wordcloud詞雲分析

對每個人的文章進行詞雲分析,存儲為圖片。wordcloud的使用用,可參考園內文章。

這裡用了多線程,一個線程用來生成分詞好的txt文本,一個線程用來生成詞雲圖片。生成詞雲大概,1秒一個。

Scrapy教程——博客園前3000名文章列表抓取
# coding=utf-8
import sys
import jieba
from wordcloud import WordCloud
import pymongo
import threading
from Queue import Queue
import datetime
import os
reload(sys)
sys.setdefaultencoding('utf-8')


class MyThread(threading.Thread):

    def __init__(self, func, args):
        threading.Thread.__init__(self)
        self.func = func
        self.args = args

    def run(self):
        apply(self.func, self.args)
# 獲取內容 線程


def getTitle(queue, table):
    for j in range(1, 3001):
        #         start = datetime.datetime.now
        list = table.find({'top': j}, {'title': 1, 'top': 1, 'nickName': 1})
        if list.count == 0:
 continue
        txt = ''
        for i in list:
 txt += str(i['title']) + '\n'
 name = i['nickName']
 top = i['top']
        txt = ' '.join(jieba.cut(txt))
        queue.put((txt, name, top), 1)
#         print((datetime.datetime.now - start).seconds)


def getImg(queue, word):
    for i in range(1, 3001):
        #         start = datetime.datetime.now
        get = queue.get(1)
        word.generate(get[0])
        name = get[1].replace('<', '').replace('>', '').replace('/', '').replace('\\', '').replace(
 '|', '').replace(':', '').replace('"', '').replace('*', '').replace('?', '')
        word.to_file(
 'wordcloudimgs/' + str(get[2]) + '-' + str(name).decode('utf-8') + '.jpg')
        print(str(get[1]).decode('utf-8') + '\t生成成功')
#         print((datetime.datetime.now - start).seconds)


def main:
    client = pymongo.MongoClient(host='127.0.0.1', port=27017)
    dbName = client['cnblogs']
    table = dbName['articles']
    wc = WordCloud(
        font_path='msyh.ttc', background_color='#ccc', width=600, height=600)
    if not os.path.exists('wordcloudimgs'):
        os.mkdir('wordcloudimgs')
    threads = 
    queue = Queue
    titleThread = MyThread(getTitle, (queue, table))
    imgThread = MyThread(getImg, (queue, wc))
    threads.append(imgThread)
    threads.append(titleThread)

    for t in threads:
        t.start
    for t in threads:
        t.join

if __name__ == "__main__":
    main

六、完整源碼地址

https://github.com/hao15239129517/cnblogs

相關推薦

推薦中...