1.异常处理
import urllib.request
import urllib.error
url = "http://www.mobiletrain.org/afd?pinzhuanbdtg=biaoti"
req = urllib.request.Request(url=url)
# res = urllib.request.urlopen(req)
try:
res = urllib.request.urlopen(req)
print("0")
except urllib.error.HTTPError as e:
# 如果是http请求的时候或者响应的时候发生错误,就会检测到HTTPError这个异常
print("1")
print(e)
except urllib.error.URLError as e:
# 网址本身存在错误,这个域名不存在
print("2")
print(e)
except Exception as e:
print(e)
2.微博登陆带cookie,写入html
import urllib.request
url = "https://weibo.cn/6370062528/info"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
"Cookie": "SCF=Ahz9Jk7TyV7zzLvwoCxFjRRTbASUHA9Jp8RcRyRaht68K11D0lYQBg5j9No1B157Zgv7Lx5COUC7DNdjo8APyKc.; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9W59rVpGeZ7yg7I7HR0hyYPg5JpX5KzhUgL.Foq0S057Sozfeon2dJLoI05LxKML1heLB-BLxKqL1heL1h-LxKML1-2L1hBLxKqLBoeLBKzLxKqLBoeLBKz41K.t; SUB=_2A253_53KDeRhGeBN7FIR9izJyTSIHXVVAyOCrDV6PUJbkdANLW75kW1NRFYvPyNwa0XZ3DB_CJthDJ6-896SR-uQ; SUHB=0FQbkbkZxmWpX1; _T_WM=ae4d1af9302c562727db8db7ad8ef936"
}
# http协议是一个无状态的协议,不记录当前的会话的状态,在某些情况下,我们需要记录状态(比如在访问某些用户登录以后的页面中),这个时候就要借助于cookie或者Session来保存用户的信息
#创建请求对象
req = urllib.request.Request(url=url,headers=headers)
#解析网址
res = urllib.request.urlopen(req)
#写入weibo.html文件
with open("weibo.html","wb") as fp:
fp.write(res.read())
3.handler保存会话信息的时候,采用的opener+handler的请求机制
import urllib.request
# Request对象无法保存会话信息,我们需要有另外的一个对象handler,用来保存
# 在handler保存会话信息的时候,采用的opener+handler的请求机制
# 1、创建一个handler对象
handler = urllib.request.HTTPHandler() # 用于保存会话信息
# 2、创建一个opener对象
opener = urllib.request.build_opener(handler) # 用于请求网络
# opener携带了handler,在用其发起http请求的时候就会携带存储在handler中的会话信息
# 构建请求
url = "http://www.baidu.com/"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"
}
req = urllib.request.Request(headers=headers,url=url)
# urllib.request.urlopen(req) # 这个请求无法携带会话信息
# 用opener发出请求,携带会话信息
res = opener.open(req) # 此时在发起请求的时候,就会携带上"http://www.baidu.com"这个网址的cookie
print(res)
4.完整微博登陆
import urllib.request
import urllib.parse
# 处理cookie我们还需要导入cookiejar库
import http.cookiejar
# 登录过程
# 1、创建一个cookiejar对象,用于保存cookie
cookie = http.cookiejar.CookieJar()
# 2、创建一个handker对象,并且让这个handler对象携带上cookie
handler = urllib.request.HTTPCookieProcessor(cookie) # 这个对象是HTTPHandler的子对象
# 3、创建一个opener对象,并且让他携带上handler
opener = urllib.request.build_opener(handler)
# 此时opener所携带的handler对象就有cookie对象的存储,用它发请求就可以存储cookie
# 登录的url
url = "https://passport.weibo.cn/sso/login"
# 请求头
headers_login = {
'Accept': '*/*',
# Accept-Encoding: gzip, deflate, br
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
# Content-Length: 162
'Content-Type': 'application/x-www-form-urlencoded',
'Host': 'passport.weibo.cn',
'Origin': 'https://passport.weibo.cn',
# 'Referer': 'https://passport.weibo.cn/signin/login?entry=mweibo&r=https%3A%2F%2Fweibo.cn%2F&backTitle=%CE%A2%B2%A9&vt=',
'Referer': 'https://passport.weibo.cn/signin/login?entry=mweibo&r=https%3A%2F%2Fweibo.cn%2F%3Fluicode%3D20000174&backTitle=%CE%A2%B2%A9&vt=',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
# 请求体
form_data = {
'username': '18610593606',
'password': 'f12345678',
'savestate': '1',
'r': 'https://weibo.cn/',
'ec': '0',
'pagerefer':'',
'entry': 'mweibo',
'wentry':'',
'loginfrom':'',
'client_id': '',
'code':'',
'qq':'',
'mainpageflag': '1',
'hff':'',
'hfp':''
}
# 将请求体处理成url参数的形式
data = urllib.parse.urlencode(form_data).encode("utf-8")
# print(data)
# 发起一个post请求
req = urllib.request.Request(url=url,headers=headers_login,data=data)
# 登录
# urllib.request.urlopen() # 这个方无法携带cookie
res = opener.open(req)
print(res.read().decode("utf-8"))
# 获取个人资料
info_url = "https://weibo.cn/6370062528/info"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
req = urllib.request.Request(url=info_url,headers=headers)
res = opener.open(req) # 此时如果登录成功,opener就携带当前用户对应的cookie信息,就可以获取当前用户的主要
print(res.read().decode("gb2312"))
5.使用代理服务器代替我们当前客户端去发起请求
import urllib.request
url = "https://www.baidu.com/s?wd=ip"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"
}
# 由于某些网站的反爬机制会通过检测ip地址的访问频率,进而决定是否是爬虫,然后进行封锁
# 通过设置代理服务器,然代理服务器代替我们当前客户端去发起请求,并且将请求结果反馈回来
# 创建一个请求对象
req = urllib.request.Request(url=url,headers=headers)
# 配置代理
handler = urllib.request.ProxyHandler({"http":"114.113.126.86:80"})
# 通过一个handler对象,携带代理服务器的ip地址和端口号
# 创建一个opener携带handler
opener = urllib.request.build_opener(handler)
# 发出请求
res = opener.open(req)
with open("ip.html","wb") as fp:
fp.write(res.read())
# 在实际的项目中代理服务器需要购买
6.正则小使用
import re
# 导入正则支持模块
string = "按时发大水 asdfdsafsadasfds"
pat = r'.*'
s = re.findall(pat,string)
print(s)
7.糗事百科爬取图片到本地
import urllib.request
import re
# 定义一个函数,用于处理url
def handler_url(url,page):
# 把url和page拼接起来
page_url = url + str(page)
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
# 创建请求对象
req = urllib.request.Request(url=page_url,headers=headers)
return req
# 定义一个函数,处理每一个请求对象,发起请求
def request_qiubai(req):
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
# print(html)
return html
# 数据解析,对网页数据进行解析
def anlysis_qiubai(html):
# 用正则表达式来匹配图片的url
pat = re.compile(r'.*?.*?',re.S)
# 正则匹配时,需要加上单行的模式修正
res = pat.findall(html)
# res中存储的是图片的url,对url进行处理
imgs = []
for url in res:
img_url = "http:" + url
imgs.append(img_url)
print(imgs)
return imgs
# 下载图片
def download_imgs(img_url,name):
urllib.request.urlretrieve(img_url,"./images/"+name + '.jpg')
# 业务逻辑
def main():
url = "https://www.qiushibaike.com/pic/page/"
# 输入要获取的页码
start_page = input("请输入起始页:")
end_page = input("请输入终止页:")
print("开始下载...")
# 从起始页到终止页循环遍历
img_name = 0
for i in range(int(start_page),int(end_page)+1):
# 创建每一个页面的请求对象
page_req = handler_url(url,i)
# 发起请求
qiu_html = request_qiubai(page_req)
# 解析网页
res = anlysis_qiubai(qiu_html)
# 下载图片
for img in res:
print("当前正在下载:"+img)
download_imgs(img,str(img_name))
img_name += 1
print("下载完毕!")
if __name__ == '__main__':
main()
8.xpath语法使用
# xpath是一种在xml文件中根据其文档结构来提取目标元素的语法
# html就是一种特殊的xml文件
from lxml import etree
# lxml这个库用于解析和提取xml文件中的内容,etree就是把xml(html)里面内容用一个树形结构来表达
# 如何用xpath语法寻找html里面的内容
# 1、用etree把整个html文档读取出来,并且创建成一棵树
html_tree = etree.parse("./test.html")
print(html_tree) #
# 2、根据树形结构获取目标节点
ret = html_tree.xpath("/html/body/ol/li")
ret = html_tree.xpath("/html/body/div/div/a")
# 3、找节点中的内容与属性
ret = html_tree.xpath("/html/body/ol/li/text()")
ret = html_tree.xpath("/html/body/div/div/a/@href")
# 4、定位
# 1)层级定位
# 找所有li
ret = html_tree.xpath("//body/div//li/text()")
# 在xpath语法中"//"代表前面有若干层,"/"代表前面一层不隔
# 2)属性定位
# 找所有带id属性的li
ret = html_tree.xpath("//li[@id]/text()")
# 找所有class值为dudu的li
ret = html_tree.xpath("//li[@class='dudu']/text()")
# 模糊匹配
# 找左右class值以h开头的li
ret = html_tree.xpath("//li[starts-with(@class,'h')]/text()")
ret = html_tree.xpath("//li[contains(@class,'a')]/text()")
# 逻辑运算
# 找class值为hehe并且id值为tata
ret = html_tree.xpath("//li[@class='hehe' and @id='tata']/text()")
# 找class值为hehe或者class值为haha
ret = html_tree.xpath("//li[@class='hehe' or @class='haha']")
ret = html_tree.xpath("//div[@class='hh kk']/text()")
# 【注意】通过xpath获取到的子节点也可作为当前字节的树根取构造另外一棵节点树
obj = html_tree.xpath("//div[@id='pp']")[0]
ret = obj.xpath("//div")
print(ret)