02通用式爬虫

AffettoIris 2023-3-5 2,593 3/5

requests库

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('爬取结束')

02通用式爬虫

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请求包。

02通用式爬虫

02通用式爬虫

发现响应数据包是json类型,请求url是https://fanyi.baidu.com/sug,请求携带的参数(data / params)只有kw:"dog":

02通用式爬虫

02通用式爬虫

02通用式爬虫

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。

02通用式爬虫

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文件,打开该文件,静态的组件就会包含在源码中,动态的组件则不包含。

  • 对于原本网页中没有的数据,随着向下滚动网页而新出现,且地址栏未变化,一定是Ajax请求。

  • 最好的方法 - F12,单击左上角小箭头,去在网页中找你需要爬取的element;然后在网页中单击右键,查看网页源代码(网址前缀view-source:),(ctrl+F)查找刚你找到的元素,发现不存在,或者被注释掉了,则证明该元素来自Ajax请求。

- THE END -

AffettoIris

10月16日16:06

最后修改:2023年10月16日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论