目录:
目录
目录:
1. 爬虫介绍
1.1 爬虫是什么
1.2 爬虫步骤
1.3 爬虫分类
1.3.1 通用爬虫
1.3.2 聚焦爬虫
编辑
1.4 一些常见的反爬手段
2. Urllib
2.1 urllib库的使用
2.2 请求对象的定制
2.3 编解码
2.3.1 get请求方式:urllib.parse.quote()
2.3.2 get请求方式:urllib.parse.urlencode()
2.3.3 post请求方式
2.3.4 总结:get与post的区别
2.4 介绍另一种反爬机制:Cookie请求条件
2.5 ajax
2.5.1 什么是ajax?
2.5.2 ajax的get请求
2.5.3 ajax的post请求
2.6 URLError\HTTPError
2.7 cookie登录
2.8 handler处理器
2.9 代理服务器
2.9.1 代理池
3. 解析语句
3.1 xpath
3.2 jsonpath
3.3 BeautifulSoup
4. Selenium
4.1 Selenium使用
5. Requests
5.1 requests一种属性及六种类型
5.2 get请求
5.3 post请求
5.4 代理的使用
5.5 cookie定制
6. Scrapy框架
6.1 scrapy安装及使用
6.1.1 创建scrapy项目
6.1.2 项目组成
6.1.3 创建爬虫文件及其组成
6.1.4 运行爬虫文件
1. 爬虫介绍
1.1 爬虫是什么
爬虫解释:
通过一个程序,根据Url(http://www.taobao.com)进行爬取网页,获取有用信息。 使用程序模拟浏览器,去向服务器发送请求,获取响应信息。1.2 爬虫步骤
爬取网页:爬取整个网页 包含了网页中所有得内容。 解析数据:对得到的网页内容进行解析,得到想要的内容。 重难点:爬虫和反爬虫之间的博弈。1.3 爬虫分类
1.3.1 通用爬虫
1.3.2 聚焦爬虫
1.4 一些常见的反爬手段
User‐Agent:user Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。 代理IP:
西次代理
快代理
什么是高匿名、匿名和透明代理?它们有什么区别?
1.使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
2.使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
3.使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。 验证码访问: 动态加载网页网站返回的是js数据并不是网页的真实数据:
selenium驱动真实的浏览器发送请求。 数据加密
分析js代码
2. Urllib
2.1 urllib库的使用
pychart自动对齐:Ctrl+Alt+L
一个类型和六个方法以及下载网页文件:
2.2 请求对象的定制
本节将遇到第一个反爬手段:UA
UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等。
该手段常用于https类型的网页。
用法代码:
2.3 编解码
此时引入一个知识:编码的由来
2.3.1 get请求方式:urllib.parse.quote()
该方法可以将一个字符串(例如“蔡徐坤”)转化为Unicode编码格式。
2.3.2 get请求方式:urllib.parse.urlencode()
该方法可以将一个字典里的所有字符串都转化为Unicode编码格式,并将每个字典通过‘&’字符进行连接起来。
2.3.3 post请求方式
如上图,接下来是对POST请求方式进行访问以及爬取数据:
注意:
post请求方式的参数 必须编码: data = urllib.parse.urlencode(data)
编码之后 必须调用encode方法: data = urllib.parse.urlencode(data).encode('utf-8')
参数是放在请求对象定制的方法中: request = urllib.request.Request(url=url,data=data,headers=headers)
2.3.4 总结:get与post的区别
get请求方式的参数必须编码,参数是拼接到url后面,编码之后不需要调用encode方法。 post请求方式的参数必须编码,参数是放在请求对象定制的方法中,编码之后需要调用encode方法。2.4 介绍另一种反爬机制:Cookie请求条件
网页介绍:接下来爬的是百度翻译中的详细翻译的网址:https://fanyi.baidu.com/v2transapi
import urllib.request
import urllib.parse
url = 'https://fanyi.baidu.com/v2transapi?from=en&to=zh'
headers = {
'Accept': '*/*',
# 'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Acs-Token': 'J3LzIgujUbcQ2H0EsLT1E8yxIN1p8PX+Nz68ePXNgUnE4veDrr+BnZcxZl/RJP3jLlVEjSASGpRG8b9RJgShnvI+/5VCRSoBj2LqqNj9VE6tWWTZvLXCuTx2TWI=',
'Connection': 'keep-alive',
'Content-Length': '135',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
# 这一系列request headers中最重要的起决定性作用的就是Cookie:本网页的反爬机制所要求的的就是看你发送的请求中有没有Cookie。
'Cookie': 'BIDUPSID=523909DDFA05F3A29C91FAEF93B43238; PSTM=1654333278; BAIDUID=523909DDFA05F3A2B6D81D921CD97D63:FG=1; BDUSS=Ztdk03eH:C; PSINO=1; delPer=0; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1680136974; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1680139371; ab_sr=1.0.1_ZjdjOTkxMmM0YTFhMGUxYjY3YTE0OTdlMTJmMTVkY2MxODNmNzRlYmMzMTBmMGZjYTcyNTMwYTFmZmYyNjlhZjI5MDg1OGQ1MmIwMjM2MzM1NGYwMTY5NjIzYjc0NGU3MzA5ODliZmM0M2YxN2FjNDdlOTI4ZjgyNWFlMjM2NzJiOTk3YzA3NjhkMWVhYTk0NzMwZTc1MzZhYjFhMTA0OTMxNGVkNzBmM2ZkMDkyNWE1MDgwZmI5YTM0ZDg0Njhh',
'Host': 'fanyi.baidu.com',
'Origin': 'https://fanyi.baidu.com',
'Referer': 'https://fanyi.baidu.com/translate?aldtype=16047&query=&keyfrom=baidu&smartresult=dict&lang=auto2zh',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozi.........537.36',
'X-Requested-With': 'XMLHttpRequest',
}
data = {
'from': 'en',
'to': 'zh',
'query': 'love',
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '198772.518981',
'token': '226bb4a02ab9044d1d0f5de29da6caff',
'domain': 'common',
}
# post请求的参数 必须进行编码 并且要调用encode方法
data = urllib.parse.urlencode(data).encode('utf-8')
# 请求对象的定制
request = urllib.request.Request(url = url,data = data,headers = headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')
import json
obj = json.loads(content)
print(obj)
通过上图代码发现,该代码比之前的代码的header多了好多的内容:
# 'Accept-Encoding': 'gzip, deflate, br', 该行表示该网页接收的编码格式。
'Cookie': 'BIDUPSID=523909DDFA05F3A29C91FAEF9......' # 这一系列request headers中最重要的起决定性作用的就是Cookie:本网页的反爬机制所要求的的就是看你发送的请求中有没有Cookie。
2.5 ajax
2.5.1 什么是ajax?
什么是ajax?——CSDN
通过阅读上面的博客,我们知道了ajax的基本概念。
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指⼀种创建交互式⽹⻚应⽤的⽹⻚开发技术。
Ajax 是⼀种⽤于创建快速动态⽹⻚的技术。
Ajax 是⼀种在⽆需重新加载整个⽹⻚的情况下,能够更新部分⽹⻚的技术。
通过在后台与服务器进⾏少量数据交换,Ajax 可以使⽹⻚实现异步更新。这意味着可以在不重新加载整个⽹⻚的情况下,对⽹⻚的某部分进⾏更新。
传统的⽹⻚(不使⽤ Ajax)如果需要更新内容,必须重载整个⽹⻚⻚⾯。
举个简单的例子:比如打开了一个淘宝的商品网页,当滑轮滑到底时网页就会继续加载新的商品;这个就是ajax的一种应用形式。
2.5.2 ajax的get请求
案例:爬取豆瓣电影中动画排行榜中的前100个电影。
# get请求
# 获取豆瓣电影的第一页的数据 并且保存起来
import urllib.request
url = 'https://movie.douban.com/j/chart/top_list?type=25&interval_id=100%3A90&action=&start=0&limit=100'
headers = {
'User-Agent': 'Mozilla/5........537.36'
}
# (1) 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# (2)获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
#print(content)
# (3) 数据下载到本地
# open方法默认情况下使用的是gbk的编码 如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
# encoding = 'utf-8'
# fp = open('douban.json','w',encoding='utf-8')
# fp.write(content)
with open('douban_100.json','w',encoding='utf-8') as fp:
fp.write(content)
爬取多个相似的网页时,要找出网页链接的不同点,通过字符串拼接的方式把链接补充完整,从而爬取多个网页的数据。
2.5.3 ajax的post请求
例子:kfc官网的N页数据。
import urllib.request
import urllib.parse
def create_request(page):
base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
data = {
'cname': '北京',
'pid':'',
'pageIndex': page,
'pageSize': '10'
}
data = urllib.parse.urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.........i/537.36'
}
request = urllib.request.Request(url=base_url,headers=headers,data=data)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page,content):
with open('kfc_' + str(page) + '.json','w',encoding='utf-8')as fp:
fp.write(content)
if __name__ == '__main__':
start_page = int(input('请输入起始页码'))
end_page = int(input('请输入结束页码'))
for page in range(start_page,end_page+1):
# 请求对象的定制
request = create_request(page)
# 获取网页源码
content = get_content(request)
# 下载
down_load(page,content)
总结:爬取多个网页的数据时,对多个网页链接进行找不同就完事了!!!
2.6 URLError\HTTPError
简介:
HTTPError类是URLError类的子类 导入的包urllib.error.HTTPError urllib.error.URLError http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出了问题。 通过urllib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加的健壮,可以通过try‐except进行捕获异常,异常有两类,URLError\HTTPError2.7 cookie登录
适用的场景:数据采集的时候 需要绕过登陆 然后进入到某个页面。
个人信息页面是utf-8,但是还报错了编码错误,因为并没有进入到个人信息页面,而是跳转到了登陆页面,那么登陆页面不是utf-8,所以报错。
什么情况下访问不成功?:因为请求头的信息不够 所以访问不成功。
Cookie:cookie中携带着你的登陆信息,如果有登陆之后的cookie,那么我们就可以携带着cookie进入到任何页面。
referer:referer判断当前路径是不是由上一个路径进来的,一般情况下,是做图片防盗链。
2.8 handler处理器
为什么要学习handler?
urllib.request.urlopen(url):不能定制请求头
urllib.request.Request(url,headers,data):可以定制请求头
Handler:定制更高级的请求头(随着业务逻辑的复杂 请求对象的定制已经满足不了我们的需求(动态cookie和代理不能使用请求对象的定制))
import urllib.request
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (W........537.36'
}
request = urllib.request.Request(url = url,headers = headers)
# handler build_opener open
# (1)获取hanlder对象
handler = urllib.request.HTTPHandler()
# (2)获取opener对象
opener = urllib.request.build_opener(handler)
# (3) 调用open方法
response = opener.open(request)
content = response.read().decode('utf-8')
print(content)
2.9 代理服务器
代理的常用功能? 突破自身IP访问限制,访问国外站点。 访问一些单位或团体内部资源扩展:某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务。 提高访问速度
扩展:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。 隐藏真实IP
扩展:上网者也可以通过这种方法隐藏自己的IP,免受攻击。 代码配置代理 创建Reuqest对象 创建ProxyHandler对象 用handler对象创建opener对象 使用opener.open函数发送请求
2.9.1 代理池
import urllib.request
proxies_pool = [
{'http':'118.24.*.*:16817'},
{'http':'118.24.*.*:16817'},
]
import random
proxies = random.choice(proxies_pool)
url = 'http://www.baidu.com/s?wd=ip'
headers = {
'User-Agent': 'Mozilla/5..........i/537.36'
}
request = urllib.request.Request(url = url,headers=headers)
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)
content = response.read().decode('utf-8')
with open('daili.html','w',encoding='utf-8')as fp:
fp.write(content)
3. 解析语句
3.1 xpath
xpath是浏览器上的一个扩展程序:Xpath Helper
安装lxml库:pip install lxml ‐i https://pypi.douban.com/simple 导入lxml.etree:from lxml import etree etree.parse() 解析本地文件:html_tree = etree.parse('XX.html') etree.HTML() 服务器响应文件:html_tree = etree.HTML(response.read().decode('utf‐8')html_tree.xpath(xpath路径)xpath页面:
xpath快捷键:Ctrl+Shift+X
xpath基本语法——CSDN
以上链接是详细的xpath基本语法;
接下来我们试试查询本地文件的xpath语句:
from lxml import etree
# xpath解析
# (1)本地文件 etree.parse
# (2)服务器响应的数据 response.read().decode('utf-8') ***** etree.HTML()
# xpath解析本地文件
tree = etree.parse('xpath_case.html')
#tree.xpath('xpath路径')
# 查找ul下面的li
# li_list = tree.xpath('//body/ul/li')
# 查找所有有id的属性的li标签
# text()获取标签中的内容
# li_list = tree.xpath('//ul/li[@id]/text()')
# 找到id为l1的li标签 注意引号的问题
# li_list = tree.xpath('//ul/li[@id="l1"]/text()')
# 查找到id为l1的li标签的class的属性值
# li = tree.xpath('//ul/li[@id="l1"]/@class')
# 查询id中包含l的li标签
# li_list = tree.xpath('//ul/li[contains(@id,"l")]/text()')
# 查询id的值以l开头的li标签
# li_list = tree.xpath('//ul/li[starts-with(@id,"c")]/text()')
#查询id为l1和class为c1的
# li_list = tree.xpath('//ul/li[@ and @class="c1"]/text()')
li_list = tree.xpath('//ul/li[@id="l1"]/text() | //ul/li[@id="l2"]/text()')
# 判断列表的长度
print(li_list)
print(len(li_list))
接下来我们试试xpath获得网页中的数据:
案例:获取站长素材的图片
代码:
import urllib.request
from lxml import etree
def create_request(page):
if(page == 1):
url = 'https://sc.chinaz.com/jianli/tongyong.html'
else:
url = 'https://sc.chinaz.com/jianli/tongyong_' + str(page) + '.html'
headers = {
'User-Agent': 'Mozilla/......36',
}
request = urllib.request.Request(url = url, headers = headers)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(content):
# 下载图片
# urllib.request.urlretrieve('图片地址','文件的名字')
tree = etree.HTML(content)
name_list = tree.xpath('//div[@id="container"]//a/img/@alt')
# 一般设计图片的网站都会进行懒加载
src_list = tree.xpath('//div[@id="container"]//a/img/@src')
# print(len(name_list),len(src_list))
for i in range(len(name_list)):
name = name_list[i]
src = src_list[i]
url = 'https:' + src
urllib.request.urlretrieve(url=url,filename='./jianli/' + name + '.jpg')
if __name__ == '__main__':
start_page = int(input('请输入起始页码'))
end_page = int(input('请输入结束页码'))
for page in range(start_page,end_page+1):
# (1) 请求对象的定制
request = create_request(page)
# (2)获取网页的源码
content = get_content(request)
# (3)下载
down_load(content)
3.2 jsonpath
jsonpath的使用:
obj = json.load(open('json文件', 'r', encoding='utf‐8')) ret = jsonpath.jsonpath(obj, 'jsonpath语法')jsonpath——简单入门——CSDN
语法小练习:
import json
import jsonpath
obj = json.load(open('073_尚硅谷_爬虫_解析_jsonpath.json','r',encoding='utf-8'))
# 书店所有书的作者
# author_list = jsonpath.jsonpath(obj,'$.store.book[*].author')
# print(author_list)
# 所有的作者
# author_list = jsonpath.jsonpath(obj,'$..author')
# print(author_list)
# store下面的所有的元素
# tag_list = jsonpath.jsonpath(obj,'$.store.*')
# print(tag_list)
# store里面所有东西的price
# price_list = jsonpath.jsonpath(obj,'$.store..price')
# print(price_list)
# 第三个书
# book = jsonpath.jsonpath(obj,'$..book[2]')
# print(book)
# 最后一本书
# book = jsonpath.jsonpath(obj,'$..book[(@.length-1)]')
# print(book)
# 前面的两本书
# book_list = jsonpath.jsonpath(obj,'$..book[0,1]')
# book_list = jsonpath.jsonpath(obj,'$..book[:2]')
# print(book_list)
# 条件过滤需要在()的前面添加一个?
# 过滤出所有的包含isbn的书。
# book_list = jsonpath.jsonpath(obj,'$..book[?(@.isbn)]')
# print(book_list)
# 哪本书超过了10块钱
book_list = jsonpath.jsonpath(obj,'$..book[?(@.price>10)]')
print(book_list)
总结:
json文件解析流程:先将网页中的json文件通过代码保存在本地,然后再用jsonpath语句对获取到的json文件进行解析,最终的到想要的数据。
切片的小使用:
# split 切割
# content是一个json文件,其中包含了一对我们不需要的(),我们可以通过下面切片的方式分别对"(",")"进行切片,然后通过下标的方式获取我们想要的哪一个json数据。
content = .....
content = content.split('(')[1].split(')')[0]
3.3 BeautifulSoup
beautifulsoup——官方文档
BeautifulSoup,和lxml一样,是一个html的解析器,主要功能也是解析和提取数据。 导入:from bs4 import BeautifulSoup 创建对象:服务器响应的文件生成对象:soup = BeautifulSoup(response.read().decode(), 'lxml')
本地文件生成对象:soup = BeautifulSoup(open('1.html'), 'lxml')
语句练习:
from bs4 import BeautifulSoup
# 通过解析本地文件 来将bs4的基础语法进行讲解
# 默认打开的文件的编码格式是gbk 所以在打开文件的时候需要指定编码
soup = BeautifulSoup(open('Soup.html',encoding='utf-8'),'lxml')
print(soup)
# 根据标签名查找节点
# 找到的是第一个符合条件的数据
# print(soup.a)
# 获取标签的属性和属性值
# print(soup.a.attrs)
# bs4的一些函数
# (1)find
# 返回的是第一个符合条件的数据
# print(soup.find('a'))
# 根据title的值来找到对应的标签对象
# print(soup.find('a',title="a2"))
# 根据class的值来找到对应的标签对象 注意的是class需要添加下划线
# print(soup.find('a',class_="a1"))
# (2)find_all 返回的是一个列表 并且返回了所有的a标签
# print(soup.find_all('a'))
# 如果想获取的是多个标签的数据 那么需要在find_all的参数中添加的是列表的数据
print(soup.find_all(['a','span']))
# limit的作用是查找前几个数据
# print(soup.find_all('li',limit=2))
# (3)select(推荐)
# select方法返回的是一个列表 并且会返回多个数据
# print(soup.select('a'))
# 可以通过.代表class 我们把这种操作叫做类选择器
# print(soup.select('.a1'))
# print(soup.select('#l1'))
# 属性选择器---通过属性来寻找对应的标签
# 查找到li标签中有id的标签
# print(soup.select('li[id]'))
# 查找到li标签中id为l2的标签
# print(soup.select('li[id="l2"]'))
# 层级选择器
# 后代选择器
# 找到的是div下面的li
# print(soup.select('div li'))
# 子代选择器
# 某标签的第一级子标签
# 注意:很多的计算机编程语言中 如果不加空格不会输出内容 但是在bs4中 不会报错 会显示内容
# print(soup.select('div > ul > li'))
# 找到a标签和li标签的所有的对象
# print(soup.select('a,li'))
# 节点信息
# 获取节点内容
# obj = soup.select('#d1')[0]
# 如果标签对象中 只有内容 那么string和get_text()都可以使用
# 如果标签对象中 除了内容还有标签 那么string就获取不到数据 而get_text()是可以获取数据
# 我们一般情况下 推荐使用get_text()
# print(obj.string)
# print(obj.get_text())
# 节点的属性
# obj = soup.select('#p1')[0]
# name是标签的名字
# print(obj.name)
# 将属性值作为一个字典返回
# print(obj.attrs)
# 获取节点的属性 其中#代表“id”
# obj = soup.select('#p1')[0]
#
# print(obj.attrs.get('class'))
# print(obj.get('class'))
# print(obj['class'])
总结:BeautifulSoup没有xpath好用......
4. Selenium
4.1 Selenium使用
selenium文档——官网
什么是selenium?(1)Selenium是一个用于Web应用程序测试的工具。
(2)Selenium 测试直接运行在浏览器中,就像真正的用户在操作一样。
(3)支持通过各种driver(FirfoxDriver,IternetExplorerDriver,OperaDriver,ChromeDriver)驱动真实浏览器完成测试。
(4)selenium也是支持无界面浏览器操作的。 selenium使用步骤
(1)导入:from selenium import webdriver
(2)创建谷歌浏览器操作对象:path = 谷歌浏览器驱动文件路径
browser = webdriver.Chrome(path)
(3)访问网址:url = 要访问的网址 browser.get(url)
其他的看官方文档,看看就会用了。
5. Requests
requests文档
requests相对于urllib来说更简单,且两者的代码结构是相似的,我们可以对比着前面学的urllib来快速的上手requests。
5.1 requests一种属性及六种类型
import requests
url = 'http://www.baidu.com'
response = requests.get(url=url)
# 一个类型和六个属性
# Response类型
# print(type(response))
# 设置响应的编码格式
# response.encoding = 'utf-8'
# 以字符串的形式来返回了网页的源码
# print(response.text)
# 返回一个url地址
# print(response.url)
# 返回的是二进制的数据
# print(response.content)
# 返回响应的状态码
# print(response.status_code)
# 返回的是响应头
print(response.headers)
5.2 get请求
import requests
url = 'https://www.baidu.com/s'
headers = {
'User-Agent': 'Mozi......36'
}
data = {
'wd':'安徽'
}
# url 请求资源路径
# params 参数
# kwargs 字典
response = requests.get(url=url,params=data,headers=headers)
content = response.text
print(content)
# 总结:
# (1)参数使用params传递
# (2)参数无需urlencode编码
# (3)不需要请求对象的定制
# (4)请求资源路径中的?可以加也可以不加
5.3 post请求
import requests
url = 'https://fanyi.baidu.com/sug'
headers = {
'User-Agent': 'Mozilla/5.......36'
}
data = {
'kw': 'eye'
}
# url 请求地址
# data 请求参数
# kwargs 字典
response = requests.post(url=url,data=data,headers=headers)
content =response.text
import json
obj = json.loads(content,encoding='utf-8')
print(obj)
# 总结:
# (1)post请求 是不需要编解码
# (2)post请求的参数是data
# (3)不需要请求对象的定制
总结:get和post的区别:
get请求的参数名字是params,post请求的参数的名字是data 请求资源路径后面可以不加? 不需要手动编解码 不需要做请求对象的定制5.4 代理的使用
import requests
url = 'http://www.baidu.com/s?'
headers = {
'User-Agent': 'Mozill.......36',
}
data = {
'wd':'ip'
}
proxy = {
'http':'212.*.*.55:*'
}
response = requests.get(url = url,params=data,headers = headers,proxies = proxy)
content = response.text
with open('daili.html','w',encoding='utf-8')as fp:
fp.write(content)
5.5 cookie定制
就是绕过登录界面,直接进到登录以后的页面内容。
# 通过登陆 然后进入到主页面
# 通过找登陆接口我们发现 登陆的时候需要的参数很多
# _VIEWSTATE: /m1O5dx.....4NjGo=
# __VIEWSTATEGENERATOR: C93BE1AE
# from: http://so.gushiwen.cn/user/collect.aspx
# email: 5.....om
# pwd: a.....n
# code: PId7
# denglu: 登录
# 我们观察到_VIEWSTATE __VIEWSTATEGENERATOR code是一个可以变化的量
# 难点:(1)_VIEWSTATE __VIEWSTATEGENERATOR 一般情况看不到的数据 都是在页面的源码中
# 我们观察到这两个数据在页面的源码中 所以我们需要获取页面的源码 然后进行解析就可以获取了
# (2)验证码
import requests
# 这是登陆页面的url地址
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
headers = {
'User-Agent': 'M..........36'
}
# 获取页面的源码
response = requests.get(url = url,headers = headers)
content = response.text
# 解析页面源码 然后获取_VIEWSTATE __VIEWSTATEGENERATOR
from bs4 import BeautifulSoup
soup = BeautifulSoup(content,'lxml')
# 获取_VIEWSTATE
viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value')
# 获取__VIEWSTATEGENERATOR
viewstategenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')
# 获取验证码图片
code = soup.select('#imgCode')[0].attrs.get('src')
code_url = 'https://so.gushiwen.cn' + code
# 有坑
# import urllib.request
# urllib.request.urlretrieve(url=code_url,filename='code.jpg')
# requests里面有一个方法 session() 通过session的返回值 就能使用请求变成一个对象
session = requests.session()
# 验证码的url的内容
response_code = session.get(code_url)
# 注意此时要使用二进制数据 因为我们要使用的是图片的下载
content_code = response_code.content
# wb的模式就是将二进制数据写入到文件
with open('code.jpg','wb')as fp:
fp.write(content_code)
# 获取了验证码的图片之后 下载到本地 然后观察验证码 观察之后 然后在控制台输入这个验证码 就可以将这个值给
# code的参数 就可以登陆
code_name = input('请输入你的验证码')
# 点击登陆
url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data_post = {
'__VIEWSTATE': viewstate,
'__VIEWSTATEGENERATOR': viewstategenerator,
'from': 'http://so.gushiwen.cn/user/collect.aspx',
'email': '5......om',
'pwd': 'a........',
'code': code_name,
'denglu': '登录',
}
response_post = session.post(url = url, headers = headers, data = data_post)
content_post = response_post.text
with open('gushiwen.html','w',encoding= ' utf-8')as fp:
fp.write(content_post)
# 难点
# (1) 隐藏域
# (2) 验证码
6. Scrapy框架
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
6.1 scrapy安装及使用
安装:pip install twisted
pip install scrapy
6.1.1 创建scrapy项目
在终端打开python目录路径,
终端输入 scrapy startproject 项目名称。
创建完成之后的样子长这样:
6.1.2 项目组成
6.1.3 创建爬虫文件及其组成
跳转到spiders文件夹 cd 目录名字/目录名字/spiders scrapy genspider 爬虫名字 网页的域名组成:
name = 'baidu' ‐‐‐》 运行爬虫文件时使用的名字
allowed_domains ‐‐‐》 爬虫允许的域名,在爬取的时候,如果不是此域名之下的url,会被过滤掉
start_urls ‐‐‐》 声明了爬虫的起始地址,可以写多个url,一般是一个
parse(self, response) ‐‐‐》解析数据的回调函数
6.1.4 运行爬虫文件
在终端中输入:scrapy crawl 爬虫名称
注意:应在spiders文件夹内执行
6.2 scrapy架构组成
6.3 scrapy工作原理
6.4 scrapy shell
6.4.1 什么是scrapy shell?
Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。
该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。
一旦熟悉了Scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。