书写爬虫文件------(三)

创建爬虫文件:

  scrapy genspider sina_spider "sina.com.cn"

书写爬虫文件:

  1 import scrapy
  2 import os
  3 from Sina.items import SinaItem
  4 from scrapy_redis.spiders import RedisSpider
  5 
  6 
  7 class SinaSpiderSpider(RedisSpider):
  8     name = 'sina_spider'
  9     allowed_domains = ['sina.com.cn']
 10     # start_urls = ['http://sina.com.cn/']
 11     redis_key = "Sina:start_urls"
 12 
 13     def parse(self, response):
 14         # 创建一个items接收item数据
 15         items = []
 16 
 17         # 所有大类链接和标题
 18         parent_urls = response.xpath('//*[@id="tab01"]/div/h3/a/@href').extract()
 19         parent_title = response.xpath('//*[@id="tab01"]/div/h3/a/text()').extract()
 20 
 21         # 所有小类链接和标题
 22         sub_urls = response.xpath('//*[@id="tab01"]/div[position()<20]/ul/li/a/@href').extract()
 23         sub_title = response.xpath('//*[@id="tab01"]/div[position()<20]/ul/li/a/text()').extract()
 24 
 25         # 爬取所有的大类
 26         for i in range(0, len(parent_title)):
 27             # 指定大类的目录和文件夹名字
 28             parent_filename = "./Data/" + parent_title[i]
 29             # 如果没有这个文件夹则创建
 30             if not os.path.exists(parent_filename):
 31                 os.makedirs(parent_filename)
 32             # 爬取所有小类
 33             for j in range(0, len(sub_title)):
 34                 item = SinaItem()
 35                 item['parent_title'] = parent_title[i]
 36                 item['parent_urls'] = parent_urls[i]
 37 
 38                 # 检查小类的url是否以同类别大类url开头,如果是返回True (sports.sina.com.cn 和 sports.sina.com.cn/nba)
 39                 if_belong = sub_urls[j].startswith(item['parent_urls'])
 40 
 41                 if if_belong:
 42                     sub_filename = parent_filename + '/' + sub_title[j]
 43                     # 如果目录不存在,则创建目录
 44                     if not os.path.exists(sub_filename):
 45                         os.makedirs(sub_filename)
 46 
 47                     # 存储 小类url、title和filename字段数据
 48                     item['sub_urls'] = sub_urls[j]
 49                     item['sub_title'] = sub_title[j]
 50                     item['sub_filename'] = sub_filename
 51 
 52                     items.append(item)
 53 
 54         # 发送每个小类url的Request请求,得到Response连同包含meta数据 一同交给回调函数 second_parse 方法处理
 55         for item in items:
 56             yield scrapy.Request(url=item['sub_urls'], meta={'meta_1': item}, callback=self.second_parse)
 57 
 58     def second_parse(self, response):
 59         # 提取每次Response的meta数据
 60         meta_1 = response.meta['meta_1']
 61 
 62         # 取出小类里所有子链接
 63         son_urls = response.xpath('//a/@href').extract()
 64 
 65         items = []
 66         for i in range(0, len(son_urls)):
 67             # 检查每个链接是否以大类url开头、以.shtml结尾,如果是返回True
 68             if_belong = son_urls[i].endswith('.shtml') and son_urls[i].startswith(meta_1['parent_urls'])
 69 
 70             # 如果属于本大类,获取字段值放在同一个item下便于传输
 71             if if_belong:
 72                 item = SinaItem()
 73                 item['parent_title'] = meta_1['parent_title']
 74                 item['parent_urls'] = meta_1['parent_urls']
 75                 item['sub_urls'] = meta_1['sub_urls']
 76                 item['sub_title'] = meta_1['sub_title']
 77                 item['sub_filename'] = meta_1['sub_filename']
 78                 item['son_urls'] = son_urls[i]
 79                 items.append(item)
 80 
 81         # 发送每个小类下子链接url的Request请求,得到Response后连同包含meta数据 一同交给回调函数 detail_parse 方法处理
 82         for item in items:
 83             yield scrapy.Request(url=item['son_urls'], meta={'meta_2': item}, callback=self.detail_parse)
 84 
 85     def detail_parse(self, response):
 86         item = response.meta['meta_2']
 87 
 88         xpath_1 = '//div[@id="article"]/p/text() | //div[@id="artibody"]/p/text()'
 89         xpath_2 = '//*[@id="artibody"]/div//text() | //div[@class="ts-d-question"]//text()'
 90         try:
 91             content_1 = "".join(response.xpath(xpath_1).extract())
 92         except IndexError:
 93             content_1 = "".join(response.xpath(xpath_2).extract())
 94         except Exception as e:
 95             print(e)
 96             return
 97 
 98         item['head'] = item['sub_title']
 99         item['content'] = content_1
100 
101         yield item

 

  我们这里是用的redis数据库保存数据,你可以把数据转到其他数据库,也可以将数据写到建立的文件夹下,这里只是演示分布式

爬虫,所以并没有将数据保存到相应的文件夹。

 

posted @ 2018-06-05 23:54  巴蜀秀才  阅读(289)  评论(0编辑  收藏  举报