scrapy安装
1. scrapy是什么?
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
2. 安装scrapy:
pip install scrapy
安装过程中出错:
如果安装有错误!!!!
pip install Scrapy
building 'twisted.test.raiser' extension
error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++
Build Tools": http://landinghub.visualstudio.com/visual‐cpp‐build‐tools
解决方案:
http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
下载twisted对应版本的whl文件(如我的Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl),cp后面是
python版本,amd64代表64位,运行命令:
pip install C:\Users\...\Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl
pip install Scrapy
如果再报错
python ‐m pip install ‐‐upgrade pip
如果再报错 win32
解决方法:
pip install pypiwin32
再报错:使用anaconda
使用步骤:
打开anaconda
点击environments
点击not installed
输入scrapy
apply
在pycharm中选择anaconda的环境
scrapy项目的创建以及运行
3. 创建scrapy项目:
终端输入 scrapy startproject 项目名称
注意:
- 项目的名字不允许使用数字开头 也不能包含中文
- 要在spiders文件夹中创建爬虫文件
cd 项目的名字\项目的名字\spiders
创建爬虫文件 scrapy genspier 爬虫的文件名 要爬取的网页 eg: scrapy genspider baidu http://baidu.com
运行爬虫代码 scrapy crawl 爬虫的名字 eg: scrapy crawl baidu 在运行前我们需要把setting中的君子协议给注释掉,如下图
这是各个浏览器之间的协议,我们不需要遵守
我们将红圈中的内容将其注释掉
import scrapy
class BaiduSpider(scrapy.Spider):
#爬虫的名字,运行爬虫的时候 使用的值
name = "baidu"
#允许访问的域名
allowed_domains = ["www.baidu.com"]
#起始的url地址 指的是第一次访问的域名
#start_urls是在allowed_domains前面添加http://
start_urls = ["http://www.baidu.com"]
#是执行了start_urls之后 执行的方法 方法中的response 就是返回的那个对象
#相当于 response=urllib.request.urlopen()
# response=request.get()
def parse(self, response):
print('这是一个测试')
4. 项目组成:
scrapy项目的结构
项目名字
项目名字
spiders
__init__.py
自定义的爬虫文件.py ‐‐‐》由我们自己创建,是实现爬虫核心功能的文件
__init__.py
items.py ‐‐‐》定义数据结构的地方,是一个继承自scrapy.Item的类
middlewares.py ‐‐‐》中间件 代理
pipelines.py ‐‐‐》管道文件,里面只有一个类,用于处理下载数据的后续处理
默认是300优先级,值越小优先级越高(1‐1000)
settings.py ‐‐‐》配置文件 比如:是否遵守robots协议,User‐Agent定义等
我们以58同城的网页为例,我们创建一个scrapy文件
6. 创建爬虫文件:
(1)跳转到spiders文件夹 cd 目录名字/目录名字/spiders
(2)scrapy genspider 爬虫名字 网页的域名
爬虫文件的基本组成:
继承scrapy.Spider类
name = 'baidu' ‐‐‐》 运行爬虫文件时使用的名字
allowed_domains ‐‐‐》 爬虫允许的域名,在爬取的时候,如果不是此域名之下的
url,会被过滤掉
start_urls ‐‐‐》 声明了爬虫的起始地址,可以写多个url,一般是一个
parse(self, response) ‐‐‐》解析数据的回调函数
response.text ‐‐‐》响应的是字符串
response.body ‐‐‐》响应的是二进制文件
response.xpath()‐》xpath方法的返回值类型是selector列表
extract() ‐‐‐》提取的是selector对象的是data
extract_first() ‐‐‐》提取的是selector列表中的第一个数据
import scrapy
class TcSpider(scrapy.Spider):
name = "tc"
allowed_domains = ["hezhou.58.com"]
start_urls = ["https://hezhou.58.com/sou/?key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&classpolicy=classify_B%2Cuuid_BWFczZwN8WKQ2ENkAYcww7TidZFSpKTz&search_uuid=BWFczZwN8WKQ2ENkAYcww7TidZFSpKTz&search_type=input"]
def parse(self, response):
content=response.text
span=response.xpath('//div[@id="filter"]/div[@class="tabs"]/a/span')[0]
print('=======')
print(span.extract())
7.运行爬虫文件:
scrapy crawl 爬虫名称
注意:应在spiders文件夹内执行
scrapy架构组成
1.(1)引擎 ‐‐‐》自动运行,无需关注,会自动组织所有的请求对象,分发给下载器
(2)下载器 ‐‐‐》从引擎处获取到请求对象后,请求数据
(3)spiders ‐‐‐》Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例
如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及
分析某个网页(或者是有些网页)的地方。
(4)调度器 ‐‐‐》有自己的调度规则,无需关注
(5)管道(Item pipeline) ‐‐‐》最终处理数据的管道,会预留接口供我们处理数据
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行
一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:
1. 清理HTML数据
2. 验证爬取的数据(检查item包含某些字段)
3. 查重(并丢弃)
4. 将爬取结果保存到数据库
scrapy工作原理
scrapy shell
1.什么是scrapy shell?
Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取
数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。
该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该
终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。
一旦熟悉了Scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。
2.安装ipython
安装:pip install ipython
简介:如果您安装了 IPython ,Scrapy终端将使用 IPython (替代标准Python终端)。 IPython 终端与其他相
比更为强大,提供智能的自动补全,高亮输出,及其他特性。
3.应用:(1)scrapy shell www.baidu.com
(2)scrapy shell http://www.baidu.com
(3) scrapy shell "http://www.baidu.com"
(4) scrapy shell "www.baidu.com"
语法:
(1)response对象:
response.body
response.text
response.url
response.status
(2)response的解析:
response.xpath() (常用)
使用xpath路径查询特定元素,返回一个selector列表对象
response.css()
使用css_selector查询元素,返回一个selector列表对象
获取内容 :response.css('#su::text').extract_first()
获取属性 :response.css('#su::attr(“value”)').extract_first()
(3)selector对象(通过xpath方法调用返回的是seletor列表)
extract()
提取selector对象的值
如果提取不到值 那么会报错
使用xpath请求到的对象是一个selector对象,需要进一步使用extract()方法拆
包,转换为unicode字符串
extract_first()
提取seletor列表中的第一个值
如果提取不到值 会返回一个空值
返回第一个解析到的值,如果列表为空,此种方法也不会报错,会返回一个空值
xpath()
css()
注意:每一个selector对象可以再次的去使用xpath或者css方法
- 进入到scrapy shell的终端 直接在window的终端中输入scrapy shell 域名
- 如果想看到一些高亮 或者 自动补全 那么可以安装ipython pip install ipython
yield
1. 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代
2. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代
时,从上一次迭代遇到的yield后面的代码(下一行)开始执行
3. 简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始
案例:
1.当当网 (1)yield(2).管道封装(3).多条管道下载 (4)多页数据下载
2.电影天堂 (1)一个item包含多级页面的数据
我们通过当当图书网,爬取了图书的图片,名字和价格,在爬取图片时需要注意的是网站的图片会进行懒加载,同时我们爬取的第一个图片为none,这时候我们就需要使用结构控制语句
import scrapy
class DangSpider(scrapy.Spider):
name = "dang"
allowed_domains = ["category.dangdang.com"]
start_urls = ["https://category.dangdang.com/cp01.01.02.00.00.00.html"]
def parse(self, response):
# src=//ul[@id="component_59"]/li/a/img/@src
# alt=//ul[@id="component_59"]/li/a/img/@alt
# price=//ul[@id="component_59"]/li/p[@class="price"]/span[1]/text()
li_list=response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
src = li.xpath('.//img/@data-original').extract_first()
# 第一张图片和其他的图片的标签的属性是不一样的
# 第一张图片的src是可以使用的 其他的图片的地址是data-original
if src:
src = src
else:
src = li.xpath('.//img/@src').extract_first()
name = li.xpath('.//img/@alt').extract_first()
price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
print(src,name,price)
我们在items.py中定义数据结构,你需要什么结构就定义什么结构
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ScrapyDangdang095Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 图片
src=scrapy.Field()
#名字
name=scrapy.Field()
#价格
price=scrapy.Field()
我们需要使用这个数据结构就需要先导入这个数据结构
#导入
from scrapy_dangdang_095.items import ScrapyDangdang095Item
我们还需要将该数据导入数据结构中
book=ScrapyDangdang095Item(src=src,name=name,price=price)
我们使用yield进行数据的下载
1. 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代
2. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代
时,从上一次迭代遇到的yield后面的代码(下一行)开始执行
3. 简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始
如果想使用管道的话,我们就必须在setting中开启管道
我们在setting中将下图的注释解开
需要注意的是管道可以有很多个,那么管道是有优先级的,优先级的范围是1到1000 值越小优先级越高
管道代码
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
# 如果想使用管道的话 那么就必须在settings中开启管道
class ScrapyDangdang095Pipeline:
# 在爬虫文件开始的之前就执行的一个方法
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# item就是yield后面的book对象
def process_item(self, item, spider):
# 以下这种模式不推荐 因为每传递过来一个对象 那么就打开一次文件 对文件的操作过于频繁
# # (1) write方法必须要写一个字符串 而不能是其他的对象
# # (2) w模式 会每一个对象都打开一次文件 覆盖之前的内容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
解决对文件的打开和关闭过于频繁
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
# 如果想使用管道的话 那么就必须在settings中开启管道
class ScrapyDangdang095Pipeline:
# 在爬虫文件开始的之前就执行的一个方法
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# item就是yield后面的book对象
def process_item(self, item, spider):
# 以下这种模式不推荐 因为每传递过来一个对象 那么就打开一次文件 对文件的操作过于频繁
# # (1) write方法必须要写一个字符串 而不能是其他的对象
# # (2) w模式 会每一个对象都打开一次文件 覆盖之前的内容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
# 在爬虫文件执行完之后 执行的方法
def close_spider(self,spider):
self.fp.close()
开启多条管道下载
class 自定义:
def process_item(self,item,spider):
return intem
我们自定义为DangDangDownloadPipeline
我们需要在setting中开启管道
'scrapy_dangdang_095.pipelines.DangDangDownloadPipeline':301
我们创建一个books文件夹用来接收我们爬取的的图片
pipelines.py中的代码如下
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
# 如果想使用管道的话 那么就必须在settings中开启管道
class ScrapyDangdang095Pipeline:
# 在爬虫文件开始的之前就执行的一个方法
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# item就是yield后面的book对象
def process_item(self, item, spider):
# 以下这种模式不推荐 因为每传递过来一个对象 那么就打开一次文件 对文件的操作过于频繁
# # (1) write方法必须要写一个字符串 而不能是其他的对象
# # (2) w模式 会每一个对象都打开一次文件 覆盖之前的内容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
# 在爬虫文件执行完之后 执行的方法
def close_spider(self,spider):
self.fp.close()
import urllib.request
# 多条管道开启
# (1) 定义管道类
# (2) 在settings中开启管道
# 'scrapy_dangdang_095.pipelines.DangDangDownloadPipeline':301
class DangDangDownloadPipeline:
def process_item(self, item, spider):
url = 'http:' + item.get('src')#注意src前面没有http,我们需要自行添加
filename = './books/' + item.get('name') + '.jpg'
urllib.request.urlretrieve(url = url, filename= filename)
return item
接下来哦我们就可以进阶到多页面的下载。
我们获取每一页的请求url寻找规律
# http://category.dangdang.com/pg3-cp01.01.02.00.00.00.html
# http://category.dangdang.com/pg4-cp01.01.02.00.00.00.html
我们发现只有在pg 后面的数字是不同的,我们将其进行初始化,将数字之前的网址和数字之后的网址进行字符串拼接
#初始化
base_url = 'http://category.dangdang.com/pg'
page = 1
if self.page < 100:
self.page = self.page + 1
url = self.base_url + str(self.page) + '-cp01.01.02.00.00.00.html'
# 怎么去调用parse方法
# scrapy.Request就是scrpay的get请求
# url就是请求地址
# callback是你要执行的那个函数 注意不需要加()
yield scrapy.Request(url=url,callback=self.parse)
在这段代码中,回调函数是 parse 方法。在 Scrapy 中,回调函数指的是在请求完成后执行的函数,用于
处理响应的数据。
在这个例子中,当爬虫发起请求后,当响应返回时,Scrapy 将调用 parse 方法来处理响应的数据。
在 yield scrapy.Request(url=url, callback=self.parse) 这行代码中,callback=self.parse 指定了当请求
完成后要执行的回调函数,即 parse 方法。
在 Python 中,self 是一个惯例,用于引用类实例中的属性和方法。在类定义中,self 是第一个参数,用于指代类的实例本身。在类的方法内部,通过 self 可以访问该类的属性和方法。
在这个例子中,self.page 是指该类的一个属性,而不是一个局部变量。通过在 self 前面加上 self,可以确保在类的其他方法中也可以访问和修改这个属性。
如果在方法中直接使用 page,Python 会认为它是一个局部变量,而不是类的属性。为了在整个类中共享和访问 page 属性,需要使用 self.page 来明确地指示这是类的属性。
完整代码如下
import scrapy
from scrapy_dangdang_095.items import ScrapyDangdang095Item
class DangSpider(scrapy.Spider):
name = 'dang'
# 如果是多页下载的话 那么必须要调整的是allowed_domains的范围 一般情况下只写域名
allowed_domains = ['category.dangdang.com']
start_urls = ['http://category.dangdang.com/cp01.01.02.00.00.00.html']
base_url = 'http://category.dangdang.com/pg'
page = 1
def parse(self, response):
# pipelines 下载数据
# items 定义数据结构的
# src = //ul[@id="component_59"]/li//img/@src
# alt = //ul[@id="component_59"]/li//img/@alt
# price = //ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()
# 所有的seletor的对象 都可以再次调用xpath方法
li_list = response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
src = li.xpath('.//img/@data-original').extract_first()
# 第一张图片和其他的图片的标签的属性是不一样的
# 第一张图片的src是可以使用的 其他的图片的地址是data-original
if src:
src = src
else:
src = li.xpath('.//img/@src').extract_first()
name = li.xpath('.//img/@alt').extract_first()
price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
book = ScrapyDangdang095Item(src=src,name=name,price=price)
# 获取一个book就将book交给pipelines
yield book
# 每一页的爬取的业务逻辑全都是一样的,所以我们只需要将执行的那个页的请求再次调用parse方法
# 就可以了
# http://category.dangdang.com/pg2-cp01.01.02.00.00.00.html
# http://category.dangdang.com/pg3-cp01.01.02.00.00.00.html
# http://category.dangdang.com/pg4-cp01.01.02.00.00.00.html
if self.page < 100:
self.page = self.page + 1
url = self.base_url + str(self.page) + '-cp01.01.02.00.00.00.html'
# 怎么去调用parse方法
# scrapy.Request就是scrpay的get请求
# url就是请求地址
# callback是你要执行的那个函数 注意不需要加()
yield scrapy.Request(url=url,callback=self.parse)
接下来我们以电影天堂为例
我们获取网页的请求头网址
我们创建好目录和爬虫文件
我们先测试看看网址做了什么反爬
网址并没有做反爬
接下来我们的需求是获取电影的名字和图片
我们现在items.py中定义好数据结构
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ScrapyMovie099Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
src = scrapy.Field()
我们获取名字和图片,使用的xpath语句表达,因为图片在链接中,则我们使用xpath语句表达出这个链接
a_list=response.xpath('//div[@class="co_content8"]//td[2]//a[2]')
for a in a_list:
name=a.xpath('./text(').extract_first()
href=a.xpath('./@href').extract_first()
我们要获取图片对第二页的链接进行访问,我们自定义一个第二页的链接的函数,需要注意的是我们要注意 allowed_domains允许访问的域名的范围
# 对第二页的链接发起访问
yield scrapy.Request(url=url, callback=self.parse_second, meta={'name': name})
这段代码使用了 Scrapy 的异步请求机制,通过 `yield` 关键字创建了一个 `scrapy.Request` 对象,用于发起对第二页的请求。
让我们逐一解释这段代码的各个部分:
- `yield`: 在 Python 中,`yield` 关键字用于生成器函数中,表示将结果产生给调用者,并暂停执行当前函数。在 Scrapy 中,使用 `yield` 关键字可以将请求、数据等生成为 Scrapy 框架可以处理的对象,从而实现异步处理和高效的爬取。
- `scrapy.Request`: 这是 Scrapy 框架中用于发起 HTTP 请求的类。它接受多个参数,其中 `url` 参数是要请求的 URL,`callback` 参数是指定请求成功后的回调函数,`meta` 参数是一个字典,用于传递额外的数据。
- `url=url`: 这是请求的 URL,即第二页电影信息的链接。在原代码中,它是通过将第一页提取的相对链接拼接而成的绝对链接。
- `callback=self.parse_second`: 这是请求成功后的回调函数。在原代码中,它指定为 `parse_second`,即第二页响应成功后会调用 `parse_second` 方法来处理响应。
- `meta={'name': name}`: 这是一个字典,用于传递额外的数据。在原代码中,它将电影的名称传递给了第二页请求,这样在第二页的解析函数中可以使用这个名称来进一步处理电影信息。
总的来说,这段代码的作用是发起一个对第二页的异步请求,并在请求成功后调用 `parse_second` 方法来处理第二页的响应。同时,通过 `meta` 参数将电影名称传递给了第二页的解析函数。
第二个函数代码如下
def parse_second(self, response):
# 注意 如果拿不到数据的情况下 一定检查你的xpath语法是否正确
src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
# 接受到请求的那个meta参数的值
name = response.meta['name']
movie = ScrapyMovie099Item(src=src, name=name)
yield movie
完整代码如下
import scrapy
from scrapy_099_mv.items import ScrapyMovie099Item
class MvSpider(scrapy.Spider):
name = "mv"
allowed_domains = ["www.dygod.net"]
start_urls = ["https://www.dygod.net/html/gndy/china/index.html"]
def parse(self, response):
a_list = response.xpath('//div[@class="co_content8"]//td[2]//a[2]')
for a in a_list:
# 获取第一页的name 和 要点击的链接
name = a.xpath('./text()').extract_first()
href = a.xpath('./@href').extract_first()
# 第二页的地址是
url = 'https://www.dygod.net/' + href
print(url)
# 对第二页的链接发起访问
yield scrapy.Request(url=url, callback=self.parse_second, meta={'name': name})
def parse_second(self, response):
# 注意 如果拿不到数据的情况下 一定检查你的xpath语法是否正确
src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
# 接受到请求的那个meta参数的值
name = response.meta['name']
movie = ScrapyMovie099Item(src=src, name=name)#使用from引入的数据结构
yield movie#将movie返回给管道,我们需要将管道打开
pipelines.py的代码如下
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
class ScrapyMovie099Pipeline:
def open_spider(self,spider):
self.fp = open('movie.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()
这几个函数是定义在 Scrapy 的 Item Pipeline 中的方法,用于对爬取到的数据进行处理和存储。下面是每个方法的作用:
1. `open_spider(self, spider)`: 这个方法在爬虫被打开时调用,用于执行一些初始化操作。在这个例子中,`open_spider` 方法打开了一个名为 `movie.json` 的文件,用于将处理后的数据写入到这个文件中。具体操作是使用 `open` 函数打开一个文件对象 `self.fp`,该文件对象用于写入数据,并指定编码格式为 `utf-8`。
2. `process_item(self, item, spider)`: 这个方法是用来处理每个从爬虫中得到的 item 的。在这里,方法将每个 item 转换为字符串形式,并将其写入到之前创建的文件对象 `self.fp` 中。最后,该方法返回处理后的 item。
3. `close_spider(self, spider)`: 这个方法在爬虫被关闭时调用,用于执行一些清理操作。在这个例子中,`close_spider` 方法关闭了之前打开的文件对象 `self.fp`,确保文件处理的完成和资源的释放。通过调用 `close` 方法,将文件对象 `self.fp` 关闭,以便文件被正确地保存和释放资源。
综合来看,这几个函数构成了一个简单的 Item Pipeline,用于将爬取到的数据存储到名为 `movie.json` 的文件中。具体操作是在 `open_spider` 方法中打开文件,然后在 `process_item` 方法中将每个 item 写入文件,最后在 `close_spider` 方法中关闭文件。这种设计模式可以保证数据的正确存储和资源的正确释放。
Mysql
(1)下载(https://dev.mysql.com/downloads/windows/installer/5.7.html)
(2)安装(https://jingyan.baidu.com/album/d7130635f1c77d13fdf475df.html)
pymysql的使用步骤
1.pip install pymysql
2.pymysql.connect(host,port,user,password,db,charset)
3.conn.cursor()
4.cursor.execute()
CrawlSpider
1.继承自scrapy.Spider
2.独门秘笈
CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发
送请求
所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常
合适的
3.提取链接
链接提取器,在这里就可以写规则提取指定链接
scrapy.linkextractors.LinkExtractor(
allow = (), # 正则表达式 提取符合正则的链接
deny = (), # (不用)正则表达式 不提取符合正则的链接
allow_domains = (), # (不用)允许的域名
deny_domains = (), # (不用)不允许的域名
restrict_xpaths = (), # xpath,提取符合xpath规则的链接
restrict_css = () # 提取符合选择器规则的链接)
4.模拟使用
正则用法:links1 = LinkExtractor(allow=r'list_23_\d+\.html')
xpath用法:links2 = LinkExtractor(restrict_xpaths=r'//div[@class="x"]')
css用法:links3 = LinkExtractor(restrict_css='.x')
5.提取连接
link.extract_links(response)
使用演示
打开scrapy shell 网址
提取链接提取器可以提取当前页面中所有符合规则的链接
from scrapy.linkextractors import LinkExtractor
#正则表达式
# \d:表示数字 +表示1到多个数字
link = LinkExtractor(allow=r'/play/4483-1-\d+\.html')
#输出
link.extract_linke(response)
#xpath方式
link1 = LinkExtractor(restrict_xpaths="//div[@class='module-play-list']/div/a/@href")
#输出
link.extract_linke(response)
6.注意事项
【注1】callback只能写函数名字符串, callback='parse_item'
【注2】在基本的spider中,如果重新发送请求,那里的callback写的是 callback=self.parse_item 【注‐
‐稍后看】follow=true 是否跟进 就是按照提取连接规则进行提取