Python

[CP_07] Python爬虫之urllib库数据挖掘、实践案

2019-03-27  本文已影响0人  Fighting_001

目录结构

一、urllib库的应用
    1. Python爬虫入门案例
    2. 自定义请求
    3. 伪装浏览器原理
        1)单个User-Agent爬虫-案例
        2)多个User-Agent爬虫-案例
    4. 自定义opener
    5. 使用代理IP
二、Python爬虫-实践案例
    1. 处理GET请求
    2. 网页翻页下载爬虫-案例
    3. 处理POST请求案例:实现词语中英文翻译
三、异常处理 & cookie模拟登录
    1. 异常处理
    2. cookie模拟登录

一、urllib库的应用

1. Python爬虫入门案例

案例:利用Python请求获取指定url的响应数据(获取信息),然后对获取的数据进行正则匹配以提取指定的内容(清洗信息)
crawler001.py

from urllib import request
import re

# 获取信息
# 确定爬虫的对象url
url=r"http://www.sogou.com"
# 发送请求,获取响应信息
data=request.urlopen(url).read()
data=data.decode()  # 解码:bytes转字符串,展示中文

# 清洗信息
# 定义正则,匹配title标签中任意长度的任意字符
pat="<title>(.*?)</title>"
data=re.findall(pat,data)   # 在响应数据中匹配符合正则的字符串

print(data)

清洗数据之前,所获取的响应数据为:

清洗数据之后,提取的信息为:

2. 自定义请求

crawler002.py

from urllib import request
import re

# 获取信息
url=r"http://www.sogou.com"
# 创建自定义请求对象(可封装url、User-Agent...)
rq=request.Request(url)
# 发送请求,获取响应信息
data=request.urlopen(rq).read()
data=data.decode()

# 清洗信息
pat="<title>(.*?)</title>"
data=re.findall(pat,data)

print(data[0])

备注说明:
crawler001.py 是直接在urlopen()中放入url,此时只封装了url
crawler002.py 通过自己创建自定义对象(rq),可封装url、User-Agent等信息(应对反爬虫机制),不限于只能封装url

3. 伪装浏览器原理

反爬虫机制:
① 通过判断是否使用浏览器访问,若是则通过访问,若不是则拦截访问
② 通过使用与真实浏览器一致的User-Agent信息,伪装为浏览器进行访问;同一个浏览器,不同请求对应的User-Agent信息是一致的
③ 多线程实现多次循环爬取时,若只采用同一个User-Agent,很可能被拦截访问,此时每次循环时需要从众多不同的User-Agent中随机获取使用

传送门:
常用浏览器(PC,移动) user-agent
手机UserAgent库

1)单个User-Agent爬虫-案例

crawler003.py

from urllib import request
import re

# 获取信息
url=r"http://www.sogou.com"
# 创建header字典(构造浏览器中的Request Headers)
header={
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; rv:65.0) Gecko/20100101 Firefox/65.0"
}
# 创建自定义请求对象(可封装url、User-Agent...)
rq=request.Request(url,headers=header)
# 发送请求,获取响应信息
data=request.urlopen(rq).read()
data=data.decode()

# 清洗信息
pat="<title>(.*?)</title>"
data=re.findall(pat,data)

print(data[0])
2)多个User-Agent爬虫-案例

crawler004.py

from urllib import request
import re
import random

# 获取信息
url=r"http://www.sogou.com"

agent1="User-Agent,Mozilla/5.0 (Windows NT 6.1; rv:65.0) Gecko/20100101 Firefox/65.0"
agent2="User-Agent, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"
agent3="User-Agent,Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11"
agent4="User-Agent, MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
agent5="Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; BLA-AL00 Build/HUAWEIBLA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/8.9 Mobile Safari/537.36"
agent6="Mozilla/5.0 (Linux; Android 5.1.1; vivo X6S A Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044207 Mobile Safari/537.36 MicroMessenger/6.7.3.1340(0x26070332) NetType/4G Language/zh_CN Process/tools"
ls=[agent1,agent2,agent3,agent4,agent5,agent6]
agent=random.choice(ls)
print(agent)

# 创建header字典(构造浏览器中的Request Headers)
header={"User-Agent":agent}
# 创建自定义请求对象(可封装url、User-Agent...)
rq=request.Request(url,headers=header)
# 发送请求,获取响应信息
data=request.urlopen(rq).read()
data=data.decode()

# 清洗信息
pat="<title>(.*?)</title>"
data=re.findall(pat,data)

print(data[0])

4. 自定义opener

其前使用的urlopen是一个特殊的opener(模块构建好的对象),但urlopen()方法不支持代理、cookie等高级功能。为支持此类功能,通过request.build_opener()方法创建自定义opener对象;使用自定义的opener对象,调用open()方法发送请求。
若程序里所有请求都使用自定义的opener,则可使用request.install_opener()将自定义的opener 对象定义为全局opener,当调用urlopen,都将使用这个opener。

opener.py

from urllib import request

# 构建HTTP处理器对象(专门处理请求的对象)
http_hander=request.HTTPHandler()
# 创建自定义的opener对象
opener=request.build_opener(http_hander)

# 创建自定义请求对象
url="http://www.sogou.com"
rq=request.Request(url)

# 发送请求,获取响应
rp=opener.open(rq).read().decode()

print(rp)

将opener对象设置为全局对象,当使用urlopen时也会调用opener对象,如下:
global-opener.py

from urllib import request

# 构建HTTP处理器对象(专门处理请求的对象)
http_hander=request.HTTPHandler()
# 创建自定义的opener对象
opener=request.build_opener(http_hander)

# 创建自定义请求对象
url="http://www.sogou.com"
rq=request.Request(url)

# 发送请求,获取响应
# rp=opener.open(rq).read().decode()

# 将自定义opener设置为全局对象
request.install_opener(opener)
# 此时使用urlopen也会调用opener对象
rp=request.urlopen(rq).read().decode()

print(rp)

5. 使用代理IP

反爬虫方式1:使用User-Agent,伪装成浏览器发送请求
反爬虫方式2:判断请求来源的IP地址,使用代理IP

传送门:西刺免费代理IP

proxy.py

from urllib import request
import random

# 代理IP组成的列表
proxylist=[
    {"http":"221.10.159.234:1337"},
    {"http":"61.189.242.243:55484"},
    {"http":"112.85.169.8:9999"},
    {"http":"114.119.116.92:61066"},
    {"http":"110.52.235.65:9999"},
    {"http":"27.43.189.219:9999"}
]
# 从以上IP列表中随机取出1个IP
proxy=random.choice(proxylist)
print(proxy)

# 构建代理处理器对象
proxyHandler=request.ProxyHandler(proxy)
# 创建自定义opener对象
opener=request.build_opener(proxyHandler)
# 创建请求对象
url="http://www.sogou.com"
rq=request.Request(url)
# 发送请求,获取响应
rp=opener.open(rq).read().decode()
print(rp)

二、Python爬虫-实践案例

1. 处理GET请求

get.py

import urllib
from urllib import request

# http://www.sogou.com/web?query=%E6%B5%8B%E8%AF%95

# 分离url中的中文参数项
query={"query":"测试"}
url_0="http://www.sogou.com/web?"

# 构造url的参数值编码;parse解析url
q=urllib.parse.urlencode(query)
print(q)
url=url_0+q # 拼接为完整的url请求链接

# 创建请求对象
rq=request.Request(url)
# 发送请求,获取响应
rp=request.urlopen(rq).read().decode()
print(rp)

2. 网页翻页下载爬虫-案例

案例目标:根据用户输入的关键词,进入对应公众号搜索结果页面,从指定页码范围下载html文件存储到本地

分析页码的规律:
第1页 ==> http://weixin.sogou.com/weixin?query=python&_sug_type_=&s_from=input&_sug_=y&type=1&page=1&ie=utf8
第2页 ==> http://weixin.sogou.com/weixin?query=python&_sug_type_=&s_from=input&_sug_=y&type=1&page=2&ie=utf8
第3页 ==> http://weixin.sogou.com/weixin?query=python&_sug_type_=&s_from=input&_sug_=y&type=1&page=3&ie=utf8
第4页 ==> http://weixin.sogou.com/weixin?query=python&_sug_type_=&s_from=input&_sug_=y&type=1&page=4&ie=utf8

页码规律:page=页码

web-page-store.py

from urllib import request
import urllib

header={
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; rv:65.0) Gecko/20100101 Firefox/65.0"
}

# 方法1:发送url请求,从服务器获取响应文件(爬取网页)
def loadPage(fullurl,filename):
    print("正在下载:",filename)
    rq=request.Request(fullurl,headers=header)
    rp=request.urlopen(rq).read()
    return rp

# 方法2:将HTML内容写入本地保存
def writePage(html,filename):
    print("正在保存:",filename)
    with open(filename,"wb") as f:
        f.write(html)
    print("-----------")

# 方法3:处理指定页码范围的页面的url(调用<方法1+方法2>)
def storeData(url,start,end):
    for i in range(start,end+1):
        page=i
        fullurl=url+"&page="+str(page)  # 每次请求的完整url
        # 每次请求后保存的文件名
        filename=r"D:\CI_Env\Python_Test\file\第"+str(page)+"页.html"
        html=loadPage(fullurl,filename) # 调用爬虫,爬取网页
        writePage(html,filename)    # 将获取到的html网页内容写入本地保存

# 主函数:通过程序入口控制代码执行(调用方法3)
if __name__ == '__main__':
    query=input("请输入公众号关键词:")
    start=int(input("请输入起始页码:"))
    end=int(input("请输入终止页码:"))

    url="http://weixin.sogou.com/weixin?"
    para=urllib.parse.urlencode({"query":query})    # 解析参数取值
    url=url+para

    storeData(url,start,end)    # 调用执行处理指定页码的url

执行结果:

3. 处理POST请求案例:实现词语中英文翻译

案例目标:根据用户输入的词语(中文or英文),实现中英文互译

原始url:http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
调整url:http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule
请求方式:POST

代码实现:
yd-fanyi.py

from urllib import request
import urllib
import re

header={
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; rv:65.0) Gecko/20100101 Firefox/65.0"
}

url="http://fanyi.youdao.com/translate?smartresult:dict&smartresult:rule"

words=input("翻译词语:")

# POST请求需要提交的参数(表单数据为字典类型)
formdata={
    "i":words,
    "from":"AUTO",
    "to":"AUTO",
    "smartresult":"dict",
    "client":"fanyideskweb",
    "salt":"15535312968212",
    "sign":"d6bd41d13ab6467bec455ff06c356b33",
    "ts":"1553531296821",
    "bv":"e2a78ed30c66e16a857c5b6486a1d326",
    "doctype":"json",
    "version":"2.1",
    "keyfrom":"fanyi.web",
    "action":"FY_BY_REALTlME",
    "typoResult":"false"
}

# 经过urlencode转码,然后用utf-8进行编码
data=urllib.parse.urlencode(formdata).encode(encoding='utf-8')
# 创建POST请求对象
req=request.Request(url,data=data,headers=header)
# 发送请求,获取响应数据
resp=request.urlopen(req).read().decode()

# 定义正则,提取翻译的内容(此时为list类型)
pat=r'"tgt":"(.*?)"'
result=re.findall(pat,resp)
# 从列表中获取翻译的有效内容
print("翻译结果:",result[0])

执行结果:

三、异常处理 & cookie模拟登录

1. 异常处理

爬虫过程中请求次数较多的场景,有可能某些请求可正常执行,某些请求异常。当请求出现异常时,为了不影响后续请求能够继续执行,需要引入异常处理机制(如:Try/Except)

exception1.py

from urllib import request

list1=[
"http://www.baidu.com",
"http://www.sogou.com",
"http://abc.123.xyz",
"http://cn.bing.com",
"http://www.yahoo.com"
]

i=0
for url in list1:
    i=i+1
    request.urlopen(url)
    print("完成请求",i)

未对异常处理时,执行结果:

exception2.py

from urllib import request

list1=[
"http://www.baidu.com",
"http://www.sogou.com",
"http://abc.123.xyz",
"http://cn.bing.com",
"http://www.yahoo.com"
]

i=0
for url in list1:
    i=i+1
    try:
        request.urlopen(url)
        print("完成请求",i)
    except Exception as e:
        print(e)

处理过异常,执行结果:

2. cookie模拟登录

cookie常用作保持登录状态。若登录成功,则会出现提示登录的用户名:

cookie.py

from urllib import request
import re

url="http://localhost/dvwa/index.php"

header={
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; rv:65.0) Gecko/20100101 Firefox/65.0",
    "Cookie":"security=impossible; PHPSESSID=pdujt5fsk535jscvotfma0bq26"
}

# 创建请求对象(GET请求)
req=request.Request(url,headers=header)
# 发送请求,获取响应数据
resp=request.urlopen(req).read().decode()
# print(resp)

# 定义正则,提取登录后才能获取的有效信息
pat1=r"<h1>(.*?)</h1>"
pat2=r"<em>Username:</em> (.*?)<br />"
result1=re.findall(pat1,resp)
result2=re.findall(pat2,resp)
print(result1[0]+"\n"+result2[0])

执行结果:

上一篇下一篇

猜你喜欢

热点阅读