本节参考链接
https://blog.csdn.net/weixin_44627151/article/details/115775239 https://www.bilibili.com/video/BV1jt411Q7PD?from=search&seid=10299534250007155058&spm_id_from=333.337.0.0
简介
写一个爬虫,需要做很多的事情。比如:发送网络请求、数据解析、数据存储、反反爬虫机制(更换p代理、设置请求头等)、异步·请求……这些知识点前面已经讲得清楚,大家会发现我们是一个一个去写每个步骤,然后我们可以用函数封装起来,但是这些工作如果每次都要自己从零开始写的话,比较浪费时间。因此Scrapy把一些基础的东西封装好了,在他上面写爬虫可以变的更加的高效(抓取效率和开发效率)因此真正在公司里,一些上了量的爬虫,都是使用scrapy框架来解决
Scrapy框架原理
引擎(Scrapy)
用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader)
用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
爬虫(Spiders)
爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline)
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据
下载器中间件(Downloader Middlewares)
位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应
爬虫中间件(Spider Middlewares)
介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出
调度中间件(Scheduler Middewares)
介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应
基本命令
全局命令
scrapy sstartproject 创建项目
genspider: scrapy genspider [-t template] <name> <domain>生成爬虫,-l 查看模板; -t 指定模板,name爬虫名,domain域名(爬取网站范围)
settings 查看设置
runspider 运行爬虫(运行一个独立的python文件,不必创建项目)
shell :scrapy shell [url]进入交互式命令行,可以方便调试
–spider=SPIDER 忽略爬虫自动检测,强制使用指定的爬虫
-c 评估代码,打印结果并退出:
$ scrapy shell --nolog http://www.example.com/ -c '(response.status, response.url)'
(200, 'http://www.example.com/')
1
2
–no-redirect 拒绝重定向
–nolog 不打印日志
response.status 查看响应码
response.url
response.text; response.body 响应文本;响应二进制
view(response) 打开下载到本地的页面,方便分析页面(比如非静态元素)
fetch 查看爬虫是如何获取页面的,常见选项如下:
–spider=SPIDER 忽略爬虫自动检测,强制使用指定的爬虫
–headers 查看响应头信息
–no-redirect 拒绝重定向
view 同交互式命令中的view
version
项目命令
crawl : scrapy crawl <spider> 指定爬虫开始爬取(确保配置文件中ROBOTSTXT_OBEY = False)
check: scrapy check [-l] <spider>检查语法错误
list 爬虫list
edit 命令行模式编辑爬虫(没啥用)
parse: scrapy parse <url> [options] 爬取并用指定的回掉函数解析(可以验证我们的回调函数是否正确)
–callback 或者 -c 指定回调函数
bench 测试爬虫性能
scrapy startproject maitian # 创建一个爬虫项目 maitian
我利用Pycharm的终端和Scrapy命令创建了项目,结果如下
创建项目后,自动生成如下文件
1. scrapy startproject 项目名称
- 在当前目录中创建中创建一个项目文件(类似于Django)
2. scrapy genspider [-t template] <name> <domain>
- 创建爬虫应用
如:
scrapy genspider -t basic oldboy oldboy.com
scrapy genspider -t xmlfeed autohome autohome.com.cn
PS:
查看所有命令:scrapy gensipider -l
查看模板命令:scrapy gensipider -d 模板名称
3. scrapy list
- 展示爬虫应用列表
4. scrapy crawl 爬虫应用名称
- 运行单独爬虫应用
scrapy crawl xxx --nolog
5.scrapy shell 进入shell
复制代码
问题1 :代码运行出错解决办法
大家在运行代码一定出现这个错误
ModuleNotFoundError: No module named ‘protego‘
不要去用pycharm去安装,而要用Anaconda去安装,安装后把protego文件夹复制到你运行Python文件的库里面,当然如果你本来用的就是Anaconda就不用了 参考链接:[https://blog.csdn.net/qq_43236333/article/details/115871163](https://blog.csdn.net/qq_43236333/article/details/115871163)
问题2 :创建爬虫文件的代码
name:用于区别spider。该名字必须是唯一的,不能为不同的spider设定相同的名字
statr_urls:它是spider在启动时进行爬取的入口URL列表。因此,第一个被获取到的页面的URL将是其中之一,后续的
URL则从初始的URL的响应中主动提取
parse():它是spider的一个方法。该方法负责解析返回的数据、提取数据(生成item)以及生成需要进一步处理的URL的request对象
import scrapy
class ItcastSpider(scrapy.Spider):
name = 'itcast' 爬虫名称
allowed_domains = ['itcast.cn'] #允许的域名
start_urls = ['http://itcast.cn/']
def parse(self, response):
pass
#处理start_urls的相应
问题3:shell进入命令交互
如:scrapy shell URL --nolog # –-nolog不打印日志
问题4:shell命令的使用
>>>response.xpath('//title/text()').extract_first()
重新下载页面
>>>fetch (URL)
修改请求参数,比如讲默认的GET方法改为POST方法,然后用fetch直接请求request
>>>requset = requset.replace(method='post')
>>>fetch(request)
exit() 即可退出scrapy shell 终端模式
还有其他的使用命令,上图明显
.extract_first()
import scrapy
from maitian.items import MaitianItem
class WebSpider(scrapy.Spider):
name = 'web'
allowed_domains = ['maitian.cn']
start_urls = ['http://bj.maitian.cn/zfall/PG1']
def parse(self, response):
for web_itme in response.xpath("/html/body/section[2]/div[2]/div[2]/ul/li[3]/div[2]"):
yield {
'title': web_itme.xpath("./h1/a/text()").extrace_first().strip(),
'price': web_itme.xpath("./div/ol/strong/span/text()").extrace_first().strip(),
'area': web_itme.xpath(".p[1]/span[1]/text()").extrace_first().strip()
}
next_page_url=response.xpath("//[@id="paging"]/a[@class="down_page"]/@href").extract_first()
if next_page_url is not None:
yield scrapy.Request(response.urljoin(next_page_url))
# 分组(对抓取数据,进行有必要的分组)
li_list = response.xpath("/html/body/div[10]/div/div[2]/ul/li")
for li in li_list:
item = {}
item["name"] = li.xpath("./div[2]/h2/text()").extract_first()
item["title"] = li.xpath("./div[2]/h2/span/text()").extract_first()
print(item)