爬虫scrapt框架
**1.创建项目:**D:\code\客户>scrapy startproject bokeyuan
**2.创建域名:**D:\code\客户\bokeyuan>scrapy genspider bokeyuanspider cnblogs.com *** 注意进入目录后创建,而且不要和项目名同名
scrapy 修改URL爬取起始位置
import scrapy from Autopjt.items import myItem from scrapy.http import Request class AutospdSpider(scrapy.Spider): name = "fulong_spider" start_urls = ['http://category.dangdang.com/pg1-cid4007379.html'] url2 = ('http://dangdang.com','http://jd.com','http://tianmao.com',) def start_requests(self): for url in self.url2: yield self.make_requests_from_url(url) def parse(self, response): item = myItem() item['name'] =response.xpath('/html/head/title/text()').extract() print(item['name'])
添加代理和请求头,以及解码数据
# -*- coding: utf-8 -*- import scrapy, re, parsel from scrapy import Request from urllib import request class YfchspiderSpider(scrapy.Spider): name = 'yfchspider' allowed_domains = ['28car.com'] start_urls = ['https://www.28car.com/'] url = "https://dj1jdjkadk.28car.com/sell_lst.php" proxyHost = "http-dyn.abuyun.com" proxyPort = "9020" # 代理隧道验证信息 proxyUser = "XXXXXXXXXXXX" proxyPass = "SSSSSSSSSSSS" proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % { "host": proxyHost, "port": proxyPort, "user": proxyUser, "pass": proxyPass, } def start_requests(self): # 跳过开始 start_urls ,重这里开始 for i in range(1, 1541): data = { "h_f_do": "1", # 未售 "h_page": f"{i}" # 页码 } headers = { "referer": "https://dj1jdjkadk.28car.com/sell_lst.php", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" } yield scrapy.FormRequest(url=self.url, formdata=data, callback=self.parse, headers=headers, meta={'proxy': self.proxyMeta}) # FormRequest 执行post请求 meta={'proxy': self.proxyMeta} 添加代理 def parse(self, response): id_list = re.findall(r'\bonclick="goDsp.*?n\b', response.text) for ids in id_list: id = ids.split(",")[1].strip() href = "https://dj1jdjkadk.28car.com/sell_dsp.php?h_vid=%s&h_vw=y" % id headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" } request = Request(href, callback=self.detail_parse, headers=headers, dont_filter=True,meta={'proxy': self.proxyMeta}) request.meta["id"] = id yield request def detail_parse(self, response): id = response.meta['id'] url = "https://www.28car.com/sell_dsp.php?h_vid=%s&h_vw=y" % id response.body.decode('big5') # 解码需要的数据格式比如:utf8\ data = parsel.Selector(response.text) table = data.xpath("//table[@bgcolor='#FFFFFF']").extract() data1 = parsel.Selector(table[3])# print(name) yield dict1
一 介绍
Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速、简单、可扩展的方式从网站中提取所需的数据。但目前Scrapy的用途十分广泛,可用于如数据挖掘、监测和自动化测试等领域,也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。
Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。整体架构大致如下
The data flow in Scrapy is controlled by the execution engine, and goes like this:
- The Engine gets the initial Requests to crawl from the Spider.
- The Engine schedules the Requests in the Scheduler and asks for the next Requests to crawl.
- The Scheduler returns the next Requests to the Engine.
- The Engine sends the Requests to the Downloader, passing through the Downloader Middlewares (see
process_request()
). - Once the page finishes downloading the Downloader generates a Response (with that page) and sends it to the Engine, passing through the Downloader Middlewares (see
process_response()
). - The Engine receives the Response from the Downloader and sends it to the Spider for processing, passing through the Spider Middleware (see
process_spider_input()
). - The Spider processes the Response and returns scraped items and new Requests (to follow) to the Engine, passing through the Spider Middleware (see
process_spider_output()
). - The Engine sends processed items to Item Pipelines, then send processed Requests to the Scheduler and asks for possible next Requests to crawl.
- The process repeats (from step 1) until there are no more requests from the Scheduler.
Components:
- 引擎(EGINE)
引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。有关详细信息,请参见上面的数据流部分。
- 调度器(SCHEDULER)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址 - 下载器(DOWLOADER)
用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的 - 爬虫(SPIDERS)
SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求 - 项目管道(ITEM PIPLINES)
在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作 - 下载器中间件(Downloader Middlewares)
位于Scrapy引擎和下载器之间,主要用来处理从EGINE传到DOWLOADER的请求request,已经从DOWNLOADER传到EGINE的响应response,你可用该中间件做以下几件事- process a request just before it is sent to the Downloader (i.e. right before Scrapy sends the request to the website);
- change received response before passing it to a spider;
- send a new Request instead of passing received response to a spider;
- pass response to a spider without fetching a web page;
- silently drop some requests.
- 爬虫中间件(Spider Middlewares)
位于EGINE和SPIDERS之间,主要工作是处理SPIDERS的输入(即responses)和输出(即requests)
官网链接:https://docs.scrapy.org/en/latest/topics/architecture.html
二 安装
#Windows平台 1、pip3 install wheel #安装后,便支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs 3、pip3 install lxml 4、pip3 install pyopenssl 5、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/ 6、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 7、执行pip3 install 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl 8、pip3 install scrapy #Linux平台 1、pip3 install scrapy
三 命令行工具
#1 查看帮助 scrapy -h scrapy <command> -h #2 有两种命令:其中Project-only必须切到项目文件夹下才能执行,而Global的命令则不需要 Global commands: startproject #创建项目 genspider #创建爬虫程序 settings #如果是在项目目录下,则得到的是该项目的配置 runspider #运行一个独立的python文件,不必创建项目 shell #scrapy shell url地址 在交互式调试,如选择器规则正确与否 fetch #独立于程单纯地爬取一个页面,可以拿到请求头 view #下载完毕后直接弹出浏览器,以此可以分辨出哪些数据是ajax请求 version #scrapy version 查看scrapy的版本,scrapy version -v查看scrapy依赖库的版本 Project-only commands: crawl #运行爬虫,必须创建项目才行,确保配置文件中ROBOTSTXT_OBEY = False check #检测项目中有无语法错误 list #列出项目中所包含的爬虫名 edit #编辑器,一般不用 parse #scrapy parse url地址 --callback 回调函数 #以此可以验证我们的回调函数是否正确 bench #scrapy bentch压力测试 #3 官网链接 https://docs.scrapy.org/en/latest/topics/commands.html
#1、执行全局命令:请确保不在某个项目的目录下,排除受该项目配置的影响 scrapy startproject MyProject cd MyProject scrapy genspider baidu www.baidu.com scrapy settings --get XXX #如果切换到项目目录下,看到的则是该项目的配置 scrapy runspider baidu.py scrapy shell https://www.baidu.com response response.status response.body view(response) scrapy view https://www.taobao.com #如果页面显示内容不全,不全的内容则是ajax请求实现的,以此快速定位问题 scrapy fetch --nolog --headers https://www.taobao.com scrapy version #scrapy的版本 scrapy version -v #依赖库的版本 #2、执行项目命令:切到项目目录下 scrapy crawl baidu scrapy check scrapy list scrapy parse http://quotes.toscrape.com/ --callback parse scrapy bench 示范用法
四 项目结构以及爬虫应用简介
project_name/ scrapy.cfg project_name/ __init__.py items.py pipelines.py settings.py spiders/ __init__.py 爬虫1.py 爬虫2.py 爬虫3.py
文件说明:
- scrapy.cfg 项目的主配置信息,用来部署scrapy时使用,爬虫相关的配置信息在settings.py文件中。
- items.py 设置数据存储模板,用于结构化数据,如:Django的Model
- pipelines 数据处理行为,如:一般结构化的数据持久化
- settings.py 配置文件,如:递归的层数、并发数,延迟下载等。强调:配置文件的选项必须大写否则视为无效,正确写法USER_AGENT='xxxx'
- spiders 爬虫目录,如:创建文件,编写爬虫规则
注意:一般创建爬虫文件时,以网站域名命名
#在项目目录下新建:entrypoint.py from scrapy.cmdline import execute execute(['scrapy', 'crawl', 'xiaohua'])
五 Spiders
1、介绍
#1、Spiders是由一系列类(定义了一个网址或一组网址将被爬取)组成,具体包括如何执行爬取任务并且如何从页面中提取结构化的数据。 #2、换句话说,Spiders是你为了一个特定的网址或一组网址自定义爬取和解析页面行为的地方
2、Spiders会循环做如下事情
#1、生成初始的Requests来爬取第一个URLS,并且标识一个回调函数 第一个请求定义在start_requests()方法内默认从start_urls列表中获得url地址来生成Request请求,默认的回调函数是parse方法。回调函数在下载完成返回response时自动触发 #2、在回调函数中,解析response并且返回值 返回值可以4种: 包含解析数据的字典 Item对象 新的Request对象(新的Requests也需要指定一个回调函数) 或者是可迭代对象(包含Items或Request) #3、在回调函数中解析页面内容 通常使用Scrapy自带的Selectors,但很明显你也可以使用Beutifulsoup,lxml或其他你爱用啥用啥。 #4、最后,针对返回的Items对象将会被持久化到数据库 通过Item Pipeline组件存到数据库:https://docs.scrapy.org/en/latest/topics/item-pipeline.html#topics-item-pipeline) 或者导出到不同的文件(通过Feed exports:https://docs.scrapy.org/en/latest/topics/feed-exports.html#topics-feed-exports)
3、Spiders总共提供了五种类:
#1、scrapy.spiders.Spider #scrapy.Spider等同于scrapy.spiders.Spider #2、scrapy.spiders.CrawlSpider #3、scrapy.spiders.XMLFeedSpider #4、scrapy.spiders.CSVFeedSpider #5、scrapy.spiders.SitemapSpider
4、导入使用
# -*- coding: utf-8 -*- import scrapy from scrapy.spiders import Spider,CrawlSpider,XMLFeedSpider,CSVFeedSpider,SitemapSpider class AmazonSpider(scrapy.Spider): #自定义类,继承Spiders提供的基类 name = 'amazon' allowed_domains = ['www.amazon.cn'] start_urls = ['http://www.amazon.cn/'] ``` def parse(self, response): pass```
5、class scrapy.spiders.Spider
这是最简单的spider类,任何其他的spider类都需要继承它(包含你自己定义的)。
该类不提供任何特殊的功能,它仅提供了一个默认的start_requests方法默认从start_urls中读取url地址发送requests请求,并且默认parse作为回调函数
class AmazonSpider(scrapy.Spider): name = 'amazon' ``` allowed_domains = ['www.amazon.cn'] start_urls = ['http://www.amazon.cn/'] custom_settings = { 'BOT_NAME' : 'Egon_Spider_Amazon', 'REQUEST_HEADERS' : { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', } } def parse(self, response): pass```
6、其他通用Spiders:https://docs.scrapy.org/en/latest/topics/spiders.html#generic-spiders
六 Selectors
#1 //与/ #2 text #3、extract与extract_first:从selector对象中解出内容 #4、属性:xpath的属性加前缀@ #4、嵌套查找 #5、设置默认值 #4、按照属性查找 #5、按照属性模糊查找 #6、正则表达式 #7、xpath相对路径 #8、带变量的xpath
https://docs.scrapy.org/en/latest/topics/selectors.html
七 Items
https://docs.scrapy.org/en/latest/topics/items.html
八 Item Pipeline
https://docs.scrapy.org/en/latest/topics/item-pipeline.html
九 Dowloader Middeware
下载中间件的用途 1、在process——request内,自定义下载,不用scrapy的下载 2、对请求进行二次加工,比如 设置请求头 设置cookie 添加代理 scrapy自带的代理组件: from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware from urllib.request import getproxies
十 Spider Middleware
1、爬虫中间件方法介绍
2、当前爬虫启动时以及初始请求产生时
3、process_spider_input返回None时
4、process_spider_input抛出异常时
5、指定errback
十一 自定义扩展
自定义扩展(与django的信号类似) 1、django的信号是django是预留的扩展,信号一旦被触发,相应的功能就会执行 2、scrapy自定义扩展的好处是可以在任意我们想要的位置添加功能,而其他组件中提供的功能只能在规定的位置执行
十二 settings.py
十三 爬取亚马逊商品信息
链接:https://pan.baidu.com/s/1eSWBDh4