失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > pythonscrapy_Python Scrapy框架

pythonscrapy_Python Scrapy框架

时间:2021-01-06 14:11:31

相关推荐

pythonscrapy_Python Scrapy框架

1. scrapy安装与环境依赖

# 1.在安装scrapy前需要安装好相应的依赖库, 再安装scrapy, 具体安装步骤如下:

(1).安装lxml库: pip install lxml

(2).安装wheel: pip install wheel

(3).安装twisted: pip install twisted文件路径

***根据网址进入页面后,找到跟自己电脑相匹配的安装包下载,下载成功后,复制到一个文件夹在地址栏用cmd打开切换到python环境中执行命令 twisted: pip install twisted文件路径(T+tab键会自动生成)

(twisted需下载后本地安装,下载地 址:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted) (版本选择如下图,版本后面有解释,请根据自己实际选择)

(4).安装pywin32: pip install pywin32

(注意:以上安装步骤一定要确保每一步安装都成功,没有报错信息,如有报错自行百度解决)

(5).安装scrapy: pip install scrapy

(注意:以上安装步骤一定要确保每一步安装都成功,没有报错信息,如有报错自行百度解决)

(6).成功验证:在cmd命令行输入scrapy,显示Scrapy1.6.0-no active project,证明安装成功

2. 创建项目等--命令介绍

# 1.手动创建一个目录test

# 2.在test文件夹下创建爬虫项目为spiderpro: *(命令)scrapy startproject spiderpro(项目名称) *

# 3.进入项目文件夹: cd spiderpro

# 4.创建爬虫文件: scrapy genspider 爬虫名 域名(---意思只能爬取在百度以内的东西)

# 5.启动scrapy的命令:scrapy crawl +'爬虫名'

# 6.解析方法 extract_first()--->目标数据,如果拼错了,不飘红也不报错,就是拿不到数据。

# 7.当在scrapy的框架中,获取列表数据的一条用---extract_first()

# 8.当在scrapy的框架中,获取列表的所有数据用---extract()

3. 项目目录介绍

spiderpro

spiderpro # 项目目录

__init__

spiders:爬虫文件目录

__init__

tests.py:爬虫文件

items.py:定义爬取数据持久化的数据结构

middlewares.py:定义中间件

pipelines.py:管道,持久化存储相关

settings.py:配置文件

venv:虚拟环境目录

scrapy.cfg: scrapy 项目部署有关

#说明:

1).spiders:其内包含一个个Spider的实现, 每个Spider是一个单独的文件

2).items.py:它

定义了Item数据结构, 爬取到的数据存储为哪些字段

3).pipelines.py:它定义Item Pipeline的实现

4).settings.py:项目的全局配置

5).middlewares.py:定义中间件, 包括爬虫中间件和下载中间

6).scrapy.cfg:它是scrapy项目的配置文件, 其内定义了项目的配置路径, 部署相关的信息等

4. 框架scrapy介绍:五大核心组件与数据流向

# 架构:

1).Scrapy Engine: 这是引擎,负责Spiders、ItemPipeline、Downloader、Scheduler中间的通 讯,信号、数据传递等等!

2).Scheduler(调度器): 它负责接受引擎发送过来的requests请求,并按照一定的方式进行整理排列, 入队、并等待Scrapy Engine(引擎)来请求时,交给引擎。

3).Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到 的Responses交还给Scrapy Engine(引擎),由引擎交给Spiders来处理,

4).Spiders:它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进 的URL提交给引擎,再次进入Scheduler(调度器),

5).Item Pipeline:它负责处理Spiders中获取到的Item,并进行处理,比如去重,持久化存储(存数据 库,写入文件,总之就是保存数据用的)

6).Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件

7).Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spiders中 间‘通信‘的功能组件(比如进入Spiders的Responses;和从Spiders出去的Requests)

# 工作流:

spider --> 引擎 --> 调度器 --> 引擎 --> 下载器 --> 引擎 --> spider --> 引擎 --> 管道 --> 数据库

1).spider将请求发送给引擎, 引擎将request发送给调度器进行请求调度

2).调度器把接下来要请求的request发送给引擎, 引擎传递给下载器, 中间会途径下载中间件

3).下载携带request访问服务器, 并将爬取内容response返回给引擎, 引擎将response返回给 spider

4).spider将response传递给自己的parse进行数据解析处理及构建item一系列的工作, 最后将item 返回给引擎, 引擎传递个pipeline

5).pipe获取到item后进行数据持久化

6).以上过程不断循环直至爬虫程序终止

#__init__初始化方法 __new__() 构造方法 :当spider接收到res响应后定义类,实例化对象存到属性中也就是存在内存上,下一步才准备存到数据库

5. scrapy--爬取科客网站

# 1. itmes.py 里配置想要抓取的字段(想要抓取多少内容)

# -*- coding: utf-8 -*-

# Define here the models for your scraped items

#

# See documentation in:

# /en/latest/topics/items.html

import scrapy

# 所写的字段

class ProItem(scrapy.Item):

# define the fields for your item here like:

img = scrapy.Field() ******

title = scrapy.Field() ******

image_url = scrapy.Field() *****所需代码

# 2. 在自己定义的爬虫py文件中

# 定义了爬取数据的行为, 定义了数据解析的规则

import scrapy

# 将解析好的数据需要需要实例化存在一个属性中

from ..items import ProItem

class MyproSpider(scrapy.Spider):

name = 'mypro' # 爬虫名, 启动项目时用

# allowed_domains = [''] # # 定义了爬取的范围 ,可注释掉,如果不注释则影响爬虫效果

start_urls = ['/'] ## 起始url, 项目启动时, 会自动向起始url发起请求

#解析方法

def parse(self, response):

#用response响应进行数据解析--》xpath解析的并不是一个真实的列表

div_list = response.xpath('//article[contains(@class,"article")]')

for i in div_list:

title = i.xpath('./div/h2/a/text()').extract_first()

href = i.xpath('./div/h2/a/@href').extract_first()

src = i.xpath('./div/a/img/@lazy_src').extract_first()

#实例化对象

item = ProItem()

#将解析的数据找其相对应的字段进行赋值----存储到item属性中(字典)

item['title'] = title

item['image_url'] = href

item['img'] = src

# yield 将数据发送给管道Pipelines

yield item

# 3.在pipelines.py 里进行MongoDB存储

# 导入pymongo模块

import pymongo

class ProPipeline(object):

def process_item(self, item, spider):

# python 与 MongoDB 数据库交互

conn = pymongo.MongoClient('localhost',27017)

# 创建或连接库

db = conn.keke

# 创建或连接表

table = db.kuke

table.insert_one(dict(item))

return item

# 4. 在settinds.py 里修改所需要的配置

# 此示例中配置文件中的配置的项, 注意是不是全部的配置, 是针对该项目增加或修改的配置项

# 忽略robots协议 -----》把True改成False(代表不遵守协议)

ROBOTSTXT_OBEY =False

# UA伪装 ----》换成自己的 UA

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36'

# 管道类打开以防数据发送不过来 --->把注释解掉即可

ITEM_PIPELINES ={ 'qsbk.pipelines.QsbkPipeline':300, }

6. scrapy实现多页爬取

1). #在起始url中,输入有顺序的每页地址,然后格式化输出。

例:

start_urls = ['/evarenti/RenTiCaiHui/14_%s.html' % for i in range(1,3)]

2). # spider编码在原基础之上, 构建其他页面的url地址, 并利用scrapy.Request发起新的请求, 请求的 回调函数依然是parse:

#声明page页码数为第一页

page = 1

base_url = '/list-1-%s.html'

# 爬取一共四页的数据所以小于4,因为每次self.page+1,当到第三页时依次加一所以就四页了,要几页写几页

if self.page < 4:

#格式化拼接页码数

page_url = base_url%self.page

#依次加一

self.page += 1

#爬取多页收据,将yield函数里 用scrapy.Request再次请求,callback回调其自身函数就OK

yield scrapy.Request(url=page_url, callback=self.parse)

# (其他文件不用改动)

#### 准确使用

import scrapy

from ..items import BizhiItem

class MybizhiSpider(scrapy.Spider):

name = 'mybizhi'

# allowed_domains = ['']

1).# start_urls = ['/bizhi/mingxing/%s.html'% i for i in range(1,5)]

2). #定义起始url为第一页数据

start_urls = ['/bizhi/mingxing/1.html']

#定义page=1从第一页开始

page = 1

def parse(self, response):

div_list = response.xpath('//li[@class="photo-list-padding"]')

for div in div_list:

title = div.xpath('./a/span/em/text()').extract_first()

image_url = div.xpath('./a/img/@src').extract_first()

detail_url = div.xpath('./a/@href').extract_first()

item = BizhiItem()

item['title'] = title

item['image_url'] = image_url

item['detail_url'] = detail_url

# 输入爬取多少页的数据

if self.page < 4:

#每次加一页,直到全部爬取结束

self.page += 1

#将每页拼接到页码上

url = '/bizhi/mingxing/%s.html'%self.page

#再次请求,调用自身函数

yield scrapy.Request(url=url,callback=self.parse)

#最后将数据发送到管道,存入MongoDB

yield item

7. scrapy解析笑话网站例

import scrapy

from ..items import SkillItem

class MyskillSpider(scrapy.Spider):

name = 'myskill'

# allowed_domains = ['']

start_urls = ['/?bmjmxa=ziqzh']

#自己定义的函数

def detail_parse(self, response):

# 将回调传来的值,取出

item = response.meta['item']

*****

当在scrapy的框架中,获取列表数据的一条用---extract_first()

当在scrapy的框架中,获取列表的所有数据用---extract()

*****

detail_url = response.xpath('//span[@id="text110"]/p/text()').extract()

# 解析的目标数据是一个大字典用 '' .join()拼接使其变成字符串

item['detail_url'] = ''.join(detail_url)

# 最后在发送到管道

yield item

def parse(self, response):

div_list = response.xpath('//div[@class="newcontent l_left"]/ul/li')

for div in div_list:

title = div.xpath('./a/text()').extract_first()

link = div.xpath('./a/@href').extract_first()

item = SkillItem()

item['title'] = title

item['link'] = ''+link

# 爬取网页xpath解析,实例化对象将其相对应的字段进行赋值,获取详情页连接再次发起去请求,

# 用yield的SCRAPY.Request的内置参数callback回调一个函数,meta将值传送到回调函数

yield scrapy.Request(url=''+link,callback=self.detail_parse,meta={'item':item})

8. scrapy框架下载图片代码

1).item.py定义字段赋值

import scrapy

class BizhiItem(scrapy.Item):

# 定义需要的字段与爬虫文件相关联

title = scrapy.Field()

image_url = scrapy.Field()

detail_url = scrapy.Field()

2). 爬虫py文件

import scrapy

# 导入item的类名内容

from ..items import BizhiItem

class MybizhiSpider(scrapy.Spider):

name = 'mybizhi'

# allowed_domains = ['']

# start_urls = ['/bizhi/mingxing/%s.html'% i for i in range(1,5)]

start_urls = ['/bizhi/mingxing/1.html']

def pic_parse(self, response):

#接收传送的参数取出来

item = response.meta['item']

#图片的名字按照 / 切割

name = item['image_url'].split('/')[-1]

# 响应内容,获取图片的二进制流

content = response.body

# open 打开的文件,***************imgs文件(图片存储的文件)一定要跟scrapy.cfg平级,不然拿不到***********

with open('./imgs/%s'%name,'wb') as f:

#把二进制流写入

f.write(content)

# 逻辑工作结束后,最后将item发送至管道

yield item

def parse(self, response):

div_list = response.xpath('//li[@class="photo-list-padding"]')

for div in div_list:

title = div.xpath('./a/span/em/text()').extract_first()

image_url = div.xpath('./a/img/@src').extract_first()

detail_url = div.xpath('./a/@href').extract_first()

item = BizhiItem()

item['title'] = title

item['image_url'] = image_url

item['detail_url'] = detail_url

# 再次请求一个图片地址链接,把赋值好的属性传送过去。

yield scrapy.Request(url=image_url,callback=self.pic_parse,meta={'item':item})

3).piplines.py 管道py存数据

import pymongo

class BizhiPipeline(object):

def process_item(self, item, spider):

# 与MongoDB数据库交互 域名加端口

conn = pymongo.MongoClient('localhost',27017)

# 创建数据库或者连接数据库

db = conn.xxxxx

# 创建表或者连接表

table = db.yyyyy

# 插入数据

table.insert_one(dict(item))

return item

4).settings.py配置内容

# 此示例中配置文件中的配置的项, 注意是不是全部的配置, 是针对该项目增加或修改的配置项

# 忽略robots协议 -----》把True改成False(代表不遵守协议)

ROBOTSTXT_OBEY =False

# UA伪装 ----》换成自己的 UA

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36'

# 管道类打开以防数据发送不过来 --->把注释解掉即可

ITEM_PIPELINES ={ 'qsbk.pipelines.QsbkPipeline':300, }

9. scrapy 篡改请求与响应,item丢弃

1).-- UA池--->大量UA----->拦截请求 ---->换UA

2).-- IP代理池---->请求---->换IP

3).-- cookie池---->换cookie

4).-- 拦截响应(动态加载)--selenium抓取(res.scrapyres.selenium)--给引擎--->spider

10. scrapy中间件--分类,作用

# 中间件分类

- 下载中间键:DownloadMiddleware

- 爬虫中间件:SpiderMiddleware

# 中间件的作用

- 下载中间件: 拦截请求与响应, 篡改请求与响应

- 爬虫中间件: 拦截请求与响应, 拦截管道item, 篡改请求与响应, 处理item

# 下载中间件的主要方法:

process_request #获取拦截非异常请求

process_response #获取拦截所有响应

process_exception #获取拦截异常请求

11. 下载中间件拦截请求, 使用代理ip案例

1).# spider编码:

import scrapy

class DlproxySpider(scrapy.Spider):

name = 'dlproxy'

# allowed_domains = ['']

start_urls = ['/s?wd=ip']

def parse(self, response):

with open('baiduproxy.html', 'w', encoding='utf-8') as f:

f.write(response.text)

2).# Downloadermiddleware编码:

def process_request(self, request, spider):

#

request.meta['proxy'] = 'http://111.231.90.122:8888'

return None

3).# settings编码

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

ROBOTSTXT_OBEY = False

# 把下载中间件注释打开

Downloader_MIDDLEWARES = {

'proxy.middlewares.ProxySpiderMiddleware': 543,

}

12. 下载中间件实现UA池

1). 在middlewares.py

from scrapy import signals

# ua导包需下载 pip install fake-useragent

from fake_useragent import UserAgent

#导入随机

import random

#实例化

ua_chrome = UserAgent()

#定义ua池

ua_pool = []

for i in range(10):

ua = ua_chrome.Chrome

ua_pool.append(ua)

# 拦截请求:拦截非异常的请求

def process_request(self, request, spider):

# request.meta['proxy'] = 'http://60.217.64.237:38829'

request.headers['User-Agent'] = random.choice(ua_pool)

return None

# 拦截响应:拦截的是所有响应

def process_response(self, request, response, spider):

print('*'*50)

***** request.headers['User-Agent'] *****取ua

print(request.headers['User-Agent'])

print('*'*50)

return response

2). 需要注释的地方,跟修改的地方 在settings.py 里设置

1.USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

2.ROBOTSTXT_OBEY = False

#把下载中间件注释开

3.DOWNLOADER_MIDDLEWARES = {

'proxy.middlewares.ProxyDownloaderMiddleware': 543,

}

3). #在起始url里,用列表推导式里面加入for循环,依次循环就可以在ua池里任意获取

start_urls = ['/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip&rsv_pq=cf95e45f000b8d2b&rsv_t=74b1V5e7UWXPDK6YWqzjFSXv%2B9wpMSDHZrF4HMP0TnouyBZ4o6hj%2FuiRWgI&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=2&rsv_sug1=1&rsv_sug7=100&rsv_sug2=0&inputT=1452&rsv_sug4=1453' for i in range(3)]

*************************************************************

简单的UA池

from fake_useragent import UserAgent

for i in range(10):

USER_AGENT = UserAgent().random

print(USER_AGENT)

*************************************************************

13. selenium与scrapy框架对接

1).item.py里

# 定义爬取的字段

import scrapy

class NewsItem(scrapy.Item):

title = scrapy.Field()

image_url = scrapy.Field()

*****************************************************************************************

2).在爬虫的py里

import scrapy

from ..items import NewsItem

from selenium import webdriver

class MynewsSpider(scrapy.Spider):

name = 'mynews'

# allowed_domains = ['']

# 在起始的url里定义网址爬取的范围

start_urls = ['/domestic/']

# 实例化selenium对象,executable_path=‘驱动程序的工具路径’

browser = webdriver.Chrome(executable_path=r'D:\爬虫段位\day13\news\chromedriver.exe')

def image_parse(self, response):

item = response.meta['item']

content = response.body

name = item['image_url'].split('/')[-1].split('?')[0]

with open('./imgs/%s'% name,'wb') as f:

f.write(content)

yield item

def parse(self, response):

# 正常的xpath解析

div_list = response.xpath('//div[contains(@class,"news_article")]')

for div in div_list:

title = div.xpath('./div/div/h3/a/text()').extract_first()

image_url = div.xpath('./a/img/@src').extract_first()

item = NewsItem()

item['title'] = title

item['image_url'] = image_url

yield scrapy.Request(url=image_url,callback=self.image_parse,meta={'item':item})

*****************************************************************************************

3).pipelines.py里 存数据

import pymongo

class NewsPipeline(object):

def process_item(self, item, spider):

conn = pymongo.MongoClient('localhost',27017)

db = conn.news

table = db.wynews

table.insert_one(dict(item))

return item

*****************************************************************************************

4).middlewares.py里

from scrapy import signals

from scrapy.http import HtmlResponse

# 因为获取js的动态数据所以属于响应拦截

def process_response(self, request, response, spider):

# 在爬虫py里已导入自动化工具,用spider导进来运用

browser = spider.browser

# 在第一次请求的js动态数据,判断拦截后的响应的url在不在起始url里

# 注意爬取的连接, 必要时判断

if response.url in spider.start_urls:

# 用自动化工具进行请求页面

browser.get(request.url)

# js下拉框 下拉一次

js = 'window.scrollTo(0,document.body.scrollHeight)'

# 把js 代码放入 browser.execute_script(js)

browser.execute_script(js)

# 获取响应后的页面赋给变量

html = browser.page_source

# 将拦截后获取的数据在发送给爬虫文件解析----

# 固定参数 url=browser.current_url(currnet_url代表当前请求的url),body=html(body请求体),

# encoding='utf-8'(文本编码),request=request(伪装成请求头,返回爬虫网页))

return HtmlResponse(url=browser.current_url,body=html,encoding='utf-8',request=request)

return response

*****************************************************************************************

5).settings.py设置

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

ROBOTSTXT_OBEY = False

DOWNLOADER_MIDDLEWARES = {

'news.middlewares.NewsDownloaderMiddleware': 543,

}

ITEM_PIPELINES = {

'news.pipelines.NewsPipeline': 300,

}

14. scrapy 持久化与MongoDB交互

# 核心方法讲解:

open_spider(self, spider): spider开启是被调用 close_spider(self, spider): spider关闭是被调用 from_crawler(cls, crawler): 类方法, 用@classmethod标识, 可以获取配置信息

Process_item(self, item, spider): 与数据库交互存储数据, 该方法必须实现

***** # 重点: 所有的方法名都必须一致

1). #在管道pipelines.py

import pymongo

class XiaoxiaoPipeline(object):

# 初始化方法, __new__: 构造方法, 在内存中开辟一块空间

def __init__(self,mongo_uri,mongo_db):

self.mongo_uri = mongo_uri

self.mongo_db = mongo_db

def open_spider(self,spider):

self.client = pymongo.MongoClient(self.mongo_uri)

self.db = self.client[self.mongo_db]

@classmethod

# 调用配置中定义的方法

def from_crawler(cls,crawler):

return cls(

mongo_uri = crawler.settings.get('MONGO_URI'),

mongo_db = crawler.settings.get('MONGO_DB')

)

def process_item(self, item, spider):

self.db['myxiao'].insert(dict(item))

return item

def close_spider(self,spider):

self.client.close()

2). # 爬虫文件正常爬取思路

import scrapy

from ..items import XiaoxiaoItem

class MyxiaoSpider(scrapy.Spider):

name = 'myxiao'

# allowed_domains = ['']

start_urls = ['/']

def parse(self, response):

div_list = response.xpath('//article[@class="post"]')

for div in div_list:

title = div.xpath('./div/h1/a/text()').extract_first()

cont = div.xpath('./div[2]/p/text()').extract()

content = ''.join(cont)

item = XiaoxiaoItem()

item['title'] = title

item['content'] = content

yield item

3). # settings.py 配置

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

ROBOTSTXT_OBEY = False

ITEM_PIPELINES = {

# 跟中间件的类相对应,后面的值,谁小谁先运行

'xiaoxiao.pipelines.XiaoxiaoPipeline': 300,

}

MONGO_URI = 'localhost'

MONGO_DB = 'xiaoxiao'

15. scrapy 持久化与Mysql交互

1). # 在中间管道.py里

import pymysql

class MyXiaoxiaoPipeline(object):

def __init__(self,host,database,user,password,port):

self.host = host

self.database = database

self.user = user

self.password = password

self.port = port

def open_spider(self,spider):

self.client = pymysql.connect(self.host,self.user,self.password,self.database,charset='utf8',port=self.port)

self.corsor = self.client.cursor()

@classmethod

def from_crawler(cls,crawler):

return cls(

host=crawler.settings.get('MYSQL_HOST'),

database = crawler.settings.get('MYSQL_DATABASE'),

user = crawler.settings.get('MYSQL_USER'),

password = crawler.settings.get('MYSQL_PASSWORD'),

port = crawler.settings.get('MYSQL_PORT')

)

def process_item(self, item, spider):

data = dict(item)

# data.keys()---->获取所有的键,字段----(title,content)

keys = ','.join(data.keys())

# 获取所有的值

values = ','.join(['%s']*len(data))

sql = 'insert into %s (%s) values (%s)'% ('myxiao',keys,values)

self.corsor.execute(sql,tuple(data.values()))

# 提交

mit()

return item

2).在settings.py 里

ITEM_PIPELINES = {

'xiaoxiao.pipelines.MyXiaoxiaoPipeline': 295,

}

MYSQL_HOST = 'localhost'

MYSQL_DATABASE = 'xiaoxiao'

MYSQL_USER = 'root'

MYSQL_PASSWORD = ''

MYSQL_PORT = 3306

ROBOTSTXT_OBEY = False

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

16. 基于crawlSpider的全站数据爬取

1).# 项目的创建

scrapy startproject projectname

scrapy genspider -t crawl spidername

2).# crawlspider全站数据爬取:

- CrawlSpider是一个爬虫类, 是scrapy.spider的子类, 功能比spider更强大.

- CrawlSpider的机制:

- 连接提取器: 可以根据指定的规则进行连接的提取

- 规则解析器: 根据指定的规则对响应数据进行解析

3))# 案例: 基于CrawlSpider对笑话网进行全站深度数据爬取, 抓取笑话标题与内容, 并存储于MongoDB中

# item编码:

import scrapy

class JokeItem(scrapy.Item):

title = scrapy.Field()

content = scrapy.Field()

# spider编码:

import scrapy

from scrapy.linkextractors import LinkExtractor

from scrapy.spiders import CrawlSpider, Rule

from..items import JokeItem

class ZSpider(CrawlSpider):

name = 'z'

# allowed_domains = ['']

start_urls = ['/lengxiaohua/']

link = LinkExtractor(allow=r'/lengxiaohua/\d+.html')

link_detail = LinkExtractor(allow=r'.*?\d+\.html')

rules = ( Rule(link, callback='parse_item', follow=True), Rule(link_detail, callback='parse_detail'), )

def parse_item(self, response):

pass

def parse_detail(self, response):

title = response.xpath('//h1[@class="article- title"]/text()').extract_first()

content = response.xpath('//div[@class="article- text"]//text()').extract()

content = ''.join(content)

if title and content:

item = JokeItem()

item["title"] = title

item["content"] = content

print(dict(item))

yield item

# pipeline编码:

class JokePipeline(object):

def __init__(self, mongo_uri, mongo_db):

self.mongo_uri = mongo_uri

self.mongo_db = mongo_db

@classmethod

def from_crawler(cls, crawler):

return cls(

mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DB') )

def open_spider(self, spider):

self.client = pymongo.MongoClient(self.mongo_uri)

self.db = self.client[self.mongo_db]

def process_item(self, item, spider): self.db["joke"].insert(dict(item))

return item

def close(self, spider):

self.client.close()

17. 增量式爬虫

# 概念:

- 检测网站数据更新, 只爬取更新的内容

- 核心:

去重

- url

- 数据指纹

# 增量式爬虫: 电影名称与电影类型的爬取 # url: https://www.4567tv.co/list/index1.html

#item.py

import scrapy

class MoveItem(scrapy.Item):

title = scrapy.Field()

lab = scrapy.Field()

#爬虫py文件

import scrapy

from ..items import MoveItem

from redis import Redis

class MymoveSpider(scrapy.Spider):

name = 'mymove'

# allowed_domains = ['']

start_urls = ['https://www.4567tv.co/list/index1.html']

# 连接redis数据库

conn = Redis('localhost',6379)

def detail_parse(self, response):

title = response.xpath('//div[@class="ct-c"]/dl/dt/text()').extract_first()

lab = response.xpath('//div[@class="ee"]/text()').extract_first()

item = MoveItem()

item['title'] = title

item['lab'] = lab

yield item

def parse(self, response):

link = response.xpath('//div[contains(@class,"index-area")]/ul/li/a/@href').extract()

for i in link:

# 如果link已经存在, 则ret为0, 说明该数据爬过来

# 如果link不存在, 则ret为1, 说明没爬虫

ret = self.conn.sadd('link',i) # 把需要的数据存入redis库

# 反向思绪

if ret:

print('有新数据, 可以爬取---------------------------------')

yield scrapy.Request(url='https://www.4567tv.co'+i,callback=self.detail_parse)

else:

print('没有数据更新, 不需要爬取###############################')

# pipelines.py

import pymongo

class MovePipeline(object):

def process_item(self, item, spider):

conn = pymongo.MongoClient('localhost',27017)

db = conn.move

table = db.mv

table.insert_one(dict(item))

return item

# settings.py

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'

ROBOTSTXT_OBEY = False

ITEM_PIPELINES = {

'move.pipelines.MovePipeline': 300,

}

18. redis安装

1.将安装包解压到一个文件夹下: 如 D:\redis, 会在该文件夹下看到所有redis的文件

2.将该文件夹添加至系统环境变量中

3.在解压的文件目录的地址栏上输入cmd, 在cmd窗口中输入redis-server ./redis.windows.conf , 然后回车, 如果出现下面图片的样子说明redis安装成功了

*****************************************************************************************

启动redis服务端

cmd:redis-server ./redis.windows.conf

启动redis客户端

cmd:redis-cli

# 查询所有键

keys *

# 删除键

del 键名

# 添加数据

sadd name ()

# 查询所有数据

lrange xw:item 0 -1

# 存储

set name laowang

OK# 取出来

127.0.0.1:6379> get name

"laowang"

127.0.0.1:6379>

19. mongo的分组聚合统计用django显示

# 连接Mongo 数据库

import pymongo

conn = pymongo.MongoClient('localhost',27017)

db = conn.fqxh

table = db.xh

def login(request):

# find()查询所有的数据

res = table.find()

return render(request,'aaa.html',locals())

def index(request):

# 对都需要的值进行排序ASC是正序,DESC倒叙

res = table.find().sort([('times_date',pymongo.ASCENDING)])

return render(request,'index.html',locals())

def indexs(request):

ret = table.aggregate([{'$group':{'_id':'$times_date','cc':{'$sum':'$count'}}}])

li = []

for i in ret:

i['date'] = i['_id']

li.append(i)

return render(request,'indexs.html',locals())

def total(request):

# Mongo的分组聚合统计,按照日期分

res = table.aggregate([{'$group':{'_id':'$times_date','cc':{'$sum':1}}}])

li = []

for i in res:

i['date'] = i['_id']

li.append(i)

return render(request,'ccc.html',locals())

如果觉得《pythonscrapy_Python Scrapy框架》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。