目录
一、了解 URL
URL(外文名:Uniform Resource Locator,中文名:统一资源定位符),统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理。
基本 URL 为:“协议://授权/路径?查询”。完整的、有授权部分的普通统一资源标志符语法看上去如下:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志
(1)模式/协议(scheme):它告诉浏览器如何处理将要打开的文件。最常用的模式是超文本传输协议(Hypertext Transfer Protocol,缩写为HTTP),这个协议可以用来访问网络。其他协议有:
-
ftp File Transfer protocol(文件传输协议)
-
gopher The Gopher protocol(Gopher协议)
-
mailto Electronic mail address(电子邮件地址)
-
news USENET news(USENET新闻)
-
nntp USENET news using NNTP access(使用NNTP访问的USENET新闻)
-
telnet Reference to interactive sessions(交互式会话访问)
-
wais Wide Area Information Servers(广域信息服务系统)
-
file Host-specific file names(特殊主机文件名)
-
prospero Prospero Directory Service(prospero目录服务)
(2)存放资源的服务器的名称或 IP 地址(有时包含端口号,各种传输协议都有默认的端口号,如 http 的端口号默认为 80)
(3)资源的具体地址,如目录或文件名等
二、了解编码
UTF-8(8-bit Unicode Transformation Format)是一种针对 Unicode 的可变长度字符编码,又称万国码。UTF-8 用 1 到 6 个字节编码 Unicode 字符。其编码中的第一个字节仍与 ASCII 兼容,这使得原来处理 ASCII 字符的软件无须或只须做少部份修改,即可继续使用。用在网页上可以统一页面显示中文简体繁体及其它语言(如英文,日文,韩文)。
UTF-8 的字节顺序在所有系统中都是一样的。UTF-8 是 Linux 的标准编码。
三、urllib
可通过 IDLE 的 Help 选项卡下的 Python Docs 熟悉 urllib 模块
>>> import urllib.request
>>> response = urllib.request.urlopen('http://www.fishC.com')
>>> html = response.read()
# 此处打印的页面呈现为二进制的数据
>>> print(html)
# 解码操作,采用 decode() 将之变为 Unicode 形式
>>> html = html.decode('utf-8')
# 打印结果和网页控制台为相同形式
>>> print(html)
练习:采用 urllib.resquest 爬取图片
# 从指定网站下载一张 200 * 300 大小的图片
# 图片保存于下列代码存放的目录下
>>> import urllib.request
>>> response = urllib.request.urlopen("http://placekitten.com/g/200/300")
>>> cat_img = response.read()
>>> with open("cat_200_300.jpg", "wb") as f:
f.write(cat_img)
注:urlopen 接收的可能是 字符串 也可能是 Request 对象
# 若传入的为字符串,则 Python 默认将该字符串转换为 Request 对象,再传递给 Request 对象
>>> req = urllib.request.Request("http://placekitten.com/g/200/300")
>>> response = urllib.request.urlopen(req)
urlopen 返回一个 类文件对象,可用 read() 方法读取内容
还有三个常用方法:
(1)geturl(): 返回请求的 url ,即地址、链接
(2)info(): 返回一个 httplib.HTTPMessage 对象,包含远程服务器返回的头信息
(3)getcode(): 返回 HTTP 状态码,200 表示正常响应
四、谷歌浏览器网页控制台
通过鼠标右键-检查,或 F12 可调用谷歌浏览器的控制台
常用选项卡为 Elements 和 Network 。可通过选择 Network 选项卡下请求方法为 POST 形式的 Name,查看其 Headers 和 Payload。
(1)Headers - General 部分:Request URL 为 urlopen 请求的链接,Request Method 为 请求方法,Remote Address 为 IP地址和端口号。
(2)Headers - Request Headers 部分:用于服务器判断客户端是否为非人为操控,通过 User-Agent 判断是浏览器访问还是代码访问,但其可被简单的自定义
(3)Payload - From Data 部分:显示页面主要提交信息

注: urlopen( data = None ) 中,data 被赋值则以 POST 的形式提交,未赋值采用 GET 形式
练习:调用翻译页面进行翻译
>>> import urllib.request
>>> import urllib.parse
>>> url = 'https://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
>>> data = {}
>>> data['i'] = 'love'
>>> data['from'] = 'AUTO'
>>> data['to'] = 'AUTO'
>>> data['smartresult'] = 'dict'
>>> data['client'] = 'fanyideskweb'
>>> data['salt'] = '16507068348049'
>>> data['sign'] = '4696ce447b11645e9fb66b819bd4c1b4'
>>> data['lts'] = '1650706834804'
>>> data['bv'] = '803d4a8f2036921cf486753934c3ae8a'
>>> data['doctype'] = 'json'
>>> data['version'] = '2.1'
>>> data['keyfrom'] = 'fanyi.web'
>>> data['action'] = 'FY_BY_REALTlME'
# 采用 urllib.parse 进行解析
# 采用 urllib.parse.urlencode() 对 data 进行编码成 url 形式
# 采用 encode 将 data 编码从 Unicode 的文件格式转化成 utf-8 的编码形式,(Python 默认为 Unicode 形式,utf-8 是 Unicode 的一种默认编码形式)
>>> data = urllib.parse.urlencode(data).encode('utf-8')
>>> response = urllib.request.urlopen(url, data)
# Windows 系统可不用 decode(),但其它系统需要采用 decode()
# decode() 是将其他编码形式转化成 Unicode 的形式
# response.read() 得到的是 utf-8 编码形式的文件
>>> html = response.read().decode('utf-8')
>>> print(html)
{"type":"EN2ZH_CN","errorCode":0,"elapsedTime":1,"translateResult":[[{"src":"love","tgt":"爱"}]]}
进一步修改代码, 人性化显示翻译结果
>>> import urllib.request
>>> import urllib.parse
>>> import json
>>> content = input("请输入需要翻译的内容:")
>>> url = 'https://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
# json 为轻量级的数据交换格式,即以字符串的形式将 Python 的数据结构封装起来
>>> data = {'i': content, 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'salt': '16507068348049', 'sign': '4696ce447b11645e9fb66b819bd4c1b4', 'lts': '1650706834804', 'bv': '803d4a8f2036921cf486753934c3ae8a', 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web', 'action': 'FY_BY_REALTlME'}
>>> data = urllib.parse.urlencode(data).encode('utf-8')
>>> response = urllib.request.urlopen(url, data)
>>> html = response.read().decode('utf-8')
# json.loads() 用于将 str 类型的数据转成dict
>>> target = json.loads(html)
>>> print("翻译结果为:%s" % (target["translateResult"][0][0]['tgt']))
请输入需要翻译的内容:想去海边
翻译结果为:Want to go to the seaside
当用户短时间内多次访问页面可能会受到限制,可做隐藏操作,分两种方法
(1)采用时间间隔(效率较低)
>>> import urllib.request
>>> import urllib.parse
>>> import json
>>> import time
>>> while True:
... content = input("请输入需要翻译的内容(输入“!!!”则退出程序):")
... if content == '!!!':
... print("退出程序!")
... break
... url = 'https://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
# 方法B:步骤一:在此处添加代码:
# head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36 '}
... data = {'i': content, 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb',
'salt': '16507068348049', 'sign': '4696ce447b11645e9fb66b819bd4c1b4', 'lts': '1650706834804',
'bv': '803d4a8f2036921cf486753934c3ae8a', 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'}
... data = urllib.parse.urlencode(data).encode('utf-8')
# 方法B:步骤二:修改该行代码为:
# req = urllib.request.Request(url, data, head)
... req = urllib.request.Request(url, data)
# 当不采用 req.add_header() 方法添加头参数时,可将改行删除,采用 方法B
... req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36 ')
... response = urllib.request.urlopen(req)
... html = response.read().decode('utf-8')
... target = json.loads(html)
... print("翻译结果为:%s" % (target["translateResult"][0][0]['tgt']))
# 间隔 5 秒钟,进行下一次操作
... time.sleep(5)
请输入需要翻译的内容(输入“!!!”则退出程序):打呼噜
翻译结果为:snore
请输入需要翻译的内容(输入“!!!”则退出程序):!!!
退出程序!
(2)利用代理
正向代理: 原本A访问B,B知道是A访问的,但是在中间加一个代理服务器C后,A 通过代理服务器C去访问B,则B看到的是C访问的,而非A去访问的B,这样就增加了A匿名。
反向代理:A向代理服务器C发起请求,代理服务器C将请求转发给B,B将消息回复给C后,C转发给A,A看到的是C接收和响应请求,却不知道B的存在,C相对与B来说就是反向代理,B增加了匿名。
在访问过程中,通过判断客户端与服务端谁具有匿名效果来判断属于正/反向代理
————————————————
版权声明:本文为CSDN博主「我想学渗透」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_32766863/article/details/123613939
五、Requests 和 BeautifulSoup4
# 爬取豆瓣电影榜单
# 控制台源码

练习:利用 Requests 和 BS4 爬取榜单上的电影名
>>> import requests
>>> from bs4 import BeautifulSoup
>>> url = "https://movie.douban.com/top250"
# 此处需要加反爬,设置 headers 中的 User-Agent
>>> res = requests.get(url=url, headers={'User-Agent': 'Mozilla/5.0'})
>>> print(res.text)
# 这里的html.parser,是四种解析器中的一种,也是经常使的。得到的soup就是HTML。所以后面我们可以直接>>> 使用soup找到我们需要的属性。
>>> soup = BeautifulSoup(res.text, "html.parser")
# 在BS4中规定,如果遇到要查询class情况,需要使用class_来代替
# 采用 find_all() 方法查找 <div> 标签下所有名称为 "hd" 的 class
>>> targets = soup.find_all("div", class_="hd")
>>> for each in targets:
... print(each.a.span.text)
# 部分结果为:
<!-- dae-web-movie--default-77797d8f94-fn5fc-->
<script>_SPLITTEST=''</script>
</body>
</html>
肖申克的救赎
霸王别姬
阿甘正传
泰坦尼克号
这个杀手不太冷
美丽人生
千与千寻
辛德勒的名单
盗梦空间
忠犬八公的故事
星际穿越
楚门的世界
海上钢琴师
三傻大闹宝莱坞
机器人总动员
放牛班的春天
无间道
疯狂动物城
大话西游之大圣娶亲
熔炉
教父
控方证人
当幸福来敲门
触不可及
怦然心动
find_all() 的用法:
1. soup.find_all(id='tag id') 通过 id 进行查找
2. soup.find_all(text='text') 通过文本进行查找
3. soup.find_all('tag') 通过标签进行查找
4. soup.find_all(text=re.compile('your re')), soup.find_all(id=re.compile('your re')) 采用正则表达式进行查找
5. soup.find_all('tag', {'id': 'tag id', 'class': 'tag class'}) 采用指定属性进行查找
对代码进一步修改
>>> import requests
>>> from bs4 import BeautifulSoup
>>> def open_url(url):
# 此处可使用代理
# 例如:proxies = {‘http’: '','http': ''}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/100.0.4896.88 Safari/537.36"}
# 若使用代理则采用该代码
# res = requests.get(url, headers=headers, proxies=proxies)
res = requests.get(url, headers=headers)
return res
# 找出榜单一共多少页
>>> def find_depth(res):
soup = BeautifulSoup(res.text, "html.parser")
# previous_sibling 找向前最近的一个兄弟节点
depth = soup.find("span", class_="next").previous_sibling.previous_sibling.text
return int(depth)
# 收集具体的电影数据
>>> def find_movies(res):
soup = BeautifulSoup(res.text, "html.parser")
# 电影名
movies = []
targets = soup.find_all("div", class_="hd")
for each in targets:
movies.append(each.a.span.text)
# 评分
ranks = []
targets = soup.find_all("span", class_="rating_num")
for each in targets:
ranks.append("评分:%s" % each.text)
# 详细资料
messages = []
targets = soup.find_all("div", class_="bd")
for each in targets:
try:
messages.append(each.p.text.split('\n')[1].strip() + each.p.text.split('\n')[2].strip())
except:
continue
result = []
length = len(movies)
for i in range(length):
result.append(movies[i] + '\n'+ ranks[i] + '\n' + messages[i] + '\n\n')
return result
>>> def main():
host = "https://movie.douban.com/top250"
res = open_url(host)
depth = find_depth(res)
result = []
for i in range(depth):
url = host + "?start=" + str(25*i) + "&filter="
# 翻页后需打开更新后的链接,获取资源
res = open_url(url)
result.extend(find_movies(res))
# 创建名为 豆瓣电影TOP250.txt 的文本文件
with open("豆瓣电影TOP250.txt", "w", encoding="utf-8") as f:
for each in result:
f.write(each)
>>> if __name__ == "__main__":
main()

3738

被折叠的 条评论
为什么被折叠?



