Python爬虫框架Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有很强通用性的项目模板。对于框架的学习,重点是要学习其框架的特性、各个功能的用法即可。
scrapy安装
Linux:
pip3 install scrapy
Windows:
a.
pip3 install wheel
b. 下载twisted
http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
c. 进入下载目录,
执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
d. pip3 install pywin32
e. pip3 install scrapy
强调:
如果windows10安装
pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl失败,
请自行换成32位的即可解决!!!
提示:如果在pycharm中安装scrapy失败
两种解决办法:
1、把pycharm中的虚拟环境模式改成直接指向现在的python安装环境!
2、把python环境中的scrapy,twisted等直接复制到pycharm工程所在的虚拟环境中去!
Scrapy组件:
引擎(Scrapy)
用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader)
用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
爬虫(Spiders)
爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline) 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
下载器中间件(Downloader Middlewares)
位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
爬虫中间件(Spider Middlewares)
介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
调度中间件(Scheduler Middewares)
介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。
Scrapy运行流程
Scrapy运行流程大概如下:
引擎从调度器中取出一个链接(URL)用于接下来的抓取
引擎把URL封装成一个请求(Request)传给下载器
下载器把资源下载下来,并封装成应答包(Response)
爬虫解析Response
解析出实体(Item),则交给实体管道进行进一步的处理
解析出的是链接(URL),则把URL交给调度器等待抓取
* 解释:引擎首先会将爬虫文件中的起始url获取,并且提交到调度器中。如果需要从url中下载数据,则调度器会将url通过引擎提交给下载器,下载器根据url去下载指定内容(响应体)。下载好的数据会通过引擎移交给爬虫文件,爬虫文件可以将下载的数据进行指定格式的解析。如果解析出的数据需要进行持久化存储,则爬虫文件会将解析好的数据通过引擎移交给管道进行持久化存储。
爬取目标网址:
https://movie.douban.com/top250
第一步:创建 Scrapy 项目
代码语言:javascript复制scrapy startproject douban
由于这里使用的是pycham ide,创建运行调试文件
pycham ide调试文件代码
新建py文件 entrypoint.py
代码语言:javascript复制from scrapy.cmdline import execute
execute(['scrapy','crawl','douban'])
注意:douban 是 Scrapy项目名
第二步:设置字段
items.py
引入 scrapy框架
设置字段格式:字段名=scrapy.Field()
代码语言:javascript复制import scrapy
class DoubanItem(scrapy.Item):
num=scrapy.Field() #序列号
name=scrapy.Field() #电影名
introduce=scrapy.Field() #介绍
star=scrapy.Field() # 星级评分
appraise=scrapy.Field() # 评价人数
survey=scrapy.Field() #一句话介绍
第三步:相关设置修改
settings.py
1.开启协议头
爬取豆瓣网站,需要开启协议头
代码语言:javascript复制# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)'
2.抓取调试开启
代码语言:javascript复制# Enable and configure HTTP caching (disabled by default)
# See [url=https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings]https://docs.scrapy.org/en/lates ... middleware-settings[/url]
HTTPCACHE_ENABLED = True
HTTPCACHE_EXPIRATION_SECS = 0
HTTPCACHE_DIR = 'httpcache'
HTTPCACHE_IGNORE_HTTP_CODES = []
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
这里开启的含义: 这几行注释的作用是,Scrapy会缓存你有的Requests!当你再次请求时,如果存在缓存文档则返回缓存文档,而不是去网站请求,这样既加快了本地调试速度,也减轻了 网站的压力。
3.激活item pipeline
我们的pipeline定义后,需要在配置文件中添加激活才能使用,因此我们需要配置settings.py。
代码语言:javascript复制ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline': 300,
}
注意,这里不开启,存储不了数据!
第四步:爬虫文件的编写,关键!
doub.py
版本一:
代码语言:javascript复制# -*- coding: utf-8 -*-
import scrapy
import requests
from douban.items import DoubanItem
from bs4 import BeautifulSoup
from scrapy.http import Request
class DoubSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['movie.douban.com']
start_urls=["https://movie.douban.com/top250"]
def parse(self, response):
item_list=response.xpath('//ol[@class="grid_view"]/li')
for item in item_list:
douban_item=DoubanItem()
douban_item['num'] = item.xpath('.//div[@class="pic"]/em/text()').extract_first()
douban_item['name']=item.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
#print(douban_item['name'])
introduces=item.xpath('.//div[@class="bd"]/p[1]/text()').extract()
for introduce in introduces:
introduce_date="".join(introduce.split())
douban_item['introduce']=introduce_date
#print(douban_item['introduce'])
douban_item['star']=item.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()').extract_first()
#print(douban_item['star'])
douban_item['appraise'] = item.xpath('.//div[@class="star"]/span[4]/text()').extract_first()
douban_item['survey']=item.xpath('.//p[@class="quote"]/span[@class="inq"]/text()').extract_first()
#print(douban_item['survey'])
print(douban_item)
yield douban_item
next_page=response.xpath('//div[@class="paginator"]/span[@class="next"]/a/@href').extract()
if next_page:
yield Request(f'https://movie.douban.com/top250{next_page[0]}',callback=self.parse)
版本二:
代码语言:javascript复制def parse(self, response):
paginator_urls=[]
paginator_urls.extend(self.start_urls)
paginators=BeautifulSoup(response.text,'lxml').find('div',class_="paginator").find_all('a')[:-1]
for paginator in paginators:
paginator=f"https://movie.douban.com/top250{paginator['href']}"
paginator_urls.append(paginator)
print(paginator_urls)
paginator_urls=set(paginator_urls)
for paginator_url in paginator_urls:
print(paginator_url)
yield Request(paginator_url,callback=self.get_content)
def get_content(self,response):
thispage=BeautifulSoup(response.text,'lxml').find('span',class_="thispage").get_text()
print(thispage)
Scrapy自带xpath 与爬虫 etree xpath类似 注意.extract() 和.extract_first()
在使用scrapy爬虫的时候,我们常常使用xpath来获取html标签,但是我们经常会用到提取的方法
有两种提取的方法
分别是:
extract():
这个方法返回的是一个数组list,里面包含了多个string,如果只有一个string,则返回['ABC']这样的形式。
extract_first():
这个方法返回的是一个string字符串,是list数组里面的第一个字符串。
Xpath选择器:
response.selector属性返回内容相当于response的body构造了一个Selector对象。
Selector对象可以调用xpath()方法实现信息的解析提取。
在xpath()后使用extract()可以返回所有的元素结果。
若xpath()有问题,那么extract()会返回一个空列表。
在xpath()后使用extract_first()可以返回第一个元素结果。
代码语言:javascript复制for v in dllist:
print(v.xpath("./dt/text()").extract_first())
print("="*50)
alist = v.xpath(".//a")
for a in alist:
print(a.xpath("./@href").extract_first(),end=":")
print(a.xpath("./span/img/@alt").extract_first())
#来源:CSDN博主「周雄伟」
版本二为调用bs4抓取数据
但是代码、排序等等不完美,推荐版本一!
第五步:保存数据,写入本地数据库
pipelines.py
代码语言:javascript复制import pymysql
class DoubanPipeline(object):
def __init__(self):
#连接MySQL数据库
self.connect=pymysql.connect(
host="localhost",
user="root",
password="123456",
db="xiaoshuo",
port=3306,
)
self.cursor=self.connect.cursor()
def process_item(self, item, spider):
self.cursor.execute('insert into movie(num,name,introduce,star,appraise,survey)VALUES("{}","{}","{}","{}","{}","{}")'.format(item['num'],item['name'],item['introduce'],item['star'],item['appraise'],item['survey']))
self.connect.commit()
return item
#关闭数据库
def close_spider(self,spider):
self.cursor.close()
项目:
数据:
运行效果:
scrapy数据保存为 csv 方法:
在Scrapy中,负责导出数据的组件被称为Exporter,Scrapy内部实现了多个Exporter,每个Exporter实现一种数据格式的导出,
支持的格式如下:
JSON(JsonItemExporter)
JSON lines(JsonLinesItemExporter)
CSV(CsvItemExporter)
XML(XmlItemExporter)
Pickle(PickleItemExporter)
Marshal(MarshalItemExporter)
cmd命令方法
1.cd进入项目文件
2.敲入命令
代码语言:javascript复制scrapy crawl douban -o douban.csv
由于未指定编码,所以导致保存输出文件为乱码
指定一下 utf-8 编码 格式
代码语言:javascript复制scrapy crawl douban -o douban.csv -s FEED_EXPORT_ENCIDING=utf-8
或者
使用第三方软件修改编码格式,notepad2打开,选择编码ANSI,保存,再用excel打开就是正常的了!
最后的解决办法
在创建项目的settings.py中,添加如下代码
代码语言:javascript复制FEED_EXPORT_ENCODING = 'gb18030'
即可解决乱码问题。
第六步:代{过}{滤}理ip的使用
由于没有账号,未测试。。
项目打包
链接:
https://pan.baidu.com/s/1GX9srMbh7aJbbpC8y6ZzDw
提取码:
zp3h