Python爬虫教程八:Scrapy框架(下)

一、数据清洗方式

spider代码

import scrapy

class PicspiderSpider(scrapy.Spider):
    name = 'picSpider'  # 爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字
    allowed_domains = ['loutoushe.com']   # 域名范围,也就是爬虫的约束区域
    start_urls = ['http://loutoushe.com/']   # 爬取的URL元祖/列表

    def parse(self, response):  # 这里的response携带请求返回的所有内容。得到一个包含response数据的本地 response 变量
        res=response.xpath("//title/text()").extract()
        print(res)

Scrapy自动发送请求,返回response

response.body 将输出response的包体

 response.headers 可以看到response的包头

数据清洗:

response.selector.xpath()response.xpath() 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表

response.selector.css() 或 response.css() 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表,语法同 BeautifulSoup4

extract(): 序列化该节点为字符串并返回list

re(): 根据传入的正则表达式对数据进行提取,返回字符串list列表

二、案例实战

本节,我将使用Scrapy爬取站酷数据作为示例

1.案例说明

既然已经初步了解了scrapy的工作流程以及原理,我们来做一个入门的小案例,爬取站酷首页推荐的item信息。如下图所示,一个小方框就是一个item信息。我们要提取每一个item的六个组成部分:

  1. imgLink(封面图片链接);
  2. title(标题);
  3. types(类型);
  4. vistor(人气);
  5. comment(评论数);
  6. likes(推荐人数)

然后只是一个页面的item,我们还要通过翻页实现批量数据采集。

2.文件配置

目录结构

在上一篇中我们说明了新建scrapy项目(zcool)和spider项目(zc),这里不再赘述,然后得到我们的目录结构如下图所示:

start.py文件

然后为了方便运行,在zcool目录下新建start文件。并进行初始化设置。

from scrapy import cmdlinecmdline.execute('scrapy crawl zc'.split())

settings.py文件

在这个文件里我们需要做几样设置

避免在程序运行的时候打印log日志信息

  LOG_LEVEL = 'WARNING' 
 ROBOTSTXT_OBEY = False 

添加请求头:

打开管道:

item.py文件

import scrapy
class ZcoolItem(scrapy.Item):    
# define the fields for your item here like:    
   imgLink = scrapy.Field() # 封面图片链接    
   title = scrapy.Field() # 标题    
   types = scrapy.Field() # 类型    
   vistor = scrapy.Field() # 人气    
   comment = scrapy.Field() # 评论数    
   likes = scrapy.Field() # 推荐人数

3.页面数据提取

首先我们在站酷页面使用xpath-helper测试一下:

然后zc.py文件里面初步测试一下:

def parse(self, response):    
    divList = response.xpath('//div[@class="work-list-box"]/div')    
    print(len(divList))

运行结果如下图所示:

没有问题,然后我们对各种信息分别解析提取,

def parse(self, response):    
   divList = response.xpath('//div[@class="work-list-box"]/div')    
   for div in divList:        
      imgLink = div.xpath("./div[1]/a/img/@src").extract()[0] # 1.封面图片链接  ...  2.title(标题);3 types(类型);4vistor(人气);5comment(评论数)  ....        
      likes = div.xpath("./div[2]/p[3]/span[3]/@title").extract_first() # 6likes(推荐人数)        
      item = ZcoolItem(imgLink=imgLink,title=title,types=types,vistor=vistor,comment=comment,likes=likes)        
      yield item

解释: xpath提取数据方法:

S.N.方法 & 描述
extract()返回的是符合要求的所有的数据,存在一个列表里。
extract_first()返回的hrefs 列表里的第一个数据。
get()和extract_first()方法返回的是一样的,都是列表里的第一个数据。
getall()和extract()方法一样,返回的都是符合要求的所有的数据,存在一个列表里。

注意:

get() 、getall() 方法是新的方法,extract() 、extract_first()方法是旧的方法。extract() 、extract_first()方法取不到就返回None。get() 、getall() 方法取不到就raise一个错误。

item实例创建(yield上面一行代码)

这里我们之前在目录文件配置的item文件中已经进行了设置,对于数据存储,我们在爬虫文件中开头要导入这个类:

from zcool.items import ZcoolItem

然后使用yield返回数据。

为什么使用yield而不是return

不能使用return这个无容置疑,因为要翻页,使用return直接退出函数;而对于yield:在调用for的时候,函数内部不会立即执行,只是返回了一个生成器对象。在迭代的时候函数会开始执行,当在yield的时候,会返回当前值(i)。之后的这个函数会在循环中进行,直到没有下一个值。

4.翻页实现批量数据采集

通过上面的代码已经可以初步实现数据采集,只不过只有第一页的,如下图所示:

但是我们的目标是100个页面的批量数据采集,所以代码还需要修改。针对翻页这里介绍两种方式:

方式一:我们首先在页面中定位到下一页的按钮,如下图所示:

然后编写如下代码,在for循环完毕后。

next_href = response.xpath("//a[@class='laypage_next']/@href").extract_first()c
if next_href:   
   next_url = response.urljoin(next_href)    
   print('*' * 60)    
   print(next_url)    
   print('*' * 60)    
   request = scrapy.Request(next_url)    
   yield request

scrapy.Request(): 把下一页的url传递给Request函数,进行翻页循环数据采集。

https://www.cnblogs.com/heymonkey/p/11818495.html # scrapy.Request()参考链接

注意方式一只有下一页按钮它的href对应属性值和下一页的url一致才行。

方式二:定义一个全局变量count = 0,每爬取一页数据,令其加一,构建新的url,再使用scrapy.Request() 发起请求。

如下图所示:

count = 1
class ZcSpider(scrapy.Spider):    
   name = 'zc'    
   allowed_domains = ['zcool.com.cn']    
   start_urls = ['https://www.zcool.com.cn/home?p=1#tab_anchor'] # 第一页的url    

   def parse(self, response):        
      global count        
      count += 1                
      for div in divList:    
          # ...xxx...            
          yield item        
      next_url = 'https://www.kuaikanmanhua.com/tag/0?state=1&sort=1&page={}'.format(count)        
      yield scrapy.Request(next_url)

这两种方式在实际案例中择机采用。

5.数据存储

数据存储是在pipline.py中进行的,代码如下:

from itemadapter import ItemAdapter
import csv
class ZcoolPipeline:    
   def __init__(self):         
      self.f = open('Zcool.csv','w',encoding='utf-8',newline='')       # line1        
      self.file_name = ['imgLink', 'title','types','vistor','comment','likes']  # line2        
      self.writer = csv.DictWriter(self.f, fieldnames=self.file_name)     # line3        
      self.writer.writeheader()              # line4    
   def process_item(self, item, spider):         
      self.writer.writerow(dict(item))              # line5        
      print(item)        
      return item                  # line6     
   def close_spider(self,spider):        
      self.f.close()

解释:

  • line1: 打开文件,指定方式为写,利用第3个参数把csv写数据时产生的空行消除
  • line2: 设置文件第一行的字段名,注意要跟spider传过来的字典key名称相同
  • line3: 指定文件的写入方式为csv字典写入,参数1为指定具体文件,参数2为指定字段名
  • line4: 写入第一行字段名,因为只要写入一次,所以文件放在__init__里面
  • line5: 写入spider传过来的具体数值,注意在spider文件中yield的item,是一个由类创建的实例对象,我们写入数据时,写入的是 字典,所以这里还要转化一下。
  • line6: 写入完返回

6.程序运行

因为之前创建了start.py文件,并且对它就行了初始化设置,现在运行爬虫程序不需要在控制台中输入命令:

scrapy crawl zc(爬虫项目名)

直运行start.py文件:得到如下结果:

对应于页面:

打开csv文件如下图所示:(由于csv文件在word中乱码了,此处我是用Notepad++打开)

没有问题,数据采集完毕。

7.总结

入门案例,需要细心,主要是基础知识的巩固,以便于为进阶学习做好准备。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享