python爬虫学习笔记3.2-urllib和request练习

一、urllib练习

1.百度贴吧案例

需求

输入贴吧名字,下载查询到的html页面。

分析

手动测试查询流程

进入百度贴吧,输入海贼王查询,点击一个页面右键下载即可。
用代码的方式编写此过程即是找到这个页面的url,请求这个url,获取内容,并保存。因此关键就在于如何找到这个url

观察页面

查询关键字海贼王,结果页面显示如下,观察当前页面,发现有2个地方比较特殊,url部分和分页部分。

分析特殊部分

https://tieba.baidu.com/f?

url中的固定部分

kw

根据前面的知识,kw=%???是’海贼王’的十六进制编码,此处的’海贼王’可以用一个变量表示

pn

分别点击第2,3页,发现url有下列变化,pn在以(n-1)*50递增,按照规律第一页应该pn=0,查询一下和最初显示的页面相同。

https://tieba.baidu.com/f?ie=utf-8&kw=%E6%B5%B7%E8%B4%BC%E7%8E%8B&fr=search
https://tieba.baidu.com/f?kw=%E6%B5%B7%E8%B4%BC%E7%8E%8B&ie=utf-8&pn=50
https://tieba.baidu.com/f?kw=%E6%B5%B7%E8%B4%BC%E7%8E%8B&ie=utf-8&pn=100
# 猜测第一页pn=0
https://tieba.baidu.com/f?kw=%E6%B5%B7%E8%B4%BC%E7%8E%8B&ie=utf-8&pn=0
# 总结规律url的拼接
pn = (n-1)*50
baseurl = 'https://tieba.baidu.com/f?'
url = baseurl + kw + '&pn=' + str(pn)

步骤

  1. 主体架构
  2. 拼接url发起请求,获取响应
  3. 写入文件

代码

import urllib.request
import urllib.parse
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36','Cookie':'BIDUPSID=23F0C104655E78ACD11DB1E20FA56630; PSTM=1592045183; TIEBA_USERTYPE=45a1bae36dc6696040e230ee; BAIDUID=23F0C104655E78AC9F0FB18960BCA3D3:SL=0:NR=10:FG=1; BDUSS=ldxR1FyQ2FEaVZ5UWFjTDlRbThVZHJUQTY1S09PSU81SXlHaUpubVpEY0FMakZmRVFBQUFBJCQAAAAAAAAAAAEAAADzvSajSjdnaGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChCV8AoQlfb; TIEBAUID=524dbb48e125ba59527aac97; BDUSS_BFESS=ldxR1FyQ2FEaVZ5UWFjTDlRbThVZHJUQTY1S09PSU81SXlHaUpubVpEY0FMakZmRVFBQUFBJCQAAAAAAAAAAAEAAADzvSajSjdnaGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChCV8AoQlfb; bdshare_firstime=1598269131458; Hm_lvt_287705c8d9e2073d13275b18dbd746dc=1598269132; MCITY=-158%3A; STOKEN=cbc451dc794ed6487c35c551af2ca5d54091f34c2442a1c32fde578f244fb763; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; PSINO=7; BCLID=9680358736405562036; BDSFRCVID=YCIOJeCin4S2BnTr7aHqhLyxn2KX8jRTH6eCU5vSD8fFhSugyYuoEG0PVf8g0KubhN5xogKKLmOTHpKF_2uxOjjg8UtVJeC6EG0Ptf8g0f5; H_BDCLCKID_SF=tJPH_IIKfII3fP36qRbBb-JH-fTB-4n-HD7yWCvw0hTcOR5JMtIM0TDYhROHt-o7-CbrX4n8tqvibbc-3MA-bftAjqjg0Tvh3DbgLR3Xy45osq0x0hjte-bQypoaaUCtMIOMahv1al7xO-JoQlPK5JkgMx6MqpQJQeQ-5KQN3KJmfbL9bT3tjjISKx-_t6DOJbnP; H_PS_PSSID=32757_32617_1428_32844_7544_31660_32723_32230_7517_32116_32718; Hm_lvt_98b9d8c2fd6608d564bf2ac2ae642948=1600675770,1600675812,1600872339,1602504063; st_key_id=17; 2737225203_FRSVideoUploadTip=1; Hm_lpvt_98b9d8c2fd6608d564bf2ac2ae642948=1602505620; st_data=2b0ded14593ade58fc1a8d50a2f8ad7928c0bef12b48ebbd60bb645cad4e10201acccc373eb356fdb56f6b0ab617ed5e9d082b71565c956d9457486ef5e25c9a41e1b40af6e8a9d866b3c7a8d4d97dc777b505aa5d3d8bb075e6c986c224472b12b37c80b76e6e1a7db114cfa47189ff53f19ad35b79cc1a1bc8ecc582d370da86edef6d209dfe8a4ba628a4880dd0fd; st_sign=7d6a3224'
}

# 主体架构
name = input('请输入贴吧的名字:')
begin = int(input('请输入起始页:'))
end = int(input('请输入结束页:'))

kw = {'kw':name}
kw = urllib.parse.urlencode(kw)

# 拼接url 发请求,获响应
for i in range(begin,end+1):

    pn = (i-1)*50
    # print(pn) https://tieba.baidu.com/f?kw=%???&pn=0
    baseurl = 'https://tieba.baidu.com/f?'
    url = baseurl + kw + '&pn=' + str(pn)
    # print(url)
    # 发起请求
    req = urllib.request.Request(url,headers=headers)
    res = urllib.request.urlopen(req)
    html = res.read().decode('utf-8')
    # print(html)
    # 写入文件
    filename = '第'+ str(i) + '页.html'
    with open(filename,'w',encoding='utf-8') as f:
        # print('正在爬取第%d页'%i)
        f.write(html)

总结

  1. 测试流程
  2. 观察页面
  3. 总结规律
  4. 编写代码

2.百度贴吧其他实现方式

需求

对百度贴吧案例进行重构

分析

观察代码发现读取页面和写入文件部分是可以复用的,不需要重复性编写细节部分调用一个读取和写入文件的端口即可。
有2种方式,分别是函数和类的方式。

代码

函数

import urllib.request
import urllib.parse

# 读取页面
def readPage(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
    }
    # 发起请求
    req = urllib.request.Request(url,headers=headers)
    res = urllib.request.urlopen(req)
    html = res.read().decode('utf-8')
    return html

# 写入文件
def writePage(filename,html):
    with open(filename, 'w', encoding='utf-8') as f:
        f.write(html)
        print('写入成功')

# 主函数
def main():
    name = input('请输入贴吧的名字:')
    begin = int(input('请输入起始页:'))
    end = int(input('请输入结束页:'))
    kw = {'kw': name}
    kw = urllib.parse.urlencode(kw)
    for i in range(begin, end + 1):
        pn = (i - 1) * 50
        baseurl = 'https://tieba.baidu.com/f?'
        url = baseurl + kw + '&pn=' + str(pn)
        # 调用函数
        html = readPage(url)
        filename = '第' + str(i) + '页.html'
        writePage(filename,html)

if __name__ == '__main__':
    main()

import urllib.request
import urllib.parse

class BaiduSpider():
    # 把常用的不变的放到init方法里面
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
        }
        self.baseurl = 'https://tieba.baidu.com/f?'

    def readPage(self,url):
        req = urllib.request.Request(url, headers=self.headers)
        res = urllib.request.urlopen(req)
        html = res.read().decode('utf-8')
        return html

    def writePage(self,filename,html):
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(html)
            print('写入成功')

    def main(self):
        name = input('请输入贴吧的名字:')
        begin = int(input('请输入起始页:'))
        end = int(input('请输入结束页:'))
        kw = {'kw': name}
        kw = urllib.parse.urlencode(kw)

        for i in range(begin, end + 1):
            pn = (i - 1) * 50
            # baseurl = 'https://tieba.baidu.com/f?'
            url = self.baseurl + kw + '&pn=' + str(pn)
            # 调用函数
            html = self.readPage(url)
            filename = '第' + str(i) + '页.html'
            self.writePage(filename, html)


if __name__ == '__main__':

    # 我们要调用main()方法 就需要实例化类
    spider = BaiduSpider()
    spider.main()

3.post请求实现有道翻译

需求

本地输入单词获取有道翻译

前提知识

数据提取

从相应url等获取我们想要的数据的过程

数据分类

  • 非结构化数据:HTML
    • 正则表达式、xpath
  • 结构化数据:json、xml
    • 处理方法:转化为python数据类型

数据提取之json

使用json库可以轻松将json数据转化为python内建数据类型。

JSON是一种轻量级的数据交换格式,方便程序员阅读和编写同时也方便机器的解析和生成。适用于数据交互,eg:网站前台和后台的数据交互。

JSON中的字符串都是双引号,eg:{"type":"EN2ZH_CN","errorCode":0,"elapsedTime":1,"translateResult":[[{"src":"nih","tgt":"国家卫生研究院"}]]}

JSON —json.loads()–> python
字符串 <–json.dumps()— 数据类型

包含JSON —json.load()—> python
类文件对象 <–json.dump()---- 数据类型

分析

POST请求需要获取Form Data。

获取Form Data

点击有道翻译,右键检查,找到下列图片,看到是POST请求,有Form Data。

image-20201208213016973

image-20201208211518981

image-20201208211728204

获取User-Agent

User-Agent的参数一般是用于模拟浏览器,欺骗服务器,获取和浏览器一致的内容。

image-20201208214012273

转换数据类型

有了Form Data和headers就可以发起请求,获取数据,当打印获取的内容却发现不是我们想要的结果,为什么会这样?打印一下html的类型
<class 'str'> {"type":"EN2ZH_CN","errorCode":0,"elapsedTime":1,"translateResult":[[{"src":"nih","tgt":"国家卫生研究院"}]]}

这是json类型的字符串,是不是有点眼熟,像python中的字典,使用json把json类型的字符串转换成Python数据类型的字典,就可以使用字典得到我们想要的’国家卫生研究院’.

步骤

  1. 获取Form Data和headers
  2. 请求url
  3. 转换数据类型
  4. 输出结果

代码

import urllib.request
import urllib.parse
import json

# 请输入你要翻译的内容
key = input('请输入你要翻译的内容:')

# 拿到form表单的数据
data = {
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

data = urllib.parse.urlencode(data)

data = bytes(data,'utf-8')

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

headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
    }

req = urllib.request.Request(url,data=data,headers=headers)
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
# print(type(html),html)
# print(html)
'''
 {"type":"ZH_CN2EN","errorCode":0,"elapsedTime":1,"translateResult":[[{"src":"你好","tgt":"hello"}]]}
'''
# 把json类型的字符串转换成Python数据类型的字典
r_dict = json.loads(html)

# print(type(r_dict),r_dict)
# [[{"src":"你好","tgt":"hello"}]]
# [{"src":"你好","tgt":"hello"}]
# {"src":"你好","tgt":"hello"}
# 'hello'
r = r_dict['translateResult'][0][0]['tgt']
print(r)

总结

  1. POST请求找Form Data
  2. 尽量找到返回json数据的URL

二、requests练习

1.requests实现有道翻译

需求

requests实现有道翻译

分析

  1. post请求查找form data
  2. 使用User-Agent
  3. 解码

步骤

  1. 搭建主框架
  2. 分别获取data,url和headers
  3. 请求url,打印数据

代码

import requests
import json

key = input('请输入您要翻译的内容:')

data = {
    'i': key,
    'from': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15880623642174',
    'sign': 'c6c2e897040e6cbde00cd04589e71d4e',
    'ts': '1588062364217',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom':'fanyi.web',
    'action': 'FY_BY_CLICKBUTTION'
}

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

headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
    }

res = requests.post(url,data=data,headers=headers)
res.encoding = 'utf-8'
html = res.text

print(html)

总结

代码框架

import requests
import json
url = ''
data = ''
headers = {'User-Agent':''}
res = requests.post(url,data=data,headers=headers)
res.encoding = 'utf-8'
html = res.text
#print(html)

2.处理不信任证书的网站

需求

什么是SSL证书?
SSL证书是数字证书的⼀种,类似于驾驶证、护照和营业执照的电子副本。
因为配置在服务器上,也称为SSL服务器证书。SSL 证书就是遵守 SSL协
议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务
器身份验证和数据传输加密功能
测试网站 https://inv-veri.chinatax.gov.cn/

分析

因为需要对网站的SSL证书进行验证,所以verify这个参数默认值为true,所以在处理不信任证书的网站,将这个参数=false即可。

代码

import requests
url = 'https://inv-veri.chinatax.gov.cn/'
res = requests.get(url,verify=False)
print(res.text)

总结

verify=False

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值