目录:
目录
2.3.1 get请求方式:urllib.parse.quote()
2.3.2 get请求方式:urllib.parse.urlencode()
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的基本概念。
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\HTTPError
2.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基本语法;
接下来我们试试查询本地文件的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[@id="l1" 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语法')
语法小练习:
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,和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?
(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相对于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时发挥的巨大作用。