python中原生的一款基于网络请求的模块,功能非常强大,简单便捷,效率极高。作用:模拟浏览器发请求。
如何使用
-
指定url。
-
UA伪装
-
发起请求。对于在browser中输入url后enter,发起的是get请求,但是requests库可以get/post。
-
获取响应数据。对于browser来说会显示网页
-
持久化存储。存储需要的数据。
requests第一战
import requests
if __name__ == '__main__':
url = 'https://www.sogou.com/' # 指定url
response = requests.get(url=url) # 发起请求;get()发起的是get请求,会返回一个响应对象
page_text = response.text # 获取响应数据,response.text会返回整个html文档
with open('./sougou.html', 'w', encoding='utf-8') as file: # 持久化保存数据,编码得是utf-8不然乱码
file.write(page_text) # 使用with open函数会自动执行关闭文件操作,不需要用户手动执行
print('爬取结束')
UA伪装
UA:User-Agent(请求载体的身份标识)。
UA检测:门户网站的服务器会检测对应请求的载体身份标识。如果梭测请求的载体身份标识为基于某一款浏览器,说明该请求是个正常用户发起的请求。但是如果检测到请求的载体身份标识不是基于某款浏览器的,则就是爬虫,服务器端就很有可能拒绝该次请求。几乎80%网站使用了UA检测作为反爬机制手段之一,所以需要UA伪装作为反反爬手段。
网页采集器实战,融入paras和headers
import requests
if __name__ == '__main__':
url = 'https://www.sogou.com/sogou?query=%E7%8C%AB' # 原url的参数是比较长的,但是只保留query后enter发现也能用。所以在此只保留query
url = 'https://www.sogou.com/sogou?query=猫' # url编码或不编码都行
url = 'https://www.sogou.com/sogou'
# 为了将query的值动态化,故将url携带的参数封装进字典,
query = input('enter a word for query')
params = {
'query': query
}
headers = { # UA伪装
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0'
}
response = requests.get(url, params=params, headers=headers)
page_text = response.text
with open(query + '.html', 'w', encoding='utf-8') as file:
file.write(page_text)
print(query + '.html' + '保存成功!')
百度翻译api实战,判断需要的数据是否来自ajax的url
观察百度翻译https://fanyi.baidu.com/?aldtype=16047#auto/zh,发现这个页面采用了ajax刷新局部数据(具体点指每次输入单词实时显示翻译,而网页未被刷新),可见我们需要爬取并保存的数据是ajax请求的响应,所以我们需要ajax请求的url,而不是百度翻译网页本身的url。在F12里勾选XHR后输入dog,在得到的几条记录里分别查找请求有dog且响应含翻译结果的数据包,最终锁定一个POST请求包。
发现响应数据包是json类型,请求url是https://fanyi.baidu.com/sug,请求携带的参数(data / params)只有kw:"dog":
import requests
import json
if __name__ == '__main__':
url = 'https://fanyi.baidu.com/sug'
data = {
'kw': "dog" # 这里可以动态化,传入input()
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0'
}
response = requests.post(url=url, data=data, headers=headers) # 此data可以理解为get的params
# 刚分析发现response是json,可以直接response.text,得到的是字符串式的json
# 对于响应头指明了Content-Type:application/json,可以response.json(),该方法返回一个字典
dic_obj = response.json()
print(type(dic_obj)) # <class 'dict'>
with open('./百度翻译kw.json', 'w', encoding='utf-8') as file:
# file.write(dic_obj)错的,参数应是str not dict
# file.write(response.text) # 建议拿专门处理json的库处理后存储,不然我这里存储的是中文被unicode编码。
# python自带的json库,json.dump(),onj是被存储的对象,fp是存到哪,拒绝允许中文转成ascii码
json.dump(obj=dic_obj, fp=file, ensure_ascii=False) # 完美。此时保存的数据是中文了。
file.close()
print('over!!!')
豆瓣电影排行榜实战
观察,发现每当鼠标划到底部就会局部刷新新的电影,且网页不刷新(网址url不变),说明也是ajax。
import requests
import json
if __name__ == '__main__':
url = 'https://movie.douban.com/j/chart/top_list'
params = { # 参数最好用params=params来处理,不要携带在url里
'type': '24', # 可以猜到是类型如喜剧 / 恐怖片 / ...
'interval_id': '100:90',
'action': '',
'start': '0', # 可以猜到意思是从哪取,可以利用下
'limit': '20' # 猜到一次取多少个,可以利用下
}
headers = { # UA伪装
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0'
}
response = requests.get(url=url, params=params, headers=headers)
list_json = response.json() # 这次response.json()返回的是list而非dict,因为你观察响应体的原始报文,最外层是[]而非{}
# 如果你不确定response.json()返回dict / list / other,就print(type(response.json()))
file = open('./豆瓣电影排行版.json', 'w', encoding='utf-8')
json.dump(obj=list_json, fp=file, ensure_ascii=False) # obj:Any
print("OVER!!!")
网页的某块内容是否来自ajax
咱就是网页开发岗,咱是知道的,动态的内容一定不是写死在html文件里的,大概率是ajax请求得到的。所以多数情况下静态的组件是写死在html里的,request(网址)得到的只有这些。对于一些好像是静态又好像是动态生成的网页,除了
-
全栈工程师的经验(有概率错)。但这经验不是绝对的,比如B站首页的部分视频栏,当你requests.get(url='https://www.bilibili.com/')会得到有该视频的a链接的源码,即该视频栏并非ajax所得。原理:动态的内容,既可以是数据是在服务器端组成好发回给浏览器,也可以是通过Ajax请求进行发送的
-
笨方法 - 直接requests请求url,保存response.text成HTML文件,打开该文件,静态的组件就会包含在源码中,动态的组件则不包含。
-
对于原本网页中没有的数据,随着向下滚动网页而新出现,且地址栏未变化,一定是请求。
-
最好的方法 - F12,单击左上角小箭头,去在网页中找你需要爬取的element;然后在网页中单击右键,查看网页源代码(网址前缀view-source:),(ctrl+F)查找刚你找到的元素,发现不存在,或者被注释掉了,则证明该元素来自Ajax请求。
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://www.ink0.cn/index.php/2023/03/05/02%e9%80%9a%e7%94%a8%e5%bc%8f%e7%88%ac%e8%99%ab/
共有 0 条评论