zoukankan      html  css  js  c++  java
  • 初级爬虫第三天

    主要内容:

    • 付费IP的使用方式
    • Auth认证
    • cookie登录验证
    • requests模块

     一、付费IP使用方式:

    1.1 无论是免费IP还是付费IP,在使用之前,都需要测试一下,如果好使,再去使用IP爬取数据。

    1.2 IP池:列表套字典

    eg:[{"https": "IP1:端口1"}, {"http": "IP2: 端口2"}, {"https": "IP3: 端口3"}]

    1.3 遍历IP池,利用遍历出来的IP创建IP处理器,再利用处理创建发送网络请求的opener对象

    1.4 opener.open()中有一个参数timeout=x,即:x秒之后如果程序还没有反应,就算做超时,报超时,x默认为30

    1.5 利用异常处理IP值不好用的报错或者超时

    代码:

     1 import urllib.request
     2 
     3 爬取百度首页"https://www.baidu.com/"
     4 def proxy_user():
     5     #1.目标网页URL
     6     url = "https://www.baidu.com/"
     7     #2. User-Agent
     8     user_agent = ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"]
     9     request = urllib.request.Request(url)
    10     request.add_header("User-Agent", user_agent[0])
    11     #3. 代理IP池
    12     #3.1 创建代理IP池
    13     #IP池结构是:列表套字典
    14     proxy_ip_list = [{"HTTP": "58.253.152.23:9999"}, {"HTTP": "112.87.68.242:9999"}, {"HTTP": "60.13.42.99:9999"}]
    15     #3.2 遍历IP
    16     for choose__proxy_ip in proxy_ip_list:
    17         #3.3 利用遍历出来的IP创建IP处理器
    18         proxy_ip_handler = urllib.request.ProxyHandler(choose__proxy_ip)
    19         #3.4 利用处理器创建opener对象
    20         opener = urllib.request.build_opener(proxy_ip_handler)
    21         #3.5 发送网络请求
    22         #利用异常处理+timeout参数,处理IP失效问题
    23         #如果IP使用异常,或者超过timeout设置时间,
    24         #则抛出异常,暂停使用当前IP,接着使用下一个IP
    25         try:
    26             #使用opener.open()发送网络请求,
    27             #超时参数timeout设置为10,超过10秒未响应,视为超时
    28             response = opener.open(request, timeout = 10)
    29         except Exception as e:
    30             #如果IP使用异常,或者超时,打印异常信息
    31             print(e)
    32             
    33 
    34 proxy_user()

     

    查看结果,发现当上一个IP不好用时,程序会自动使用下一个IP

    2. 付费IP的两种写法:

    2.1 写法1:发送付费的代理IP请求

    (1)创建代理IP池

    (2)创建handler处理器

    (3)创建opener对象

    (4)发送网络请求

    注意:付费代理IP需要有:1. 购买时的用户名 2. 购买时的密码

    代理IP池结构:列表套字典

    其中字典结构:{"协议类型": "username: password@IP地址:端口号"}

     1 import urllib.request
     2 
     3 #付费代理IP第一种写法:
     4 def money_proxy_user():
     5     #url = "http://www.baidu.com/"
     6     
     7     #1. IP池
     8     #结构:{"http/https": "username:pwd@IP:端口号"}
     9     money_proxy_list = [{"http": "abc:123@58.253.152.23:9999"}, 
    10                         {"http": "abc:123@112.87.68.242:9999"}, 
    11                         {"http": "abc:123@60.13.42.99:9999"}]
    12     #遍历IP
    13     for proxy_ip in money_proxy_list:
    14         #2. 创建代理IP处理器handler
    15         ProxyHandler = urllib.request.ProxyHandler(proxy_ip)
    16         #3. 创建opener对象
    17         opener = urllib.request.build_open(ProxyHandler)
    18         #4. 发送网络请求
    19         response = opener.open(url)                

    2.2 付费IP第二种写法:使用密码管理器(推荐)

    (1)创建IP池

    (2)创建密码管理器

    (3)向密码管理器中,添加用户名和密码

    (4)创建处理器

    (5)创建opener对象

    (6)opener对象发送网络请求

     1 import urllib.request
     2 
     3 #付费代理IP第二种写法:
     4 def money_proxy_user():
     5     url = "http://www.baidu.com/"
     6     
     7     #1. 创建IP池
     8     #结构:{"http/https": "IP值:端口号"}
     9     money_proxy_list = [{"http": "58.253.152.23:9999"}, 
    10                         {"http": "112.87.68.242:9999"}, 
    11                         {"http": "60.13.42.99:9999"}]
    12     #遍历IP
    13     for proxy_ip in money_proxy_list:
    14         #2. 创建密码管理器
    15         #密码管理器需要购买IP的用户名和密码
    16         user_name = "abc"
    17         password = "123"
    18         pass_word_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    19         #3. 向密码管理器添加用户名和密码
    20         pass_word_manager.add_password(None, proxy_ip, user_name, password)
    21         #4. 创建handler处理器
    22         money_proxy_handler = urllib.request.ProxyBasicAuthHandler(pass_word_manager)
    23         #5. 创建opener对象
    24         opener =urllib.request.build_opener(money_proxy_handler)
    25         #6. 发送请求
    26         response = opener.open(url)
    27         

    注意:

    1. 密码管理器对象,添加用户名和密码的方法:'

    add_password(Realm, uri, user_name, password)

    第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None

    参数uri:填写代理IP!!!

    user_name:付费IP用户名

    password:付费IP密码

    2. 本方式中,如果程序中提供的代理IP全部都不能使用,程序会使用本地IP

    二、Auth认证:

    使用范围:

    (1)爬取公司内网数据

    (2)通过第三方认证的方式(如:微信账号登录),进行爬取

    方法:使用密码管理器

    代码:

     1 import urllib.request
     2 
     3 def auth_user():
     4     #1. 给出内网账号和密码
     5     user_name = "abc"
     6     pwd = "123"
     7     #2. 内网的URL地址
     8     nei_url = "xxx"
     9     
    10     #3. 创建密码管理器
    11     pwd_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
    12     #4. 向密码管理器中,添加用户名和密码
    13     #注意此时,add_password()的第二个参数要访问的目标网页URL地址
    14     pwd_manager.add_password(None, nei_url, user_name, pwd)
    15     
    16     #5. 创建处理器Handler
    17     auth_handler = urllib.request.HTTPBasicAuthHandler(pwd_manager)
    18     #6. 创建opener对象
    19     opener = urllib.request.build_opener(auth_handler)
    20     
    21     #7. 发送网络请求:
    22     response = opener.open(nei_url)

     

    2.5:SSL爬虫报错:SSL: CERTIFICATE_VERIFY_FAILED

    当使用urllib.request.urlopen()向https网页发送网络请求时,有时会报这个错误:

    urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)

    解决方法:导入ssl模块和如下代码,即可解决

    1 import ssl
    2 
    3 ssl._create_default_https_context = ssl._create_unverified_context

    三、Cookie与登录信息:

    目标:爬取药智网的会员中心页面数据

    URL:https://www.yaozh.com/member/

    目标网页截图:

    3.1  第一次爬取:

     1 import urllib.request
     2 import ssl
     3 
     4 #忽略SSL验证
     5  ssl._create_default_https_context = ssl._create_unverified_context
     6 
     7 #1. 目标网页URL
     8 url = "https://www.yaozh.com/member/"
     9 
    10 #2. User-Agent
    11 #2.1 创建request对象
    12 request = urllib.request.Request(url)
    13 #2.2 User-Agent池
    14 user_agent_headers = ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"]
    15 #2.3 向request对象添加User-Agent
    16 request.add_header("User-Agent", user_agent_headers[0])
    17 
    18 #也可以直接在创建request对象时,添加User-Agent
    19 #request = urllib.request.Request(url, headers=user_agent_headers[0])
    20 
    21 
    22 #3. 代理IP
    23 #3.1 代理IP池
    24 proxy_ip = {"https": "60.13.42.101:9999"}
    25 #3.2 创建自定义处理器handler
    26 proxy_handler = urllib.request.ProxyHandler(proxy_ip)
    27 #3.3 创建自定义opener对象
    28 opener = urllib.request.build_opener(proxy_handler)
    29 
    30 
    31 #4. 发送网络请求
    32 response = opener.open(request)
    33 
    34 #5. 读取返回的数据
    35 data = response.read().decode('utf-8')
    36 
    37 #6. 数据持久化
    38 with open("yaozh01.html", 'w', encoding='utf-8') as f:
    39     f.write(data)

    得到结果:

    结果,个人中心页面未登录

    ——(1)原因:登录需要账号信息:用户名和密码

    但是,爬虫代码中,没有这两个信息

    ——(2)解决方法:向请求头中,添加cookie

    因为,所有的个人信息,包括:账号和密码都保存在cookie中。

    一旦用户登录成功,其账号和密码就会自动保存在cookie中。

    而cookie位于请求头中。

    ——(3)所以,我们需要先登录成功一次,获取cookie,然后,将cookie添加到请求头中。这样,以后爬虫代码发送网络请求登录时,就可以自动使用第一次登陆成功后,保存下来的cookie,使用它里面的账号信息。

    3.2 方式1:手动获取添加cookie:

    (1)手动登录账号,进入个人中心页面

    (2)f12,进入network,查看请求头request_headers

    (3)如图所示,将cookie后面的所有信息全部复制粘贴,添加进请求头

    (4)发送网络请求

     1 import urllib.request
     2 import ssl
     3 
     4 
     5 #爬取药智网会员中心界面
     6 #"https://www.yaozh.com/member/"
     7 
     8 #忽略SSL验证
     9 ssl._create_default_https_context = ssl._create_unverified_context
    10 
    11 #1. 目标网页URL
    12 url = "https://www.yaozh.com/member/"
    13 
    14 #2. 请求头信息
    15 #User-Agent、Cookie
    16 #手动填写用户名和密码,进行登录,登陆成功之后,在会员中心页面,f12查看请求头信息,复制User-Agent和Cookie信息
    17 user_agent = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
    18               "Cookie": "acw_tc=2f624a1c15572983332095835e56ab374f19bbfa04320ed34624c8cb736211; PHPSESSID=db04icmo08qlth57e283e1jug6; Hm_lvt_65968db3ac154c3089d7f9a4cbb98c94=1557298333; MEIQIA_VISIT_ID=1KwMiirKV6lBEDTorlxXFpIQYZ2; MEIQIA_EXTRA_TRACK_ID=1KwMiirgbfupj7bs3kZzgBM0zWb; Hm_lpvt_65968db3ac154c3089d7f9a4cbb98c94=1557298612; yaozh_logintime=1557298624; yaozh_user=743973%09wtf1234; yaozh_userId=743973; db_w_auth=666998%09wtf1234; UtzD_f52b_saltkey=NQ3FQNjM; UtzD_f52b_lastvisit=1557295025; UtzD_f52b_lastact=1557298625%09uc.php%09; UtzD_f52b_auth=760dhxbJO6R21izVhpr2PAlqsjjpHEtuxu9QWpf%2FdzfvGFnBP6V66TEdhcVOWltYjPEmVh4tVSLLQTPKM12K%2BlK55Ls; yaozh_uidhas=1; yaozh_mylogin=1557298627; acw_tc=2f624a1c15572983332095835e56ab374f19bbfa04320ed34624c8cb736211; MEIQIA_VISIT_ID=1KwMiirKV6lBEDTorlxXFpIQYZ2; MEIQIA_EXTRA_TRACK_ID=1KwMiirgbfupj7bs3kZzgBM0zWb"
    19               }
    20 #2.2 创建request对象,并添加User-Agent
    21 request = urllib.request.Request(url, headers=user_agent)
    22 
    23 
    24 #3. 代理IP
    25 #3.1 代理IP,IP池
    26 proxy_ip = {"https": "115.159.155.60:8118"}
    27 #3.2 创建自定义处理器对象handler
    28 proxy_handler = urllib.request.ProxyHandler(proxy_ip)
    29 #3.3 创建自定义opener对象
    30 opener = urllib.request.build_opener(proxy_handler)
    31 
    32 
    33 #4. 发送网络请求,登录
    34 response = opener.open(request)
    35 #5. 读取返回数据
    36 data = response.read().decode('utf-8')
    37 
    38 #6. 数据持久化
    39 with open("yaozhi02.html", "w", encoding='utf-8') as f:
    40     f.write(data)

     结果:

    可以看到,在本机启动的网页会员中心,这次有了用户名,说明登录成功。

    ———手动获取cookie的缺点:(1)麻烦;(2)获取的cookie有时效性

    3.3 方式2:使用代码自动获取cookie(重点)

    目标:自动获取(登陆后的)会员中心页面

    难点:获取cookie,即:获取登录所需用户名和密码。由于在登录成功之后,Cookie会被自动保存,所以,要想获取Cookie,先要登录成功。

    登录页面login和会员中心页面member是两个不同的页面,所以需要我们现在login页面登录成功,然后拿着cookie,去请求member页面

    步骤:

    (1)自动登录(但需要自己手动设置用户名和密码),登录成功之后,会自动保存Cookie

    (2)代码自动获取Cookie

    (3)带着cookie,代码请求会员中心页面,获取会员中心数据

    ———————————分割线—————————————————————

    (1)为了能让程序自动登录,我们需要查看,登录过程中,浏览器都向服务器提交了哪些数据

    由于登录过程为:

    1. 浏览器向服务器提交登录数据
    2. 服务器验证数据
    3. 服务器向浏览器发送新的跳转页面的链接
    4. 浏览器按照跳转页面的链接,向服务器重新发送请求

    所以,在登录页面,点击“登录”按钮之后,页面会跳转到新的页面。此时浏览器network抓取到的数据,是第4步:浏览器向服务器按照跳转页面URL,向服务器发送请求时,的数据;而不是第1步:浏览器向服务器提交的登录数据。因为谷歌浏览器会只保留最新一次请求的数据,而将之前的请求抹除了。

    所以,在f12的network中,点击preserve log按钮,这样浏览器就会保留之前发送过的请求日志。

    点击preserve log按钮,在https://www.yaozh.com/login/操作登录,发现浏览器进行登录时,发送的是一个叫做“login”的网络请求。

    点击login请求,发现:(1)login发送的是POST请求!!!;(2)Form Data:Form Data为需要发送POST请求时,要发送的参数

     

     1 import urllib.request
     2 import urllib.parse
     3 import http.cookiejar
     4 import ssl
     5 
     6 #忽略SSL验证
     7 ssl._create_default_https_context = ssl._create_unverified_context
     8 
     9 #目标:爬取会员中心网页
    10 
    11 #1. 会员登录,获取cookie
    12 #1.1 登录网页URL
    13 login_url = "https://www.yaozh.com/login/"
    14 
    15 #1.2 请求头信息User-Agent
    16 user_agent = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"}
    17 
    18 #1.3 构造请求参数
    19 #构造POST请求参数,格式必须是字典
    20 #发现登录请求中,发送的是POST请求,POST请求有请求参数
    21 #POST请求中需要用到的参数:位于浏览器请求头的Form Data中,将其中的数据全部复制下来
    22 """
    23 username: wtf1234
    24 pwd: 123456
    25 formhash: 3210139E64
    26 backurl: https%3A%2F%2Fwww.yaozh.com%2F
    27 """
    28 login_request_data = {"username": "wtf1234",
    29                       "pwd": "123456",
    30                       "formhash": "3210139E64",
    31                       "backurl": "https%3A%2F%2Fwww.yaozh.com%2F"}
    32 
    33 
    34 #1.4 转换POST请求参数格式
    35 #POST请求中,上传的请求参数必须是2进制格式
    36 login_request_data_bytes = urllib.parse.urlencode(login_request_data).encode("utf-8")
    37 
    38 #1.5 向request对象中,添加URL地址、User-Agent、POST请求参数
    39 #get请求中,参数拼接到URL地址中;POST请求中,Request对象里面专门有个data参数,用于接收POST请求参数
    40 login_request = urllib.request.Request(login_url, headers=user_agent, data=login_request_data_bytes)
    41 
    42 #1.6 构造CookieJar对象——用于保存管理cookie
    43 my_cookiejar = http.cookiejar.CookieJar()
    44 
    45 #1.7 构造自定义的可以添加cookie的处理器handler
    46 #handler处理器的参数是构造的cookiejar对象
    47 #因为urlopen()中不能添加cookie,所以我们需要找一个能添加cookie的处理器,然后再创建opener,再发送网络请求
    48 cookie_handler = urllib.request.HTTPCookieProcessor(my_cookiejar)
    49 
    50 #1.8 使用处理器handler对象,构造自定义opener对象
    51 opener = urllib.request.build_opener(cookie_handler)
    52 
    53 #1.9 使用opener对象,发送网络请求
    54 #此时的login_request,既包含请求头信息,又包含请求参数
    55 #此时,如果请求发送成功,则cookiejar对象会自动将cookie信息保存到opener对象中
    56 opener.open(login_request)      #由于我们这里只是为了登录成功,获取cookie,所以不需要response对象接收返回数据
    57 
    58 
    59 #2. 使用cookie,访问会员中心网页
    60 #2.1 会员中心URL
    61 member_url = "https://www.yaozh.com/member/"
    62 
    63 #2.2 构造请求头,添加User-Agent信息
    64 user_agent2 = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"}
    65 member_request = urllib.request.Request(member_url, headers=user_agent2)
    66 
    67 #2.3 拿着刚才获得的cookie,发送网络请求
    68 #由于opener对象中已经保存有cookie信息,所以直接用opener对象发送网络请求即可
    69 response = opener.open(member_request)
    70 
    71 #3. 读取数据
    72 data = response.read().decode("utf-8")
    73 
    74 #4. 持久化
    75 with open("yaozhi_day03.html", 'w', encoding='utf-8') as f:
    76     f.write(data)

     爬取结果:

    注:目前为止学过的反爬机制:

    (1)User-Agent:模拟真实用户

    同一个浏览器,短时间内频繁访问,反爬

    (2)IP地址:

    同一个IP地址,短时间内频繁访问,反爬

    (3)账号:

    同一个账号,短时间内在不同地点(使用不同IP地址)访问,反爬

    三、初学requests模块:

    理论:

    (1)requests模块为第三方模块

    (2)使用方法:import requests     注意末尾多一个s

    (3)优点:

    • 简单易用
    • URL会自动转译
    • python2、python3的方法名字一样
    • 有官方中文文档
     1 import requests
     2 
     3 #爬取百度首页"https://www.baidu.com/"
     4 
     5 #1. 目标网页URL
     6 url = "https://www.baidu.com/"
     7 
     8 #2. 发送get请求
     9 response = requests.get(url)
    10 #返回的response为状态码
    11 
    12 #3.解析数据
    13 #3.1 方式1:使用content属性解析,返回的是2进制数据
    14 data = response.content.decode('utf-8')
    15 
    16 #3.2 方式2:使用text属性解析,返回的是字符串格式数据
    17 str_data = response.text
    18 #但是不建议,使用此种方式解析数据,因为text内部,将2进制数据转换为字符串格式,靠猜。

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    asp.net 学习连接
    学习笔记一
    windows 2008 r2 AD密码策略
    Windows Server 2008 R2之活动目录回收站
    用java 调用 .net 自定义的 Soap WEB Service
    昆明赶街时间
    Windows Server 2008 R2 AD的备份和恢复
    AD 自定义属性
    AD、IIS、asp.net
    wsgen与wsimport命令说明
  • 原文地址:https://www.cnblogs.com/tommyngx/p/10830178.html
Copyright © 2011-2022 走看看