一. Requests模块
1. 简述爬虫的概念
爬虫就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程。
2. 爬虫有几种分类,在使用场景中
主要有两种:
在编写爬虫时先下载到本地进行测试,然后再进行正规的验证
1.通用爬虫:
通用爬虫是搜索引擎(Baidu、Google、Yahoo等)“抓取系统”的重要组成部分。主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份。
简单来讲就是尽可能的;把互联网上的所有的网页下载下来,放到本地服务器里形成备分,在对这些网页做相关处理(提取关键字、去掉广告),最后提供一个用户检索接口。
搜索引擎如何抓取互联网上的网站数据?
门户网站主动向搜索引擎公司提供其网站的url
搜索引擎公司与DNS服务商合作,获取网站的url
门户网站主动挂靠在一些知名网站的友情链接中
2.聚焦爬虫:聚焦爬虫是根据指定的需求抓取网络上指定的数据。例如:获取豆瓣上电影的名称和影评,而不是获取整张页面中所有的数据值。
3. 简述robots协议的概念也作用
- 如果自己的门户网站中的指定页面中的数据不想让爬虫程序爬取到的话,那么则可以通过编写一个robots.txt的协议文件来约束爬虫程序的数据爬取。
robots协议的编写格式可以观察淘宝网的robots(访问www.taobao.com/robots.txt即可)。但是需要注意的是,该协议只是相当于口头的协议,并
没有使用相关技术进行强制管制,所以该协议是防君子不防小人。但是我们在学习爬虫阶段编写的爬虫程序可以先忽略robots协议。
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
4. 什么是反爬机制和反反爬机制
- 门户网站通过相应的策略和技术手段,防止爬虫程序进行网站数据的爬取。
反爬机制:
(1)U-A校验模式
当你在家用浏览器上网的时候,每次发送请求时请求头会自动携带浏览器参数还有系统参数给服务器。从而让服务器知道这是一个人啊!一次来作为反爬机制的一种。
(2)限制访问频率
正常人浏览网站点击速度有多少?机器访问快多了,短时间发送几百个请求。这时候服务器检测到后就可以通过设置一个速度去封IP,例如一分钟访问200次就封锁IP
(3)设置验证码
很多朋友都不明白为什么要验证码?我小时候想了这个问题很久很久,自从学了爬虫才明白,这东西真的是为了验证我是一个人在上网而生得。这种方法就让爬虫更加困难了。
(4)通过账号限制
通过登录才可以浏览网站。
反反爬虫机制:
- 爬虫程序通过相应的策略和技术手段,破解门户网站的反爬虫手段,从而爬取到相应的数据。
5. 简述使用requests模块进行数据爬取的大致流程
1、指定url
2、基于requests模块发起请求
3、获取响应对象中的数据值
4、数据解析
5、持久化存储
#指定搜索关键字 word = input('enter a word you want to search:') #自定义请求头信息 headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } #指定url url = 'https://www.sogou.com/web' #封装get请求参数 prams = { 'query':word, 'ie':'utf-8' } #发起请求 response = requests.get(url=url,params=param) #获取响应数据 page_text = response.text with open('./sougou.html','w',encoding='utf-8') as fp: fp.write(page_text)
6. 简述使用requests模块爬取ajax加载数据爬取的大致流程
流程和普通的requests相同,
不同之处是:通过抓包工具获取请求的url和请求参数
url和请求参数,get请求参数封装在params字典里面;post请求参数封装在data字典里面
基于requests模块ajax的get请求 需求:爬取豆瓣电影分类排行榜 https://movie.douban.com/中的电影详情数据 基于requests模块ajax的post请求 需求:爬取肯德基餐厅查询http://www.kfc.com.cn/kfccda/index.aspx中指定地点的餐厅数据
#指定ajax-get/post请求的url(通过抓包进行获取) url = 'https://movie.douban.com/j/chart/top_list?' #定制请求头信息,相关的头信息必须封装在字典结构中 headers = { #定制请求头中的User-Agent参数,当然也可以定制请求头中其他的参数 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #定制get请求携带的参数(从抓包工具中获取) param = { 'type':'5', 'interval_id':'100:90', 'action':'', 'start':'0', 'limit':'20' } #发起get/post请求,获取响应对象 response = requests.get(url=url,headers=headers,params=param) #获取响应内容:响应内容为json串 print(response.text)
7. 简述User-Agent参数的作用
在http协议里,头信息中有一个 User-Agent,它的作用是告诉服务器,用户客户端是什么浏览器,以及操作系统的信息的。在某些特殊的情况下,
服务器根据浏览器的不同类型,输出不 同的内容。大概在三四年前,很多网站都只显示给IE看,所以当时的 opera 浏览器还特别做了一个功能,可
以把它的 User-Agent 换成 IE 的。所以 user-agent 是非常不可靠的,原因就是它是客户端自己决定并发送给服务器。 1,使用User-Agent伪造浏览器,谎称身份欺骗服务器
8. 在requests模块中接触过哪些反爬机制
验证码、限制ip访问频率、U-A校验模式
9. 介绍下requests模块中get和post方法常用参数的作用
#封装get请求参数 prams = { 'query':word, 'ie':'utf-8' } #发起get请求,获取响应对象 #定制请求头信息,相关的头信息必须封装在字典结构中 headers = { #定制请求头中的User-Agent参数,当然也可以定制请求头中其他的参数 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } response = requests.get(url=url,headers=headers,params=param) #定制post请求携带的参数(从抓包工具中获取) data = { 'cname':'', 'pid':'', 'keyword':'北京', 'pageIndex': '1', 'pageSize': '10' } #发起post请求,获取响应对象 response = requests.get(url=url,headers=headers,data=data) #获取响应内容:响应内容为json串 print(response.text)
10. 简述session的创建流程及其该对象的作用
#创建一个session对象,该对象会自动将请求中的cookie进行存储和携带 session = requests.session()
cookie由服务器创建并交给客户端浏览器保存,会话跟踪技术,再次访问时,服务器就可以区分客户端浏览器
#使用session发送请求,目的是为了将session保存该次请求中的cookie
session.post(url=post_url,data=formdata,headers=headers)
get_url = 'http://www.renren.com/960481378/profile'
#再次使用session进行请求的发送,该次请求中已经携带了cookie
response = session.get(url=get_url,headers=headers)
11. 简述如何使用requests模块进行模拟登录,并抓取登录成功后的某个二级页面数据。
requests.get请求到登陆页面
requests.post请求
/pazims/
结合session = requests.post.session() 先登陆成功后:在浏览器获取post请求的参数 response = requests.post(url=url,data=data,headers=headers) 获取个人页面url params = {} 获取get请求参数 response = requests.get(url=url,params=params,headers=headers) # 3.获取响应对象的页面数据 page_text = response.text print(page_text)
12. 简述如何使用requests模块设置代理IP
两种爬虫编写方法
1、在使用requests模块--get post ---proxy 2]、在scrapy框架下----下载中间件
设置代理ip主要有两种形式: 一种是在代码中直接写 #不同的代理IP proxy_list = [ {"http": "112.115.57.20:3128"}, {'http': '121.41.171.223:3128'} ] #随机获取UA和代理IP header = random.choice(header_list) proxy = random.choice(proxy_list) #参数3:设置代理 response = requests.get(url=url,headers=header,proxies=proxy) ------------------------------------------------------------------------------ 另外一种是在中间件中设置: 1.在下载中间件中拦截请求 2.将拦截到的请求的IP修改成某一代理IP 3.在配置文件(settings.py)中开启下载中间件
二. 数据解析
1. 简述使用在使用正则进行解析时用到的re.S和re.M的作用和区别
re.I : 忽略大小写
re.M :多行匹配
re.S :单行匹配
---------------------------
#匹配出i开头的行 string = '''fall in love with you i love you very much i love she i love her''' re.findall('^.*',string,re.M)
##################################################################### #匹配全部行 string1 = """<div>静夜思 窗前明月光 疑是地上霜 举头望明月 低头思故乡 </div>""" re.findall('.*',string1,re.S)
2. 简述如何使用xpath进行数据解析
jupyter 音标:/ˈdʒuːpɪtə(r)/
1、jupyter,python环境下
首先要下载 from lxml import etree
xpath插件:就可以直接将xpath表达式作用到浏览器的网页当中
安装:选择浏览器更多工具-扩展程序(管理)-打开开发者 打开界面直接拖进来
创建etree对象进行指定数据的解析
- 本地:tree = etree.parse(‘本地文件路径’)
tree.xpath('xpath表达式')
- 网络:tree=etree.HTML('网络请求到的页面数据')
tree.xpath('xpath表达式')
2、使用Scrapy框架开发,已经封装了xpath模块
属性定位:
div_list = response.xpath("//div[@class='data_row news_article clearfix']")
#找到class属性值为song的div标签 //div[@class="song"]
层级定位、逻辑元算、模糊匹配、取属性
取属性: //div[@class="tang"]//li[2]/a/@href
3. 简述如何使用bs4进行数据解析
beautiful soup soup 英 /suːp/ 美 /sup/
python独有的一种解析方式,只能在python中进行解析
使用起来更加简便和高效
from bs4 import BeautifulSoup - 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容 (1)转化本地文件: - soup = BeautifulSoup(open('本地文件'), 'lxml') (2)转化网络文件: #获取标题正文页数据 page_text = requests.get(url,headers=headers).text soup = BeautifulSoup('字符串类型或者字节类型', 'lxml') (3)打印soup对象显示内容为html文件中的内容 #创建soup对象 soup = BeautifulSoup(page_text,'lxml') #解析数据 1、找到符合条件的标签 2、获取标签的属性、内容 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
4. xpath方法返回值类型是什么‘
xpath函数返回的总是一个列表----列表里面是选择器对象
可以用索引、和切片进行处理
5. 在xpath中如何/text()和//text()的区别是什么
1、/text()表示获取某个标签下的文本内容
2、//text()表示获取某个标签下的文本内容 和 所有子标签下的文本内容
6. id为su的div标签有一个子标签ul,ul下有十个li标签,每一个li标签下都有一个a标签,如何编写xpath表达式可以解析到a标签的href属性值
tree=etree.HTML(url_content)
li = tree.xpath('//div[@]/ul/li')
li = response.xpath('//div[@]/ul/li')
for i in li:
i.xpath('./a/@href').extract_first()
response.xpath('//div[@>).extract_first() 提取到第一个匹配到的元素, 必须调用 .extract_first() 提取真实的原文数据,你需要调用 .extract() response.xpath('//title/text()').extract() 当你没有使用extract()的时候,提取出来的内容依然具有选择器属性,简而言之,你可以继续使用里面的内容进行提取下级内容,而当你使用了extract()之后,提取出来的内容就会变成字符串格式了 关于选择器 Scrapy帮我们下载完页面后,我们怎样在满是html标签的内容中找到我们所需要的元素呢,这里就需要使用到选择器了,它们是用来定位元素并且提取元素的值。先来举几个例子看看: /html/head/title: 选择<title>节点, 它位于html文档的<head>节点内 /html/head/title/text(): 选择上面的<title>节点的内容. //td: 选择页面中所有的元素 //div[@class=”mine”]: 选择所有拥有属性class="mine"的div元素 Scrapy使用css和xpath选择器来定位元素,它有四个基本方法: xpath(): 返回选择器列表,每个选择器代表使用xpath语法选择的节点 css(): 返回选择器列表,每个选择器代表使用css语法选择的节点 extract(): 返回被选择元素的unicode字符串 re(): 返回通过正则表达式提取的unicode字符串列表
在Scrapy中才有 extract_first()和extract()
# 需求:将id97电影网站中电影详情数据进行爬取(名称,类型,导演,语言,片长) div_list = response.xpath('/html/body/div[1]/div[1]/div[2]/div') # 可循环,切片、索引 print('div_list',type(div_list)) print('div_list[0],索引',type(div_list[0])) print('div_list[1:],切片',type(div_list[1:])) for div in div_list: # extract_first()第一个 name = div.xpath(".//div[@class='meta']/h1/a/text()").extract_first() name2 = div.xpath(".//div[@class='meta']/h1/a/text()") name3 = div.xpath(".//div[@class='meta']/h1/a/text()")[0] #name4 = div.xpath(".//div[@class='meta']/h1/a/text()")[0].extract_first() print('name---',name,type(name))#print('name4---',name4,type(name4)) kind = div.xpath('.//div[@class="otherinfo"]//text()').extract() kind2 = div.xpath('.//div[@class="otherinfo"]//text()') kind3 = div.xpath('.//div[@class="otherinfo"]//text()')[0] kind4 = div.xpath('.//div[@class="otherinfo"]//text()')[0].extract() # 将kind列表转化成字符串 kind = " ".join(kind) print('" ".join(kind)---',kind,type(kind))
7. class为wd的div标签有一个子标签ul,ul下有十个li标签,每一个li标签下都有一个a标签,如何编写xpath表达式可以解析到a标签中的文本内容
lis=response.xpath('//div[@class="wd"]/ul/li')
for li in lis:
a=li.xpath('./a/text()').extract_first()
prin(a)
8. 简述BeautifulSoup模块中find和findall方法的区别
(4)find:找到第一个符合要求的标签 - soup.find('a') 找到第一个符合要求的 - soup.find('a', title="xxx") - soup.find('a', alt="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (5)find_all:找到所有符合要求的标签 - soup.find_all('a') - soup.find_all(['a','b']) 找到所有的a和b标签 - soup.find_all('a', limit=2) 限制前两个
9. 简述BeautifulSoup模块中select方法的使用
(6)根据选择器选择指定的内容 select:soup.select('#feng') - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器 - 层级选择器: div .dudu #lala .meme .xixi 下面好多级 div > p > a > .lala 只能是下面一级 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
a_list = soup.select('.book-mulu > ul > li > a')
print(a_list,type(a_list)) <class 'list'> 列表里面全是Tag对象 可以 继续Beatiful对象的属性和方法
print(a_list[0],type(a_list[0])) <class 'bs4.element.Tag'>
10. 简述xpath插件的作用
xpath插件:就可以直接将xpath表达式作用到浏览器的网页当中 ,进行验证
快捷键: 开启和关闭xpath插件:ctrl+shitf+x
-------------------------------------
首先先来介绍下xml,它是用来存储和传输数据使用的。 和html的不同有以下的两点: (1)html用来显示数据,xml是用来传输数据 (2)html标签是固定的,xml标签是自定义的 xpath用来在xml中查找指定的元素,它是一种路径表达式 常用的路径表达式: // : 不考虑位置的查找 ./ : 从当前节点开始往下查找 @ : 选取属性
# "."表示当前节点。
# ".."表示当前节点的父节点
1)通过属性进行定位 //input[@id="kw"] //input[@class="bg s_btn"] (2) 层级定位 索引定位 //div[@id="head"]/div/div[2]/a[@class="toindex"] 【注】索引从1开始 //div[@id="head"]//a[@class="toindex"] 【注】双斜杠代表下面所有的a节点,不管位置 逻辑运算 //input[@class="s_ipt" and @name="wd"] 模糊匹配 contains //input[contains(@class, "s_i")] 所有的input,有class属性,并且属性中带有s_i的节点 //input[contains(text(), "爱")] starts-with //input[starts-with(@class, "s")] 所有的input,有class属性,并且属性以s开头 取文本 //div[@id="u1"]/a[5]/text() 获取节点内容 //div[@id="u1"]//text() 获取节点里面不带标签的所有内容 取属性 //div[@id="u1"]/a[5]/@href 在代码中进行使用方法如下 from lxml import etree 两种方式使用:将html文档变成一个对象,然后调用对象的方法去查找指定的节点 (1)本地文件 tree = etree.parse(文件名) (2)网络文件 tree = etree.HTML(网页字符串) ret = tree.xpath(路径表达式) 注意:ret是一个列表 #将所用满足条件的内容进行拼接起来形成string ret = tree.xpath('//div[@class="**"]') string = ret[0].xpath('string(.)') print(string.replace('\n', '').replace('\t', ''))