bs4
aa = bs('r','lxml')
div = aa.find('div',class_="values").text
li = aa.select(".classname > ul > li ")
xpath
from lxml import etree
tree = etree.HTML("page")
tree.xpath('/html/head/meta') 最左侧的/表示从根标签开始定位,非最左侧的/表示一个层级
tree.xpath('/html//meta') 非最左侧的//表示多个层级
tree.xpath('//head/meta') 最左侧的//表示从任意位置开始定位
定位标签:
tree.xpath('//div[@class="valus"]/p')
索引定位:tag[index]:索引从1开始
取文本:
/text() 直系文本内容 tree.xpath('//div[@class=""]/p[1]/text()')
//text() 所有文本内容
取属性:
/@attrname 返回属性内容
局部解析:
li_list = tree.xpath('//div[@class="slist"]/ul/li') 获取所有li
for li in li_list:
li.xpath('./a/img/@src') 进行局部解析,获取img的src
li.xpath('./a/text()) 局部解析,获取a的文本
cookie
自动处理:基于Session对象
获取一个Session对象:requests.Session()返回一个Session对象
Session对象的作用:
该对象可以像requests一样调用get和post发起指定的请求。在使用Session发请求的过程中,如果产生了Cookie,则cookie会被自动存储到该Session对象中,下次再次使用Session对象发起请求,刚该次请求就是携带cookie进行的请求发送。
验证码: 使用打码平台,
先从页面获取验证码图片,保存到本地,然后使用打码平台返回值。
如果请求参数中有乱序的参数,最好验证一下此参数是不是动态变化的
一般来说,动态变化的请求参数会被隐藏在前台页面中,需要去前面页面源码中 找
如果前台页面没有,可以基于抓包工具进行进行全局搜索
异步爬虫
from multiprocessing.dummy import Pool
pool =Pool(3) 开启3个线程
使用get_request 作为回调函数,需要基于异步的形式对urls列表中的每一个列表元素进行操作,
保证回调函数必须要有一个参数和返回返回值
result_list = pool.map(get_request,urls)
pool.map(pars,result_list) 解析 的回调
print(result_list)
selenium
scrapy
import scrapy
- 创建工程:cd ProName
- scrapy startproject ProName
- 目录结构:
- spiders:爬虫文件夹
- 必须要存放一个爬虫文件
- setting.py:工程的配置文件
- spiders:爬虫文件夹
- 创建爬虫源文件:
- scrapy genspider spidername www.xxx.com
- 编写对应的代码在爬虫文件中
- 执行工程
- scrapy crawl spidername
- 执行工程后,默认会输出工程所有的日志信息
- 指定类型日志的输出:
- setting.py:LOG_LEVEL = 'ERROR'
爬虫文件spiderName内容:
- name: 爬虫文件名称,该文件的唯一标识
- start_urls:起始url列表,存储的都是url,url可以被自动进行get请求
- parse方法: 请求后的数据解析操作
settings.py:
1.禁止robots ROBOTS_OBEY = False
2.指定日志类型:LOG_LEVEL = 'ERROR'
3.UA伪装
scrapy 数据解析
article_list = response.xpath() #xpath 和etree里的有区别
此处xpath返回的列表中存储的不时字符串,而是Selector对象,字符串数据在Selector中
需要使用extract()将data属性值取出,extract_first()将列表中第一个列表元素表示的Selector对象的data值取出
title = article.xpath('./div/[1]/h1/a/text()').extract_first()
持久化存储
- 基于终端指令的持久化存储
要求:只可以将parse返回值 存储到本地指定后缀的文本文件中
执行指令:scrapy crawl spiderName -o filepath
- 基于管道的持久化存储(重点)
- 在掉文件中进行数据解析
- 在items.py中定义相关属性
- 在解析出的数据中有几个数据,就要定义几个属性
- title = scrapy.Field()
- 在掉文件中将解析到的数据存储封闭到Item类型的对象中
- 将Item类型对象提交给管道
- 在管理文件(pipelines.py)中,接收掉文件提交过来的Item类型对象,且对其进行任意形式的换货存储操作
- 在配置文件中开启管道机制
ITEM_PIPELINES={'WANG.pipelines.wanline':300, }#300是优先级,数越小,优先级越高,自己写的类如mysql等,要加入到这里
- item 只会将数据提交给优先级最高的管道类
- 优先级高的管道类,需要return item,将item返回给下一个优先级的管道类
class FirstSpider(scrapy.Spider):
name = 'First'
allowed_domains = ['www.xxx.com']
start_urls = ['https://www.baidu.com/','https://www.taobao.com/'] #列表中存储的URL都会被进行get请求的发送
def parse(self, response):
title = article.xpath('./div/[1]/h1/a/text()').extract_first()
item = WangziproItem()
item['title'] = title
#将item提交给管道:
yield item
管道文件--pipelinies.py :
import pymysql
from redis import Redis
class wanPipeline(object):
fp = None
#重写父类的两个函数
def open_spider(self,spider):
#只在爬虫开始的时候打开一次)
self.fp = open('duanzi.txt','w',encoding='utf-8')
def close_spider(self,spider):
#只在爬虫结束时执行一次
self.fp.close()
def process_item(self,item,spider):
self.fp.write(item['title']+':'+item['content']+'\n')
将数据写入本地文件
yield item
#将数据存到Mysql中:
class MysqlPipeline(object):
conn = None
cursor = None
#定义打开数据库的函数
def open_spider(self,spider):
self.conn = pymysql.Connect(host='127.0.0.1',port=3306,......)
print(self.conn)
def process_item(self,item,spider):
self.cursor = self.conn.cursor()
sql = 'insert into duziwnag values ("%s","%s")'%(item['title'],item['connect'])
#事物处理
try:
self.cursor.execute(sql)
self.conn.commit()
except Exception as e:
print(e)
self.conn.rollback()
return item # 在多管道,本管道优先级高的情况下加上
#定义关闭数据库
def close_spider(self,spider)
self.cursor.close()
self.conn.close()
#将数据存储到 redis
class Redispipeline(object):
conn = None
def open_spider(self,spider):
self.conn = Redis(host='127.0.0.1',port=6379)
def process_item(self,item,spider):
#报错:将Redis 模块的版本指定成2.10.6,pip install -U redis==2.10.6
self.conn.lpush('duanziData',item)