Scrapy教程--部落格園前3000名文章列表抓取,scrapy3000名
一、前3000名人員列表頁
1)進入首頁,找到部落格園積分列表。如:然後我們就找到前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跟著變動就可以了。
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就可以了。
三、資料存放區MongoDB
這一部分沒什麼難的。記著安裝pymongo,pip install pymongo。總共有80+萬篇文章。
from cnblogs.items import CnblogsItemimport pymongoclass 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
四、代理及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秒一個。
# coding=utf-8import sysimport jiebafrom wordcloud import WordCloudimport pymongoimport threadingfrom Queue import Queueimport datetimeimport osreload(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