您好,欢迎访问一九零五行业门户网

Scrapy教程--某网站前N篇文章抓取

一、前3000名人员列表页
 2)分析页面结构:每一个td都是,一个人员。
第一个small为排名
第二个a标签是昵称和用户名,以及首页的博客地址。用户名通过地址截取获取
第四个small标签是,博客数量以及积分,通过字符串分离后可以逐个获取到。
3)代码:使用xpath获取标签及相关的内容,获取到首页博客地址后,发送请求。
def parse(self, response):
       for i in response.xpath(//table[@width='90%']//td):
           item = cnblogsitem()
           item['top'] = i.xpath(
               ./small[1]/text()).extract()[0].split('.')[-2].strip()
           item['nickname'] = i.xpath(./a[1]//text()).extract()[0].strip()
           item['username'] = i.xpath(
               ./a[1]/@href).extract()[0].split('/')[-2].strip()
           totalandscore = i.xpath(
               ./small[2]//text()).extract()[0].lstrip('(').rstrip(')').split(',')
           item['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, 'item': item},
                                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['item']['top'])
           item['nickname'] = response.meta['item']['nickname']
           item['username'] = response.meta['item']['username']
           item['score'] = int(response.meta['item']['score'])
           item['pagelink'] = response.url
           item['title'] = i.xpath(
               ./text()).extract()[0].replace(u'[置顶]', '').replace('[top]', '').strip()
           item['articlelink'] = i.xpath(./@href).extract()[0]
           yield scrapy.request(i.xpath(./@href).extract()[0], meta={'item': item}, callback=self.parse_content)
       if len(list) > 0:
           response.meta['page'] += 1
           yield scrapy.request(baseurl + 'default.aspx?page=' + str(response.meta['page']), meta={'page': response.meta['page'], 'item': response.meta['item']}, callback=self.parse_page)
3)对于每篇博客的内容,这里没有抓取。也很简单,分析页面。继续发送请求,找到id为cnblogs_post_body的div就可以了。
def parse_content(self, response):         content = response.xpath(//div[@id='cnblogs_post_body']).extract()         item = response.meta['item']if len(content) == 0:             item['content'] = u'该文章已加密'else:             item['content'] = content[0]yield item
三、数据存储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.createdef 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()
# 文章内容
   content = scrapy.field()
五、wordcloud词云分析对每个人的文章进行词云分析,存储为图片。wordcloud的使用用,可参考园内文章。
这里用了多线程,一个线程用来生成分词好的txt文本,一个线程用来生成词云图片。生成词云大概,1秒一个。
# coding=utf-8import sysimport jiebafrom wordcloud import wordcloudimport pymongoimport threadingfrom queue import queueimport datetimeimport 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 = argsdef 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:continuetxt = ''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()
六、完整源码地址
附:mongodb内存限制windows:
以上就是scrapy教程--某网站前n篇文章抓取的详细内容。
其它类似信息

推荐信息