目录
昨日回顾
# 1 xpath
/ //和能看懂
用:去copy
## 2 selenium
驱动浏览器,模拟浏览器行为(为解决js执行的问题)
page_source
查找标签:点击,键盘输入,清空,写文字
执行js:打开标签,滑动屏幕
cookie(重要):可以手动通过selenium登陆进去,取到cookie,搭建cookie池
动作链:很炫,基本用处很少
## 3 抓包工具的使用
抓手机包:移动开发的后端(postman),抓包工具
移动开发人员在你手机上装一个连接你机器的app
app--resful接口-》10.0.0.1
app-------抓包工具(可以看到发送和接受到的数据什么样)----------->你电脑的ip(跑着项目),在你电脑上加断点
scrapy框架
1.介绍
Scrapy 是一个基于 Twisted 的异步处理框架,是纯 Python 实现的爬虫框架,其架构清晰,模块之间的耦合程度低,可扩展性极强,可以灵活完成各种需求。我们只需要定制开发几个模块就可以轻松实现一个爬虫。
1.1 框架的生命周期
它可以分为如下的几个部分。
- Engine,引擎,用来处理整个系统的数据流处理,触发事务,是整个框架的核心。
- Item,项目,它定义了爬取结果的数据结构,爬取的数据会被赋值成该对象。
- Scheduler, 调度器,用来接受引擎发过来的请求并加入队列中,并在引擎再次请求的时候提供给引擎。
- Downloader,下载器,用于下载网页内容,并将网页内容返回给蜘蛛。
- Spiders,蜘蛛,其内定义了爬取的逻辑和网页的解析规则,它主要负责解析响应并生成提取结果和新的请求。
- Item Pipeline,项目管道,负责处理由蜘蛛从网页中抽取的项目,它的主要任务是清洗、验证和存储数据。
- Downloader Middlewares,下载器中间件,位于引擎和下载器之间的钩子框架,主要是处理引擎与下载器之间的请求及响应。
- Spider Middlewares, 蜘蛛中间件,位于引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛输入的响应和输出的结果及新的请求。
1.1 框架流程
Scrapy 中的数据流由引擎控制,其过程如下:
- Engine 首先打开一个网站,找到处理该网站的 Spider 并向该 Spider 请求第一个要爬取的 URL。
- Engine 从 Spider 中获取到第一个要爬取的 URL 并通过 Scheduler 以 Request 的形式调度。
- Engine 向 Scheduler 请求下一个要爬取的 URL。
- Scheduler 返回下一个要爬取的 URL 给 Engine,Engine 将 URL 通过 Downloader Middlewares 转发给 Downloader 下载。
- 一旦页面下载完毕, Downloader 生成一个该页面的 Response,并将其通过 Downloader Middlewares 发送给 Engine。
- Engine 从下载器中接收到 Response 并通过 Spider Middlewares 发送给 Spider 处理。
- Spider 处理 Response 并返回爬取到的 Item 及新的 Request 给 Engine。
- Engine 将 Spider 返回的 Item 给 Item Pipeline,将新的 Request 给 Scheduler。
- 重复第二步到最后一步,直到 Scheduler 中没有更多的 Request,Engine 关闭该网站,爬取结束。
通过多个组件的相互协作、不同组件完成工作的不同、组件对异步处理的支持,Scrapy 最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。
五大组件
引擎:大总管,总的控制数据流动
调度器:去重,加入队列
下载器:负责下载,加载数据
爬虫:咱们主要在这写,解析response和重新发起请求
项目管道:持久化相关
二大中间件
爬虫中间件:爬虫和引擎之间(用的少)
下载中间件:引擎和下载器之间(加代理,加cookie,修改user-agent,集成selenium)
2.安装
mac/Linux:
pip install scrapy
windows: (两种方式)
1. pip install scrapy
2. 如果报错,以下
-pip install wheel (xxx.whl文件安装模块)
-下载pywin32
-pip install pywin32 或者 下载.exe文件安装https://sourceforge.net/projects/pywin32/files/pywin32/
-下载twisted的wheel文件
- 执行pip iinstall 下载目录Twisted-17.9.0-cp36-cp36m-win_amd64.whl(可以直接手动拖放至控制台)
3.创建项目
通过命令行
# 创建项目
scrapy startproject 项目名
# 创建爬虫
#(django中创建app)在spiders文件夹下创建一个py文件,一个py文件就是一个爬虫(不要注册,没有注册一说)
scrapy genspider 爬虫名 爬取的地址
scrapy genspider chouti dig.chouti.com
# 打开项目,pycharm打开
运行爬虫
# 命令行运行
scrapy crawl 爬虫名
scrapy crawl 爬虫名 --nolog # 不打印日志
或者更改log级别: LOG_LEVEL='ERROR' # 也可不打印日志
# pycharm运行
设置
在项目目录下创建一个py文件,假设叫main.py,点击右键执行即可执行爬虫,等同于命令
from scrapy.cmdline import execute
execute(['scrapy','crawl','chouti','--nolog'])
保存数据到本地文件
# 保存文件的指令
from scrapy.cmdline import execute
execute(['scrapy', 'crawl', 'lianjia', '-o', 'items.csv','--nolog'])
目录介绍
-scarpyfirst 项目名
-scrapy.cfg 上线相关的(不用管)
-scrapyfirst 文件夹
-spiders文件夹 所有的爬虫写在这里面
-chouti.py 一个py文件就是一个爬虫(类似于django的app)
-items.py :配合管道,做数据存储(类似于django中models.py 写一个个的模型类)
-middlewares.py :中间件(爬虫中间件,下载中间件都写在这里面)
-pipelines.py :管道,持久化相关,数据存储卸载这
-settings.py :配置文件相关
setting介绍
#配置文件全是大写
ROBOTSTXT_OBEY = True #是否遵循爬虫协议,如果是true,基本上网站都爬不了,遵循要爬取网站的爬虫协议,一般设置成false
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'
LOG_LEVEL='ERROR' # 只打印错误信息
# 控制持久化的类执行顺序
ITEM_PIPELINES = {
'mypachong.pipelines.MypachongMySQLPipeline': 100, # 优先级,数值越小,优先级越高
'mypachong.pipelines.MypachongPipeline': 300, # 优先级,数值越小,优先级越高
}
使用--爬取天猫
自定义启动文件run.py
#-*- coding: utf-8 -*-
#!/usr/bin/env python3
' 启动文件 '
__author__ = 'Fwzzz'
# 代替cmd的命令
from scrapy.cmdline import execute
execute(['scrapy','crawl','chouti','--nolog'])
# execute(['scrapy','crawl','chouti'])
爬虫文件
# -*- coding: utf-8 -*-
import scrapy
from urllib.parse import urlencode
from mypachong import items
# 爬取天猫
class ChoutiSpider(scrapy.Spider):
# 爬虫名
name = 'chouti'
# 允许爬取的域名
allowed_domains = ['www.tmall.com']
# 初始请求 自行向域名发送get请求获取数据
# start_urls = ['http://www.baidu.com/']
# 自定义初始请求
# 实例化获取初始请求对象
def __init__(self,*args,**kwargs):
# 继承父类的属性
super(ChoutiSpider,self).__init__(*args,**kwargs)
# 定义接口的url
self.api = 'http://list.tmall.com/search_product.htm?'
# 定义搜索的接口参数 (通过urlencode拼接)
self.param = {
'q' :'女装大佬',
'totalPage' :1,
'jumpto' :1
}
# 想要自行发送定义请求,重写Spider类中的start_requests方法
def start_requests(self):
# 获取主页的url
url = self.api + urlencode(self.param)
# 搜索页发送请求
# callback 回调函数,进行处理获取数据 并指定dont_filter=True 链接不去重
yield scrapy.Request(url=url,callback=self.getpage,dont_filter=True)
# 获取响应,进行数据的清洗(获取总页码)
def getpage(self,response):
# 进行解析
page = response.css('[name="totalPage"]::attr(value)').extract_first()
# print(page) # 30
# 将接口的url页数更换
self.param['totalPage'] = int(page)
# 发送新的请求,获取所有页面的数据
# for i in range(1,self.param['totalPage']+1):
for i in range(1,2):
self.param['jumpto'] = i
# 拼接url
url = self.api + urlencode(self.param)
# 发送请求到新的回调函数中去
yield scrapy.Request(url,callback=self.get_info,dont_filter=True)
# 解析页面中的数据
def get_info(self, response):
# 获取数据 价格,商品名,交易量,图片
# 先获取当前页面的所有商品标签对象
product_list = response.css('.product ')
for product in product_list:
# 解析单数据
good_title = product.css('.productTitle a::attr(title)').extract_first()
good_price = product.css('.productPrice em::attr(title)').extract_first()
good_img = product.css('.productImg img::attr(src)').extract_first()
# 图片懒加载解决
if not good_img:
good_img = product.css('.productImg img::attr(data-ks-lazyload)').extract_first()
# print(good_title,good_img,good_price)
# 返回数据给items或者继续发送请求
item = items.MypachongItem() # 实例化获得items对象
# 将数据封装成items对象
item['good_title'] = good_title
item['good_price'] = good_price
item['good_img'] = good_img
# 这里需要设置setting文件中的ITEM_PIPELINES,yield之后并触发pipelines
yield item
items文件 控制接收持久化字段
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
# 规定了items接受的那些对象
class MypachongItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
good_title = scrapy.Field()
good_price = scrapy.Field()
good_img = scrapy.Field()
pipelines.py 持久化存储
# -*- coding: utf-8 -*-
# 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
import pymysql
# 存数据 --文件保存方式
class MypachongPipeline(object):
def open_spider(self,spider):
'''爬虫打开时触发一次'''
print('我打开了')
self.f = open('a.txt','w')
def process_item(self, item, spider):
'''每次数据都会触发'''
# print('在items后我被触发了')
self.f.write(item['good_title']+item['good_price']+item['good_img'])
self.f.write('
')
return item
def close_spider(self,spider):
'''爬虫关闭之后触发一次'''
print('我关闭了')
# 存数据 --MySQL保存方式 需要去settings文件中设置ITEM_PIPELINES优先级
class MypachongMySQLPipeline(object):
def open_spider(self,spider):
self.conn = pymysql.connect(
host='127.0.0.1',
user='root',
password='',
database='tianmao',
port=3306
)
print('我打开了mysql')
def process_item(self, item, spider):
cursor = self.conn.cursor()
sql = "insert into article (title,price,img) values ('%s','%s','%s')"%(item['good_title'],item['good_price'],item['good_img'])
# sql = f"insert into article (title,price,img) values ('{item['good_title']}','{item['good_price']}','{item['good_img']}')"
cursor.execute(sql)
# 提交
self.conn.commit()
def close_spider(self,spider):
self.conn.close()
print('我关闭了mysql')
settings.py
BOT_NAME = 'mypachong'
SPIDER_MODULES = ['mypachong.spiders']
NEWSPIDER_MODULE = 'mypachong.spiders'
ROBOTSTXT_OBEY = False
# 控制持久化的类执行顺序
ITEM_PIPELINES = {
'mypachong.pipelines.MypachongMySQLPipeline': 100, # 优先级,数值越小,优先级越高
'mypachong.pipelines.MypachongPipeline': 300, # 优先级,数值越小,优先级越高
}
4. scrapy的数据解析(重点)
css选择器
res.css('[name="tag"]::text').extract_first()
::text 获取标签内文本
::attr(属性) 获取标签属性值
# 需要与下面的extract想配合获取内容
.extract() 获取对象内容列表
.extract_first() 获取第一个
5. scrapy的持久化存储(重点)
详细使用参见上面的爬取天猫案例
第一种,通过命令:scrapy crawl chout -o aa.csv (用的比较少)
需要在parser解析方法中返回列表套字典的格式
第二种:通过管道方式(文件,数据,redis,mongodb),同时支持以多种方式存储
-1 在items.py中定义一个类,写属性(要存多少字段,就有多少属性)
-2 在爬虫中中解析出数据,把数据放到这个类对象中,然后 yield item
-3 在配置文件中配置:ChoutiPipeline对应pipelines.py中的类
ITEM_PIPELINES = {
'scrapyfirst.pipelines.ChoutiPipeline': 300, # 数字表示优先级,数字越小,优先级越高
}
-4 pipelines.py中写ChoutiPipeline类
-open_spider:开启时调用,打开文件,打开数据库连接
-process_item:存数据
-close_sapider:关闭时调用,关闭文件,关闭数据库连接
-总结:ITEM_PIPELINES可以写多个,有优先级的,数字越小,优先级越大,一定要注意process_item一定要return , 否则后续就拿不到item了
补充
1 pycharm系列激活
http://idea.medeming.com/jet/
2 ide,开发工具
你用什么ide?
ide系列:
java:eclipse(免费),myeclips(收费),idea(大部分java都用它)
python:pycharm,vscode(微软出的,免费,go,c,python,java)
go:goland,vscode。。
开发安卓:eclipse+adt,谷歌爸爸花钱买了jetbrains公司的版权idea+adt=androidstatdio(免费)
java,当年已经有大量的java开发人员,java可以直接无缝转过去,java虚拟机
开发ios:必须买Mac,Xcode(黑苹果)
jetbrains公司全家桶系列:idea,pycharm,webstom,goland,php
python体系
python基础,mysql,前端,web框架,爬虫,数据分析,人工智能
java体系
javase:基础,可以做桌面开发(基本上没有)
学完基础+安卓相关包的学习
javaee:web相关
javame:手机开发(不是安卓,ios,很古老的java手机软件)
区别:jdk,jre,jvm
jdk:java软件开发工具包,java开发人员需要安装
jre:java运行环境,java软件才能运行
jvm:java虚拟机 (java程序运行在虚拟机之上),跨平台,一次编码到处运行
c/c++:如果想在windwos上运行,需要在window上编译 exe
go----》编译之后---》直接可以运行 跨平台编译:在windows平台可以编译出liunx下可执行的文件
java写了代码----》编译--》jar包和war包 不是编译成直接可以运行的二进制(中间态)---》需要操作系统装java虚拟机(java虚拟机,要跑起来,至少就得占500m内存)