目录
一、框架介绍
Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。
scrapy框架的工作流程如下流程图
- Scrapy Engine(引擎):负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
- Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
- Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。
- Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)。
- Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
- Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件。
- Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件。
以上内容来自百度搜索引擎,纯属为了扩展自己的知识面,没有故意侵权的想法
二、安装步骤
在terminal执行以下命令安装或者在pycharm的下载第三方模块的位置搜索安装也可以的,甚至可以源码安装
pip3.8 install scrapy
Mac或Linux系统直接执行以上命令就顺利安装,但是Windows有时会出现安装失败的情况,这时候,我可以以下步骤针对性的解决问题即可
第一步:pip3 install wheel #安装后,便支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
第二步:pip3 install lxml
第三步:pip3 install pyopenssl
第四步:下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
第五步:下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
第六步:执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl
第七步:pip3 install scrapy
三、创建项目
pycharm不支持在它可视化界面创建scrapy但是我们有cmd终端,我们在终端用命令创建项目再用pycharm打开即可
scrapy startproject myfirstscrapy # 第一步:创建项目 等同于 创建Django
cd myfirstscrapy # 第二步:CD到scrapy项目路径
scrapy genspider cnblogs www.cnblogs.com # 创建爬虫 等同于 创建app
在D盘根目录下就会有咱刚刚创建的scrapy项目咯
创建好了的项目可以在pycharm里打开进行开发
项目创建成功之后,命令方式运行
scrapy crawl cnblogs
用绿色三角形点击运行的话先建run.py 文件
然后呢,在该文件里写如下代码
from scrapy.cmdline import execute
execute(['scrapy', 'crawl', 'cnblogs','--nolog']) # --nolog指的是不输出日志
四、项目目录结构
五、项目配置
1. 基本配置
#项目名字,整个爬虫名字
BOT_NAME = "firstscrapy"
# 爬虫存放位置
SPIDER_MODULES = ["firstscrapy.spiders"]
NEWSPIDER_MODULE = "firstscrapy.spiders"
# 是否遵循爬虫协议,一般都设为False
ROBOTSTXT_OBEY = False
# 用户代理
USER_AGENT = "firstscrapy (+http://www.yourdomain.com)"
# 日志输出级别(当前是只输出报错信息)
LOG_LEVEL='ERROR'
# 默认请求头
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
}
# 爬虫中间件
SPIDER_MIDDLEWARES = {
'cnblogs.middlewares.CnblogsSpiderMiddleware': 543,
}
# 下载中间件
DOWNLOADER_MIDDLEWARES = {
'cnblogs.middlewares.CnblogsDownloaderMiddleware': 543,
}
# 持久化配置
ITEM_PIPELINES = {
'cnblogs.pipelines.CnblogsPipeline': 300,
}
2. 提高爬虫效率的配置
#1 增加并发:默认16
默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改
CONCURRENT_REQUESTS = 100
值为100,并发设置成了为100。
#2 降低日志级别:
在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:
LOG_LEVEL = 'INFO'
# 3 禁止cookie:
如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:
COOKIES_ENABLED = False
# 4 禁止重试:
对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:
RETRY_ENABLED = False
# 5 减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:
DOWNLOAD_TIMEOUT = 10 超时时间为10s
六、解析数据
1. 解析方法
# response对象有css方法和xpath方法
css中写css选择器
xpath中写xpath选择
xpath取文本内容
'.//a[contains(@class,"link-title")]/text()'
xpath取属性
'.//a[contains(@class,"link-title")]/@href'
css取文本
'a.link-title::text'
css取属性
'img.image-scale::attr(src)'
.extract_first() 取一个
.extract() 取所有
2. 解析案例
用xpath解析cnblogs
import scrapy
class CnblogsSpider(scrapy.Spider):
name = "cnblogs"
allowed_domains = ["www.cnblogs.com"]
start_urls = ["https://www.cnblogs.com/"]
def parse(self, response):
"""css解析"""
article_list = response.xpath('//*[@id="post_list"]/article')
for article in article_list:
title = article.xpath('.//div/a/text()').extract_first()
author_img = article.xpath('.//div//img/@src').extract_first()
author_name = article.xpath('.//footer//span/text()').extract_first()
desc_old = article.xpath('.//p/text()').extract()
desc = desc_old[0].replace('\n', '').replace(' ', '')
if not desc:
desc = desc_old[1].replace('\n', '').replace(' ', '')
url = article.xpath('.//div/a/@href').extract_first()
info_demo = """
1.文章题目:%s
2.作者头像:%s
3.作者姓名:%s
4.文章简介:%s
5.文章地址:%s
"""
print(info_demo % (title, author_img, author_name,desc,url))
用css选择器解析cnblogs
import scrapy
class CnblogsSpider(scrapy.Spider):
name = "cnblogs"
allowed_domains = ["www.cnblogs.com"]
start_urls = ["https://www.cnblogs.com/"]
def parse(self, response):
"""css解析"""
article_list = response.css('article.post-item')
for article in article_list:
title = article.css('div.post-item-text>a::text').extract_first()
author_img = article.css('div.post-item-text img::attr(src)').extract_first()
author_name = article.css('footer span::text').extract_first()
desc_old = article.css('p.post-item-summary::text').extract()
desc = desc_old[0].replace('\n', '').replace(' ', '')
if not desc:
desc = desc_old[1].replace('\n', '').replace(' ', '')
url = article.css('div.post-item-text>a::attr(href)').extract_first()
info_demo = """
1.文章题目:%s
2.作者头像:%s
3.作者姓名:%s
4.文章简介:%s
5.文章地址:%s
"""
print(info_demo % (title, author_img, author_name,desc,url))
七、持久化方案
- items.py 写类
- 爬虫中,实例化得到对象(必须放在for内部),放到对象中数据,yield item对象
- pipline中写 类中3个方法
open_spider :打开资源
close_spider:关闭资源
process_item
- 配置文件中配置
第一步:在items.py中写一个类
import scrapy
class MyfirstscrapyItem(scrapy.Item):
title = scrapy.Field()
author_img = scrapy.Field()
author_name = scrapy.Field()
desc = scrapy.Field()
url = scrapy.Field()
content = scrapy.Field()
第二步:在piplines.py中写代码,写一个类:open_spide,close_spider,process_item
- open_spider:开启爬虫会触发
- close_spider:爬完会触发
- process_item:每次要保存一个对象会触发
import pymysql
class MyfirstscrapyMySqlPipeline:
def open_spider(self, spider):
self.conn = pymysql.connect(
user='root',
password="mire123",
host='127.0.0.1',
database='cnblogs',
port=3306,
)
self.cursor = self.conn.cursor()
def close_spider(self, spider):
self.cursor.close()
self.conn.close()
def process_item(self, item, spider): # article
sql = '''INSERT INTO article (title,author_img,author_name,`desc`,url,content) VALUES(%s,%s,%s,%s,%s,%s);'''
self.cursor.execute(sql,
args=[item['title'], item['author_img'], item['author_name'], item['desc'], item['url'],
item['content']
])
self.conn.commit()
return item
第三步:配置文件配置
ITEM_PIPELINES = {
"myfirstscrapy.pipelines.MyfirstscrapyMySqlPipeline": 300, # 数字越小优先级越大
}
第四步:在解析方法parse中yield item对象
import scrapy
from myfirstscrapy.items import MyfirstscrapyItem
from scrapy.http.request import Request
class CnblogsSpider(scrapy.Spider):
name = "cnblogs"
allowed_domains = ["www.cnblogs.com"]
start_urls = ["https://www.cnblogs.com/"]
# 解析出下一页地址,继续爬取
def parse(self, response):
article_list = response.xpath('//*[@id="post_list"]/article')
for article in article_list:
item = MyfirstscrapyItem()
title = article.xpath('.//div/a/text()').extract_first()
item['title'] = title
author_img = article.xpath('.//div//img/@src').extract_first()
item['author_img'] = author_img
author_name = article.xpath('.//footer//span/text()').extract_first()
item['author_name'] = author_name
desc_old = article.xpath('.//p/text()').extract()
desc = desc_old[0].replace('\n', '').replace(' ', '')
if not desc:
desc = desc_old[1].replace('\n', '').replace(' ', '')
item['desc'] = desc
url = article.xpath('.//div/a/@href').extract_first()
item['url'] = url
yield Request(url=url, callback=self.parser_detail, meta={'item': item}) # 爬完后执行的解析方法
next = 'https://www.cnblogs.com' + response.css('div.pager>a:last-child::attr(href)').extract_first()
yield Request(url=next, callback=self.parse)
# 解析详情的方法
def parser_detail(self, response):
content = response.css('#cnblogs_post_body').extract_first()
item = response.meta.get('item')
if content:
item['content'] = content
else:
item['content'] = '没查到'
yield item
八、在scrapy框架加proxy、cookie、header、selenium
1. 加proxy
2. 加cookie
3. 加header
4. 加selenium
标签:cnblogs,框架,author,item,scrapy,article,desc
From: https://www.cnblogs.com/almira998/p/17255470.html