python爬虫三

今天我们来介绍几种反爬机制及其应对方法

Cookie:

在互联网数据传输中http协议是无状态的,每次连接都是新连接,那么有些网站可以记录用户状态是如何做到的呢?大部分都是使用cookie记录用户相关的用户名密码以校验用户状态,首先实现一个小案例吧。

目的地址:雪球网

爬取内容:动态加载的数据(也就是滑动才会加载的数据)

import requests
headers = {
  "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
}
url = "https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=114438&size=15"
response = resquests.get(url=url,headers=headers).text
print(response)

  

我们发现按照上述方式爬取的数据会得到一个error,如果我们发生了这种情况那么说明我们在模仿浏览器发送请求数据上出现了缺失,也就是模仿的力度不足,那么在此回顾网站,我们发现在请求头中有cookie的存在,那么接下来的解决方法就简单了,我们也需要定义一个cookie来模仿浏览器

方式一:直接在请求头中写上cookie

import requests
headers = {
  "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
  "cookie":"xxxxxxxx"     #这里并不是cookie就长这个样子,只是我懒得写了吼吼吼
}
url = "https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=114438&size=15"
response = resquests.get(url=url,headers=headers).text
print(response)

方式二:利用session会话来获取cookie,我们需要定义一个session会话,然后利用session会话来向目标地址发送get或者post请求,这时如果服务端产生了cookie会自动存储在session对象中,而下一次请求session就会自动携带cookie,这也就意味着session必须向目标服务器发送至少两次请求

import requests
from lxml import etree
headers = {
    "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
}
s = requests.Session()
first_url = "http://xueqiu.com"
s.get(first_url,headers=headers)

url = "https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=111264&size=15"
json_text = s.get(url,headers=headers).text
print(json_text)
json_text.ecoding="utf-8"

response = requests.get(url=url,headers=headers).text

with open("./xueqiu.html","w")as f:
    f.write(json_text)

所以当我们遇到了cookie限制了我们的爬取时我们可以再两种方法中选取一种

IP封锁

有些网站针对爬虫机制是有特殊的防御手段的,但是比较常见的手段ip封锁就是其中之一,当一个ip对目标服务器访问次数有异常(比如访问频率过快,访问次数过多等)目标服务器就会限制该IP访问,这时你的爬虫程序就会停止,那么我们该如何避免这种事情的发生呢?

爬虫程序停止的原因是因为ip被限制我们无法再从目标服务器获取数据,那么我们只需要更换我们所访问的ip即可,由此我们引出了代理概念。

代理的分类:

  • 正向代理:代理客户端获取数据。正向代理是为了保护客户端防止被追究责任。

  • 反向代理:代理服务器提供数据。反向代理是为了保护服务器或负责负载均衡。

我们可以通过一些网站来获取代理地址(我使用的就是智联代理,还有许多不同的代理网站,那样的话处理ip地址的方式就要大家自己开动脑筋了),然后发送请求的时候以这些代理地址的ip去访问

import random
ips = []   #设置代理池
ip_url = "代理网站地址"
page_text = requests.get(ip_url,headers=headers).text #获取具体路由界面
tree = etree.HTML(page_text)
ip_list = tree.xpath("根据内部规则进行页面数据解析")
for ip in ip_list:
     dic = {"https":ip}  #进行IP地址拼接
     ips.append(dic)   #装入代理池

url = "爬取网站"
all_data = []
for page in range(2,10):
    pass
通过request设置proxies属性来进行ip地址更换

验证码解决方案

这也是比较日常的一种反爬机制,当我们进行登录验证的时候(或者其他的一些时候)会出现图片验证码来阻拦我们使用程序进行数据爬取,正所谓道高一尺,魔高一尺二。一些特殊的验证码处理网站应运而生(因为再让大家学习图像处理可能会有点吐血,所以我们还是用现成的吧)

超级鹰网站:用于进行验证码处理,不同的验证码有不同的处理code,我们只需要将图片与相应的验证序号发送给超级鹰网站,网站会为我们返回相应的解决。我在这里就不在详细介绍超级鹰如何使用大家可以去官方看开发文档如何对接。

在这里我们来介绍一个模仿登录的实例给大家,需要注意的是我们需要提前下载一个chaojiying.py的文件

from chaojiying import Chaojiying_Client
def get_code(imgPath,imgType):

    chaojiying = Chaojiying_Client('用户名', '密码', '软件id')  
    im = open(imgPath, 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    print(chaojiying.PostPic(im, imgType))
url = "https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx"
response = requests.get(url,headers=headers).text
tree = etree.HTML(resopnse)
__VIEWSTATE = tree.xpath('//*[@id="__VIEWSTATE"]/@value')[0]
__VIEWSTATEGENERATOR = tree.xpath('//*[@id="__VIEWSTATEGENERATOR"]/@value')[0]
img_path = 'https://so.gushiwen.cn'+tree.xpath("//*[@id='imgCode']/@src")[0]
img_data = requests.get(url=img_path,headers=headers).content
with open('./imgCode.jpg','wb') as f:
    f.write(img_data)
result = get_code('./imgCode.jpg',1902)

login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data = {
    '__VIEWSTATE': __VIEWSTATE,
    '__VIEWSTATEGENERATOR': __VIEWSTATEGENERATOR,
    'from': 'http://so.gushiwen.cn/user/collect.aspx',
    'email': '13102165156@163.com',
    'pwd': '123456',
    'code': result,
    'denglu': '登录',
}
s = requests.Session()
page_text = s.post(url=login_url,headers=headers,data=data).text
with open('./login.html','w',encoding='utf-8') as fp:
    fp.write(page_text)

这里整个过程我们唯一之前没有提到过的就是超级鹰的使用,还是推荐大家去看看官方开发文档,里面有你需要的py文件和详细的解释。

selenium仿照浏览器运作

selenium是python中的一个模块,其主要功能就是打开一个浏览器窗口,用代码实现模仿点击,登录等一系列类人行为动作。

准备材料:一款浏览器驱动,在这里我举例的是谷歌浏览器,也就是你需要一个chromdriver的驱动文件来帮助你打开浏览器

from selenium import webdriver #模块模仿浏览器打开
from time import sleep
#实例化一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver')

bro.get('https://www.bilibili.com/')#向目标地址发送请求

search_box = bro.find_element_by_xpath('//*[@class="nav-search-keyword"]')#通过标签找到搜索框
search_box.send_keys('郭德纲')#输入搜索内容

btn = bro.find_element_by_xpath("//*[@class='nav-search-btn']/button")#找到搜索按键
btn.click()#点击事件
sleep(2)
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')#拉到底部
sleep(2)
bro.quit()#关闭浏览器
#########################################################################################
bro = webdriver.Chrome(executable_path='./chromedriver')
url = "http://scxk.nmpa.gov.cn:81/xk/"
bro.get(url)
sleep(1)
all_page_text = [bro.page_source]  #获取页面源码
for i in range(5):
    next_btn = bro.find_element_by_xpath('//*[@id="pageIto_next"]')
    next_btn.click()
    sleep(1)
    all_page_text.append(bro.page_source)

for page_text in all_page_text:
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//*[@id="gzlist"]/li')
    for li in li_list:
        name = li.xpath('./dl/@title')[0]
        print(name)

bro.quit()

通过两个实例为大家简单介绍一下selenium用法,我们之后将结合selenium的动作链概念实现12306的登录与网易新闻数据爬取

 

posted @ 2020-10-03 18:29  TopJocker  阅读(164)  评论(0编辑  收藏  举报