爬虫2

1.Cookie

  • 什么是cookie?

    • cookie的本质就是一组数据(键值对的形式存在)

    • 是由服务器创建,返回给客户端,最终会保存在客户端浏览器中。

    • 如果客户端保存了cookie,则下次再次访问该服务器,就会携带cookie进行网络访问。

      • 典型的案例:网站的免密登录

  • 爬虫中cookie的处理方式(两种方式):

    • 手动处理:将抓包工具中的cookie赋值到headers中即可

      • 缺点:

        • 编写麻烦

        • cookie通常都会存在有效时长

        • cookie中可能会存在实时变化的局部数据

    • 自动处理

      • 基于session对象实现自动处理cookie。

        • 1.创建一个空白的session对象。

        • 2.需要使用session对象发起请求,请求的目的是为了捕获cookie

          • 注意:如果session对象在发请求的过程中,服务器端产生了cookie,则cookie会自动存储在session对象中。

        • 3.使用携带cookie的session对象,对目的网址发起请求,就可以实现携带cookie的请求发送,从而获取想要的数据。

      • 注意:session对象至少需要发起两次请求

        • 第一次请求的目的是为了捕获存储cookie到session对象

        • 后次的请求,就是携带cookie发起的请求了

import requests
#1.创建一个空白的session对象
session = requests.Session()

headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
main_url = 'https://xueqiu.com/'
#2.使用session发起的请求,目的是为了捕获到cookie,且将其存储到session对象中
session.get(url=main_url,headers=headers)

url = 'https://xueqiu.com/statuses/hot/listV2.json'
param = {
    "since_id": "-1",
    "max_id": "311519",
    "size": "15",
}
#3.就是使用携带了cookie的session对象发起的请求(就是携带者cookie发起的请求)
response = session.get(url=url,headers=headers,params=param)
data = response.json()
print(data)

 

1.1 timeout 超时

  • 在平时网上冲浪的过程中,我们经常会遇到网络波动,这个时候,一个请求等了很久可能任然没有结果。
  • 在爬虫中,一个请求很久没有结果,就会让整个项目的效率变得非常低,这个时候我们就需要对请求进行强制要求,让他必须在特定的时间内返回结果,否则就报错。
  •  timeout=3   发送请求后,3秒内没有响应就抛出异常。
import requests
 
url = 'https://twitter.com'
response = requests.get(url, timeout=3)     # 设置超时时间

 

1.2 使用verify参数忽略CA证书

  • 在使用浏览器上网的时候,有时能够看到下面的提示

 

运行下面的代码将会抛出包含ssl.CertificateError ...字样的异常

import requests
url = "https://sam.huat.edu.cn:8443/selfservice/"
response = requests.get(url)

解决方案:为了在代码中能够正常的请求,我们使用verify=False参数,此时requests模块发送请求将不做CA证书的验证:verify参数能够忽略CA证书的认证

import requests
url = "https://sam.huat.edu.cn:8443/selfservice/"
response = requests.get(url,verify=False)

 

2. 代理

  • 代理服务器的作用

    • 就是用来转发请求和响应

  • 为何需要使用代理?
    • 有些时候,需要对网站服务器发起高频的请求,网站的服务器会检测到这样的异常现象,则会讲请求对应机器的ip地址加入黑名单,则该ip再次发起的请求,网站服务器就不在受理,则我们就无法再次爬取该网站的数据。

    • 使用代理后,网站服务器接收到的请求,最终是由代理服务器发起,网站服务器通过请求获取的ip就是代理服务器的ip,并不是我们客户端本身的ip。

    

代理ip的匿名程度:

  • 透明代理(Transparent Proxy):网站的服务器知道你使用了代理,也知道你的真实ip。目标服务器接收到的请求头如下:
REMOTE_ADDR = Proxy IP
HTTP_VIA = Proxy IP
HTTP_X_FORWARDED_FOR = Your IP
  • 匿名代理(Anonymous Proxy):网站服务器知道你使用了代理,但是无法获知你真实的ip。目标服务器接收到的请求头如下:
REMOTE_ADDR = proxy IP
HTTP_VIA = proxy IP
HTTP_X_FORWARDED_FOR = proxy IP
  • 高匿代理(Elite proxy或High Anonymity Proxy):网站服务器不知道你使用了代理,也不知道你的真实ip(推荐)。毫无疑问使用高匿代理效果最好。目标服务器接收到的请求头如下:
REMOTE_ADDR = Proxy IP
HTTP_VIA = not determined
HTTP_X_FORWARDED_FOR = not determined

 

根据网站所使用的协议不同,需要使用相应协议的代理服务。从代理服务请求使用的协议可以分为:

  • http代理:目标url为http协议

  • https代理:目标url为https协议

  • socks隧道代理(例如socks5代理)等:

    • socks 代理只是简单地传递数据包,不关心是何种应用协议(FTP、HTTP和HTTPS等)。

    • socks 代理比http、https代理耗时少。

    • socks 代理可以转发http和https的请求

 

测试:访问如下网址,返回自己本机ip

import requests
from lxml import etree
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
url = 'https://www.sogou.com/web?query=ip'
page_text = requests.get(url=url,headers=headers).text
tree = etree.HTML(page_text)
data = tree.xpath('//*[@id="ipsearchresult"]/strong/text()')[0]
print(data)

 

使用代理发起请求,查看是否可以返回代理服务器的ip  

import requests
from lxml import etree
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36',
}
url = 'https://www.sogou.com/web?query=ip'
#使用代理服务器发起请求
#proxies={'代理类型':'ip:port'}
page_text = requests.get(url=url,headers=headers,proxies={'https':'42.57.150.150:4278'}).text
tree = etree.HTML(page_text)
data = tree.xpath('//*[@id="ipsearchresult"]/strong/text()')[0]
print(data)

 

3. 验证码

import base64
import json
import requests
# 一、图片文字类型(默认 3 数英混合):
# 1 : 纯数字
# 1001:纯数字2
# 2 : 纯英文
# 1002:纯英文2
# 3 : 数英混合
# 1003:数英混合2
#  4 : 闪动GIF
# 7 : 无感学习(独家)
# 11 : 计算题
# 1005:  快速计算题
# 16 : 汉字
# 32 : 通用文字识别(证件、单据)
# 66:  问答题
# 49 :recaptcha图片识别
# 二、图片旋转角度类型:
# 29 :  旋转类型
#
# 三、图片坐标点选类型:
# 19 :  1个坐标
# 20 :  3个坐标
# 21 :  3 ~ 5个坐标
# 22 :  5 ~ 8个坐标
# 27 :  1 ~ 4个坐标
# 48 : 轨迹类型
#
# 四、缺口识别
# 18 : 缺口识别(需要2张图 一张目标图一张缺口图)
# 33 : 单缺口识别(返回X轴坐标 只需要1张图)
# 五、拼图识别
# 53:拼图识别
#函数实现忽略
def base64_api(uname, pwd, img, typeid):
    with open(img, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""


def getImgCodeText(imgPath,imgType):#直接返回验证码内容
    #imgPath:验证码图片地址
    #imgType:验证码图片类型
    result = base64_api(uname='bb328410948', pwd='bb328410948', img=imgPath, typeid=imgType)
    return result
  • 验证码图片识别操作

from lxml import etree
import requests
import tujian
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
}
#将验证码图片请求后保存到本地
login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
page_text = requests.get(url=login_url,headers=headers).text
tree = etree.HTML(page_text)
img_src = 'https://so.gushiwen.cn'+tree.xpath('//*[@id="imgCode"]/@src')[0]
code_data = requests.get(url=img_src,headers=headers).content
with open('./code.jpg','wb') as fp:
    fp.write(code_data)

#识别验证码图片内容
result = tujian.getImgCodeText('./code.jpg',3)
print(result)

 

4. 模拟登录

  • 古诗文网

  • 在抓包工具里定位点击登录按钮后对应的数据包:

    • 只要数据包的请求参数中包含用户名,密码和验证码则该数据包就是我们要定位的

  • 首次模拟登录操作:

from lxml import etree
import requests
import tujian
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
}
#将验证码图片请求后保存到本地
login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
page_text = requests.get(url=login_url,headers=headers).text
tree = etree.HTML(page_text)
img_src = 'https://so.gushiwen.cn'+tree.xpath('//*[@id="imgCode"]/@src')[0]
code_data = requests.get(url=img_src,headers=headers).content
with open('./code.jpg','wb') as fp:
    fp.write(code_data)

#识别验证码图片内容
result = tujian.getImgCodeText('./code.jpg',3)
print(result)
#模拟登录
url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data = {
    "__VIEWSTATE": "opfVI7oolwkr7MLRVzsNSMASqLRUuO1dg5ZP5EIRa4FyM+mOYKEs6KWEKQKaba2ulLoZQIaLFiKK4mr5K3ci1v8ua28wtcRtabKWjOtJtU/i2etH+zSduegTMcg=",
    "__VIEWSTATEGENERATOR": "C93BE1AE",
    "from": "http://so.gushiwen.cn/user/collect.aspx",
    "email": "15027900535",
    "pwd": "bobo@15027900535",
    "code":result ,
    "denglu": "登录"
}
#获取了登录成功后的页面源码数据
login_page_text = requests.post(url=url,headers=headers,data=data).text
with open('wushiwen.html','w') as fp:
    fp.write(login_page_text)

 

查看gushiwen.html发现,没有登录成功,原因:

  • 验证码不对(否定)

  • 没有携带cookie

  • 出现了动态变化的请求参数

    • 如何获取动态变化的请求参数

      • 基于抓包工具进行全局搜索,发现该参数值被隐藏在了登录页面的页面源码中

from lxml import etree
import requests
import tujian
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
}
#创建session对象
session = requests.Session()

#将验证码图片请求后保存到本地
login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
page_text = session.get(url=login_url,headers=headers).text
tree = etree.HTML(page_text)
img_src = 'https://so.gushiwen.cn'+tree.xpath('//*[@id="imgCode"]/@src')[0]
code_data = session.get(url=img_src,headers=headers).content
with open('./code.jpg','wb') as fp:
    fp.write(code_data)

#解析出动态变化的请求参数
__VIEWSTATE = tree.xpath('//*[@id="__VIEWSTATE"]/@value')[0]

#识别验证码图片内容
result = tujian.getImgCodeText('./code.jpg',3)
print(result)
#模拟登录
url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data = {
    "__VIEWSTATE": __VIEWSTATE,
    "__VIEWSTATEGENERATOR": "C93BE1AE",
    "from": "http://so.gushiwen.cn/user/collect.aspx",
    "email": "15027900535",
    "pwd": "bobo@15027900535",
    "code":result ,
    "denglu": "登录"
}
#获取了登录成功后的页面源码数据
login_page_text = session.post(url=url,headers=headers,data=data).text
with open('wushiwen.html','w') as fp:
    fp.write(login_page_text)

 

5. 防盗链

  • 现在很多网站启用了防盗链反爬,防止服务器上的资源被人恶意盗取。什么是防盗链呢?

    • 以图片为例,访问图片要从他的网站访问才可以,否则直接访问图片地址得不到图片

  • 练习:抓取微博图片,url:http://blog.sina.com.cn/lm/pic/,将页面中某一组系列详情页的图片进行抓取保存,比如三里屯时尚女郎:http://blog.sina.com.cn/s/blog_01ebcb8a0102zi2o.html?tj=1

    • 注意:

      • 1.在解析图片地址的时候,定位src的属性值,返回的内容和开发工具Element中看到的不一样,通过network查看网页源码发现需要解析real_src的值。

      • 2.直接请求real_src请求到的图片不显示,加上Refere请求头即可

        • 哪里找Refere:抓包工具定位到某一张图片数据包,在其requests headers中获取

import requests
from lxml import etree
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
    "Referer": "http://blog.sina.com.cn/",

}
url = 'http://blog.sina.com.cn/s/blog_01ebcb8a0102zi2o.html?tj=1'
page_text = requests.get(url,headers=headers).text
tree = etree.HTML(page_text)
img_src = tree.xpath('//*[@id="sina_keyword_ad_area2"]/div/a/img/@real_src')
for src in img_src:
    data = requests.get(src,headers=headers).content
    with open('./123.jpg','wb') as fp:
        fp.write(data)
    # break

 

6. 懒加载

  • url:https://sc.chinaz.com/tupian/meinvtupian.html

  • 爬取上述链接中所有的图片数据

  • 图片懒加载:

    • 主要是应用在展示图片的网页中的一种技术,该技术是指当网页刷新后,先加载局部的几张图片数据即可,随着用户滑动滚轮,当图片被显示在浏览器的可视化区域范围的话,在动态将其图片请求加载出来即可。(图片数据是动态加载出来)。

    • 如何实现图片懒加载/动态加载?

      • 使用img标签的伪属性(指的是自定义的一种属性)。在网页中,为了防止图片马上加载出来,则在img标签中可以使用一种伪属性来存储图片的链接,而不是使用真正的src属性值来存储图片链接。(图片链接一旦给了src属性,则图片会被立即加载出来)。只有当图片被滑动到浏览器可视化区域范围的时候,在通过js将img的伪属性修改为真正的src属性,则图片就会被加载出来。

  • 如何爬取图片懒加载的图片数据?

    • 只需要在解析图片的时候,定位伪属性(src2)的属性值即可。

  • 注意:爬取页面后在查实图片的属性是 src 还是 src2 ,根据对应属性爬取。
import requests
import re

header = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
}
url = "https://sc.chinaz.com/tupian/meinvtupian.html"

res = requests.get(url=url,headers=header)
res.encoding="utf-8"


html_text = res.text
ex = re.findall('<div class="item".*?data-original="(.*?)"',html_text,re.S)
for i in ex:
    new_url = "https:"+i
    aa = requests.get(url=new_url,headers=header)
    img = aa.content
    name = i.split('/')[-1]
    with open(name,'wb') as f:
        f.write(img)
    print(name,"下载成功")

 

 

 

 

 

 

 

posted @ 2024-03-01 13:58  Crazy丶迷恋  阅读(1)  评论(0编辑  收藏  举报