文章目录
1. 写一个爬帖子的项目
我们先打开百度贴吧输入“海贼王”,然后随便打开两页,复制一下url,研究一下规律。
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
以上是我点开的第二页和第三页的url,经过观察我们可以看到这样的规律
https://tieba.baidu.com/f? # 基本的url
kw=%E6%B5%B7%E8%B4%BC%E7%8E%8B # 这个应该是我们输入的关键字的16进制编码
&ie=utf-8 # 这个是译码的
&pn=50 # 这个应该是页码有关的数字
# 我们看到页码的规律是(页数-1)×50
我们可以构建要抓取页的url了,下面是面向过程的代码:
# 百度贴吧项目
'''
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
'''
import urllib.request
import urllib.parse
base_url = 'https://tieba.baidu.com/f?'
start_page = int(input('请输入起始页:'))
end_page = int(input('请输入结束页:'))
key = input('请输入你要搜索的主题:')
kw = {'kw':key}
kw = urllib.parse.urlencode(kw)
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36'}
for i in range(start_page,end_page+1): # 因为range()函数的特点是左含右不含,所以要加上1才能够输出结束页
pn = (i-1)*50
url = base_url+kw+'&ie=utf-8'+'&pn='+str(pn) # 这里要转换成字符串才能拼接
req = urllib.request.Request(url,headers=headers)
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
with open(r'D:\spiderdocuments\tieba_{}_page_{}.txt'.format(key,i),'w',encoding='utf-8') as f:
f.write(html)
print(f'第{i}页已经成功写入!')
print('程序执行完毕')
在我输入相关的信息后,这个执行结果就是在我的相应盘里多出来这么几个文件
2. 面向对象编程
我们可以将上述代码用面向对象编程的思想来尝试编写
2.1 使用函数对象编程
我大概把面向过程编程的内容分成以下几个步骤:
- 抓取网页 生成要写入文本的内容
- 写入文本
- 主程序 生成抓取网页需要的url
- 主入口判断语句
所以我大概可以先写这样一个框架
import urllib.request
import urllib.parse
def readpage(url):
pass
def writepage(filename,html)
pass
def main():
pass
if __name__ == '__main__':
main()
下面我们把必要的内容移入各自的函数,得到如下结果:
# 面向对象,函数
import urllib.request
import urllib.parse
def readpage(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36'}
req = urllib.request.Request(url, headers=headers)
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
return html
def getpage(filename, html):
with open(filename, 'w', encoding='utf-8') as f:
f.write(html)
print('写入成功')
def main():
base_url = 'https://tieba.baidu.com/f?'
key = input('请输入你要搜索的内容:')
start_page = int(input('请输入起始页:'))
end_page = int(input('请输入结束页:'))
kw = {'kw': key}
kw = urllib.parse.urlencode(kw)
for i in range(start_page, end_page + 1):
pn = (i - 1) * 50
url = base_url + kw + '&ie=utf-8' + str(pn)
html = readpage(url)
filename = r'D:\spiderdocuments\爬虫结果第{}页.txt'.format(i)
getpage(filename, html)
if __name__ == '__main__':
main()
当输入相关的数据后,执行结果是在我相应的文件夹里出现一些新的文件:
2.2 使用类对象编程
代码如下,慢慢琢磨:
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/87.0.4280.88 Safari/537.36'
}
self.base_url = '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}
result = urllib.parse.urlencode(kw)
for i in range(begin, end + 1):
pn = (i - 1) * 50
url = self.base_url + result + '&pn=' + str(pn)
# 调用函数
html = self.readPage(url)
filename = '第' + str(i) + '页.html'
self.writePage(filename, html)
if __name__ == '__main__':
spider = BaiduSpider()
spider.main()
这个和使用函数不同的是:
- 定义了初始化方法,把headers,base_url放进去。
- 引用headers和base_url的时候用self.headers和self.base_url
- 在主函数中调用类中的方法的时候也是用self.readpage(url)和self.getpage(filename,html)
这些都遵循了类的属性和方法的调用规则,其他的基本没有什么改变。执行的时候页右主入口判断语句,不过后面跟的是实例化类,和用实例调用主函数。
3. post案例:有道翻译项目
下面我们尝试写一个爬取有道翻译的项目,目标是实现输入中文或者英文,翻译成英文或中文并输出。
方法步骤:
- 请求数据 请求的url地址需要携带数据
- Request URL:http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
- Request Method:POST
- User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/49.0.2623.75 Safari/537.36X-Requested-With:XMLHttpRequest
- 需要的form data
i:ni'hao
from:AUTO
to:AUTO
smartresult:dict
client:fanyideskweb
salt:16080913521534
sign:77ea47df15df6aab9c8795ae97b3738c
lts:1608091352153
bv:03c7fe57b6c3c6df93436a3d08a92a66
doctype:json
version:2.1
keyfrom:fanyi.web
action:FY_BY_REALTlME
- 解析数据 得到翻译的结果
以上是我们的思路。
下面是我们的代码,请仔细看注释:
# 有道翻译
import urllib.request # 先引用必要的模块
import urllib.parse
content = input('请输入你要查找的内容:') # 接收所要查询的内容
# 这个数据表格是我们在网页内得到的
data = {
'i': content,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '16080848522314',
'sign': '4411bb288b085cd52841d65ddde0d8f8',
'lts': '1608084852231',
'bv': '03c7fe57b6c3c6df93436a3d08a92a66',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'
}
'''
TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
'''
data = urllib.parse.urlencode(data) # 要把data进行编译一下
data = bytes(data,encoding='utf-8') # 而且要把data转换成字节类型,并且要编译,不然会报错如上面注释。
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
# http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
# 在这里我们要删掉_o,不然的话会报错:{"errorCode":50},我们暂时这样处理,就不会报错了。以后学了js逆向后再解释。
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36X-Requested-With:XMLHttpRequest'} # 用soft wrap功能可以换行
# 以下代码是请求以及获取数据:
req = urllib.request.Request(url,data=data,headers=headers) # 将url,data,headers都当成参数传入
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
print(html)
当我执行以后,在提示中输入:你好。结果如下:
请输入你要查找的内容:你好
{"type":"ZH_CN2EN","errorCode":0,"elapsedTime":0,"translateResult":[[{"src":"你好","tgt":"hello"}]]}
我们看到得到的好像是字典,也许你会用字典的知识取出所要的数据。但是,这里注意,其实输出的是字符串,不信我们检查一下:
print(type(html))
结果
请输入你要查找的内容:nihao
<class 'str'>
所以,一定要先转换成字典,这就要用到一个工具——json,功能是把字典类型的字符串转换成字典。
html = res.read().decode('utf-8')
r_dict = json.loads(html) # 把字符串转换成字典
print(type(r_dict))
注意我只写了最后三行代码,前面的省略了,其中要记得先import json不然会提示错误。
执行结果:
请输入你要查找的内容:你好
<class 'dict'>
就是我们熟悉的字典类型了。后面我再用所学的知识提出所需要的内容即可,完整代码如下:
# 有道翻译
import json
import urllib.request # 先引用必要的模块
import urllib.parse
content = input('请输入你要查找的内容:') # 接收所要查询的内容
# 这个数据表格是我们在网页内得到的
data = {
'i': content,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '16080848522314',
'sign': '4411bb288b085cd52841d65ddde0d8f8',
'lts': '1608084852231',
'bv': '03c7fe57b6c3c6df93436a3d08a92a66',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'
}
'''
TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
'''
data = urllib.parse.urlencode(data) # 要把data进行编译一下
data = bytes(data,encoding='utf-8') # 而且要把data转换成字节类型,并且要编译,不然会报错如上面注释。
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
# http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
# 在这里我们要删掉_o,不然的话会报错:{"errorCode":50},我们暂时这样处理,就不会报错了。以后学了js逆向后再解释。
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36X-Requested-With:XMLHttpRequest'} # 用soft wrap功能可以换行
# 以下代码是请求以及获取数据:
req = urllib.request.Request(url,data=data,headers=headers) # 将url,data,headers都当成参数传入
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
r_dict = json.loads(html) # 把字符串转换成字典
# print(r_dict)
'''
{'type': 'ZH_CN2EN', 'errorCode': 0, 'elapsedTime': 0, 'translateResult': [[{'src': '你好', 'tgt': 'hello'}]]}
'''
res_words = r_dict['translateResult'][0][0]['tgt']
print('翻译结果:',res_words)
我在提示中输入“你好”,执行结果是:
请输入你要查找的内容:你好
翻译结果:hello
我在提示中输入“hello”,输出结果是:
请输入你要查找的内容:hello
翻译结果: 你好
3. 第三方模块requests
需要先安装这个模块
3.1 用requests模块爬取某官网数据
下面我用这个模块爬取当当网官网数据,注意看注释:
# requests模块
import requests
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36X-Requested-With:XMLHttpRequest'} # 用soft wrap功能可以换行
# 下面是当当网的官网
url = 'http://book.dangdang.com/?_utm_brand_id=11106&_ddclickunion=460-5-biaoti|ad_type=0|sys_id=1'
response = requests.get(url,headers=headers)
# response.encoding='gbk'
# result = response.text
# print(result)
# 或者用如下方法
result = response.content.decode('gbk')
print(result)
3.2 用requests模块发送post请求
我们还将上面的有道翻译项目再使用requests模块做一遍:
# 用requests模块做有道翻译项目
import json
import requests
content = input('请输入你要查找的内容:') # 接收所要查询的内容
data = {
'i': content,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': '16080848522314',
'sign': '4411bb288b085cd52841d65ddde0d8f8',
'lts': '1608084852231',
'bv': '03c7fe57b6c3c6df93436a3d08a92a66',
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'
}
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36X-Requested-With:XMLHttpRequest'} # 用soft wrap功能可以换行
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
res = requests.post(url,data=data,headers=headers)
html = res.text
r_dict = json.loads(html) # 把字符串转换成字典
res_words = r_dict['translateResult'][0][0]['tgt']
print('翻译结果:',res_words)
我执行代码,并再提示中输入:hello world执行结果为
请输入你要查找的内容:hello world
翻译结果: 你好,世界
我们发现这个模块非常的简便,不需要再那么多的编译和转化了。步骤简单,所以以后推荐使用这个方法。
3.3 requests模块源码查看
可以直接去Github上下载源码:
确实写得很牛。可以学习和借鉴。
本次博文到此结束。谢谢观看!