文章目录
*
– 1.scrapy组成
– 2.scrapy工作原理
– 3.小栗子-01
–
+ 3.1后续request
– 4.CrawlSpider
–
+ 4.1小栗子-02
– 4.数据入库
- 安装scrapy
在python文件的scripts目录下打开cmd
pip install scrapy
可能安装失败
1.scrapy是基于twisted,先下载twisted对应版本的whl文件
2.提示upgrade pip,那就python -m pip install –upgrade pip
3.或者直接安装anaconda,这是个重量级,里面啥都有,就是有点难下载
- 创建scrapy项目
1.在当前正在使用的python项目下,或者新建一个目录
2.从该目录进入cmd窗口
-创建项目:不允许数字开头,不允许包含中文及中文符号
scrapy startproject 项目名字
-创建文件:在spiders文件夹中创建爬虫文件
cd 项目名字\项目名字\spiders
scrapy genspider 爬虫文件名字 要爬取的网页(域名)
1.scrapy组成
基于Twisted的异步处理框架
- Engine:引擎;处理整个系统的数据流处理,触发事务,整个框架的核心
- Item:项目;定义爬取结果的数据结构,爬取的数据会被赋值成该item对象
- Scheduler:调度器;接受引擎发过来的请求,并将其加入队列中,在引擎再次请求的时候将请求提供给引擎
- Downloader:下载器;下载网页内容,并将网页内容返回给Spiders
- Spiders:定义爬取逻辑和网页的解析规则,主要负责解析响应并生成提取结果和新的请求
- Item Pipeline:管道;负责处理由Spiders从网页中抽取的项目,主要任务是清洗,验证和存储数据
2.scrapy工作原理
数据流:
; 3.小栗子-01
小介绍:
-name:每个项目唯一的名字,用来区分不同的Spider
-allowed_domains:允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤掉
-start_urls:包含Spider在启动时爬取的url列表,初始请求由他来定义
-parse:Spider的一个方法。默认情况下,被调用时start_urls里面的链接构成的请求完成下载执行后,返回的响应就会作为唯一的参数传递给这个函数。然后该方法解析返回的响应,提取数据或者进一步生成要处理的请求
- spider
import scrapy
from scr_piao_01.items import ScrPiao01Item
class BaiduSpider(scrapy.Spider):
name = 'baidu'
allowed_domains = ['category.dangdang.com']
start_urls = ['http://category.dangdang.com/cp01.01.08.00.00.00.html']
base_url = 'http://category.dangdang.com/pg'
page = 1
def parse(self, response):
li_lst = response.xpath('//ul[@id="component_59"]/li')
for li in li_lst:
src = li.xpath('.//img/@data-original').extract_first()
if src:
src = src
else:
src = li.xpath('.//img/@src').extract_first()
alt = li.xpath('.//img/@alt').extract_first()
price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
book = ScrPiao01Item(src=src, name=alt, price=price)
yield book
if self.page < 100:
self.page += 1
url_next = self.base_url + str(self.page)+'-cp01.01.08.00.00.00.html'
yield scrapy.Request(url=url_next, callback=self.parse)
- items
item是保存爬取的容器,它的使用方法和字典类似。多了额外的保护机制,可以避免拼写错误或者定义字段错误。
创建item需要继承scrapy.Item类。并且定义类型为scrapy.Field的字段
class ScrPiao01Item(scrapy.Item):
src = scrapy.Field()
name = scrapy.Field()
price = scrapy.Field()
- pipelines
通过管道存储数据到文件或数据库
class ScrPiao01Pipeline:
def open_spider(self, spider):
self.fp = open('book.json', 'w', encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
return item
def close_spider(self, spider):
self.fp.close()
3.1后续request
上面这个只爬取了初始页面的60条数据,对于下一页或者后面的数据怎么获取呢?
首先从当前页面中找到下一页的请求信息,然后在下一个请求的页面里找到信息再构造下下一个请求,一直迭代下去,就实现整站的爬取啦!
先瞅瞅那个每页的url
构造请求时要用到scrapy.Request
构造请求时要用到scrapy.Request,传递的参数
-url:请求链接
-callback:回调函数,当指定了该回调函数的请求完成==>获取到响应==>引擎再将该响应传递给这个回调函数
要注意allowed_domains
4.CrawlSpider
crawlspider为全站爬取而生的。CrawlSpider可以定义规则,在解析HTML内容的时候,根据规则提取指定的链接,然后再向这些链接发送请求。
- 链接提取
from scrapy.linkextractors import LinkExtractor
常用:
1.正则表达式,提取符合的链接;为空就全部匹配:allow=()
2.xpath,提取符合xpath规则的链接:restrict_xpaths=()
3.提取符合css规则的链接:restrict_css=()
其他:
4.与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取:deny=()
5.会被提取的链接的domains: allow_domains=()
6.一定不会被提取链接的domains: deny_domains=()
link01 = LinkExtractor(allow=r'**************')
link02 = LinkExtractor(restrict_xpaths=r'**************')
link02 = LinkExtractor(restrict_css=r'**************')
link.extract_links(response)
4.1小栗子-02
创建项目及文件
-scrapy startproject dushuproject
-cd dushuproject\dushuproject\spiders
-scrapy genspider -t crawl xiaoye https://www.dushu.com/book/1617.html
- spiders
这里有个不大不小的大坑~~
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from dushuproject.items import DushuprojectItem
class XiaoyeSpider(CrawlSpider):
name = 'xiaoye'
allowed_domains = ['www.dushu.com']
start_urls = ['https://www.dushu.com/book/1617.html']
rules = (
Rule(LinkExtractor(allow=r'/book/1617_\d+\.html'),
callback='parse_item',
follow=False),
)
def parse_item(self, response):
img_lst = response.xpath('//div[@class="bookslist"]//img')
for img in img_lst:
name = img.xpath('./@alt').extract_first()
src = img.xpath('./@data-original').extract_first()
book = DushuprojectItem(name=name, src=src)
yield book
- items
class DushuprojectItem(scrapy.Item):
name = scrapy.Field()
src = scrapy.Field()
- pipelines
class DushuprojectPipeline:
def open_spider(self, spider):
self.fp = open('book.json', 'w', encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
return item
def close_spider(self, spider):
self.fp.close()
正儿八经分割线~
那个不大不小的大坑在这里~
start_urls = ['https://www.dushu.com/book/1617.html']
那个规则rules里面的LinkExtractor(allow=r'/book/1617_\d+\.html')的正则表达式是从第2页开始的,那么首页start_urls不在规则里面可不就获取不到了么
-> start_urls = ['https://www.dushu.com/book/1617_1.html']
注意
- crawlspider中callback只能写函数名字字符串,callback=’parse_item’
- 在一般的spider中,比如小栗子-01中,callback=self.parse
4.数据入库
create database spider01 charset=utf8;
use spider01;
create table book(
id int primary key auto_increment,
name varchar(128),
src varchar(128));
- settings
DB_HOST = 'localhost'
DB_PORT = 3306
DB_USER = 'root'
DB_PASSWORD = 'xiaoye777'
DB_NAME = 'spider01'
DB_CHARSET = 'utf8'
ITEM_PIPELINES = {
'dushuproject.pipelines.DushuprojectPipeline': 300,
'dushuproject.pipelines.MysqlPipeline': 301
}
- 再开一条管道将数据放入mysql
from scrapy.utils.project import get_project_settings
import pymysql
class MysqlPipeline:
def open_spider(self, spider):
settings = get_project_settings()
self.host = settings['DB_HOST']
self.port = settings['DB_PORT']
self.user = settings['DB_USER']
self.password = settings['DB_PASSWORD']
self.name = settings['DB_NAME']
self.charset = settings['DB_CHARSET']
self.connect()
def connect(self):
self.conn = pymysql.connect(
host=self.host,
port=self.port,
user=self.user,
password=self.password,
db=self.name,
charset=self.charset
)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
sql = 'insert into book(name,src) values("{}","{}")'.format(item['name'],item['src'])
self.cursor.execute(sql)
self.conn.commit()
return item
def close_spider(self, spider):
self.cursor.close()
self.conn.close()
Original: https://blog.csdn.net/weixin_48023487/article/details/123557009
Author: 猿儿飘飘
Title: scrapy笔记
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/789031/
转载文章受原作者版权保护。转载请注明原作者出处!