一、 安装Scrapy库遇到的问题
使用pip安装,出现找不到安装包的问题,可能是国内网络的问题,使用国内镜像源加速成
pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
三、scrapy简单使用
scrapy startproject 项目名
注意
①此时会在当前路径中创建一个爬虫文件夹
②爬虫文件spiders中的只有init.py一个文件
cd 爬虫文件夹
scrapy genspider baidu baidu.com
baidu:爬虫名
baidu.com:爬虫的域名
注:
①此时爬虫文件夹中的spiders文件夹会自动创建爬虫的py文件,文件名为创建爬虫时的名字
②可同时在一个爬虫项目中创建多个爬虫文件,而这些爬虫文件全部存在于spiders文件夹中
③parse函数中的response是start_url请求的响应,类型是一个对象。
3. 提取数据
完善spider,使用xpath等方法
# -*- coding: utf-8 -*-
import scrapy
class BaiduSpider(scrapy.Spider):
name = 'baidu' # 爬虫名
allowed_domains = ['baidu.com'] # 允许爬虫的范围
start_urls = ['https://www.baidu.com'] # 最开始的url地址--根据自己需求可自行更改
def parse(self, response):
'''处理start_urls对应的响应(提取数据)'''
print(type(response))
item = response.xpath('//a[@id="s-top-username"]/span[starts-with(@class,"user-name")]/text()') # 返回特殊类型的列表,没有爬取到元素则返回空列表
print(item)
yield item
注:
①处理响应数据时的函数名必须是parse,不可更改
②使用yield生成器将提取到的数据item传递给pipelines
③运行爬虫
scrapy crawl 爬虫名
在创建的爬虫项目文件夹路径下运行程序
③设置日志等级
不设置日志等级时
开启pipeline服务
注:
①pipeline可以处理多个数值(多个类),拥有多个管道,处理数据前需要开启的所有要处理数据的pipeline类,并指定具体的距离大小。
②后面的数值越小,表示距离搜索引擎越近,数据越早被处理
③开启pipeline服务中的键实际上是pipelines中FirstscrapyPipeline类对应的位置
处理数据
class FirstscrapyPipeline(object):
def process_item(self, item, spider):
print(item)
return item
注:
①管道中的item数据就是spiders/baidu.py中从响应中提取到的数据并传递到process_item中
②pipelines中的函数名process_item不可修改,否则接收不到爬虫文件传递过来的数据
四、scrapy项目文件目录
五、logging模块输入日志
作用:代替print输出,可查看具体哪个文件的输出,并可将日志文件保存到本地
1.输出到界面
爬虫文件baidu.py
import scrapy
import logging
logger = logging.getLogger(__name__)
class BaiduSpider(scrapy.Spider):
name = 'baidu' # 爬虫名
allowed_domains = ['baidu.com'] # 允许爬虫的范围
start_urls = ['https://www.baidu.com'] # 最开始的url地址--根据自己需求可自行更改
def parse(self, response):
'''处理start_urls对应的响应(提取数据)'''
for i in range(10):
item = {}
item['hello'] = 'spider'
logger.warning(item)
yield item
管道文件pipelines.py
import logging
logger = logging.getLogger(__name__)
class FirstscrapyPipeline(object):
def process_item(self, item, spider):
if spider.name == 'baidu':
logger.warning('*'*20)
return item
运行结果
2.输出到日志文件
setting文件中添加
运行结果(自动创建日志文件并写入内容)
六、下一页请求(scrapy.Request构造请求)
next_url = response.xpath(…) # 提取下一页的url地址 yield scrapy Request(
next_url,
callback=self.parse )
案例:爬取网易云华语歌单
1.创建爬虫项目
2.创建爬虫文件
3.cloundmusic爬虫文件
import scrapy
class CloudmusicSpider(scrapy.Spider):
name = 'cloudmusic'
allowed_domains = ['music.163.com'] # 不能设置为music.163--这样只能爬取第一页
start_urls = ['https://music.163.com/discover/playlist/?cat=%E5%8D%8E%E8%AF%AD']
def parse(self, response):
li_list = response.xpath("//ul[@id='m-pl-container']/li")
for li in li_list:
item = {}
item['title'] = li.xpath("./p[1]/a/text()").extract_first()
item['author'] = li.xpath("./p[2]/a/text()").extract_first()
item['num'] = li.xpath(".//div[@class='bottom']/span[2]/text()").extract_first()
yield item # 传递数据
# 下一页请求(构建request请求对象)
next_url = response.xpath("//div[@id='m-pl-pager']/div/a[last()]/@href").extract_first()
if next_url != 'javascript:void(0)':
next_url = 'https://music.163.com/' + next_url
print(next_url)
yield scrapy.Request(
next_url,
callback=self.parse
)
4.pipelines管道文件
class MusicPipeline(object):
def process_item(self, item, spider):
print(item)
return item
5.setting文件设置
请求头设置
6.运行程序
截取最后一部分
注:
①创建爬虫文件时设置的域名问题
将容许域名和自己需要爬虫的base_url设置一样,否则可能只爬到第一页数据(start_url不会被过滤),其他的next_url可能会被过滤(eg:allowed_domains = [‘music.163’])
②response.xpath(…)返回一个列表类型。response.xpath(…).extract_first()则取列表第一个元素,如果为空列表时,返回None值
七、scrapy之items文件介绍
作用:
①提前定义爬取内容的字段
②可使用不同的item(不同类)存放不同的字段
③在pipelines中,可通过isinstance(item,items中的类名)判断具体的数据并处理
案例:爬取阳光政府内容
1.创建项目文件
2.创建爬虫文件
3.编写items文件–确定需要爬取的字段
import scrapy
class YangguangItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field()
publish_data = scrapy.Field()
content_img = scrapy.Field()
content_text = scrapy.Field()
4.编写爬虫文件
import scrapy
from yangguang.items import YangguangItem
class YgSpider(scrapy.Spider):
name = 'yg'
allowed_domains = ['wz.sun0769.com']
start_urls = ['http://wz.sun0769.com/political/index/politicsNewest']
def parse(self, response):
item = YangguangItem()
li_list = response.xpath("//ul[@class='title-state-ul']/li")
for li in li_list:
item['title'] = li.xpath("./span[3]/a/text()").extract_first()
item['href'] = li.xpath("./span[3]/a/@href").extract_first()
item['href'] = 'http://wz.sun0769.com' + item['href']
# 获取详情页内容
yield scrapy.Request(
item['href'],
callback = self.parse_detail,
meta={'item':item}
)
#获取下一页内容
next_url = response.xpath("//div[@class='mr-three paging-box']/a[2]/@href").extract_first()
next_url = 'http://wz.sun0769.com' + next_url
yield scrapy.Request(
next_url,
callback=self.parse,
meta={'item': item}
)
def parse_detail(self,response): # 此时的response是item['href']请求的响应
item = response.meta['item']
item['content_text'] = response.xpath("//div[@class='mr-three']/div[2]/pre/text()").extract_first()
item['content_img'] = response.xpath("//div[@class='mr-three']/div[3]/img/@src").extract_first()
yield item # 传递item
5.编写pipelines管道文件(可以将爬取到的内容写入mongdb数据库)
class YangguangPipeline(object):
def process_item(self, item, spider):
print(item)
return item
6.设置setting文件
只截取其中一部分
注
scrapy.Request()中的meta参数可实现数据在不同解析函数之间的传递
八、pipeline管道之open、close函数
open_spider(self,spider)函数在爬虫开启时执行且仅执行一次,
close_spider(self,spider)函数在爬虫关闭时执行且仅执行一次
注:一般用于连接数据库和关闭数据库的操作