Ajax(Asynchronous JavaScript and XML)异步的JS和XML。原理是: 利用JS在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。
拖动刷新的内容由Ajax加载且页面的URL无变化,那么可以去哪里查看这些Ajax请求?
(1)开发者工具(F12)->Network选项卡, 获取页面加载过程中Browser与Server之间请求和响应。
(2)筛选出所有的Ajax请求。在请求的上方有一层筛选栏,直接点击XHR(Ajax特殊的响应类型)
(3)模拟Ajax请求,提取我们所需要的信息。
打开Ajax的XHR过滤器,然后一直滑动页面以加载新的微博内容。可以看到,会不断有Ajax请求发出。请求的参数有4个:type、value、containerid和page。
import json
import requests
from colorama import Fore
from requests import HTTPError
from fake_useragent import UserAgent
import os
def download_page(url, params=None):
""" 根据url地址下载html页面"""
try:
ua = UserAgent()
headers = {
'User-Agent': ua.random,
}
# 请求https协议时报错SSLError 解决:verify = False 不验证证书
response = requests.get(url, params=params, headers = headers, verify = False)
except HTTPError as e:
print(Fore.RED + '[-] 爬取网站失败:%s' %(url, e.reason) )
return None
else:
"""
html = response.text 是字符串
json.loads(html) 将字符串反序列化成python数据类型
"""
# response.json()方法会自动将字符串反序列化为pyth数据类型
# return response.json() #
return response
def parse_html(html):
""" 参考源代码, 进行解析
{'ok': 0, 'msg': '这里还没有内容', 'data': {'cards': []}}
"""
cards = html.get('data').get('cards')
count = 0
for card in cards:
try:
count += 1
text = card['mblog'].get('text')
# 对于博客正文的内容进行处理,删除标签,用正则+sub
print('第%s页的微博正文内容:%s' %(count,text))
# 获取微博内容的图片
pics = card['mblog'].get('pics')
if pics:
# 枚举:返回索引和内容
for index , pic in enumerate(pics):
pic_url = pic.get('url')
pic_content = download_page(pic_url).content # 获取二进制bytes类型
# 通过图片网址获取图片名称
img_name = os.path.join('weibo_picture',pic_url.split('/')[-1])
with open(img_name,'wb') as f:
f.write(pic_content)
print('下载第%s张图片成功' %(index+1))
except Exception as e:
print('下载博客失败:%s'%(str(e)))
if __name__ == '__main__':
uid = input('请输入你要爬取的微博博主的uid:')
for page in range(10):
url = 'https://m.weibo.cn/api/container/getIndex?uid=%s&type=uid&containerid=107603%s&page=%s' %(uid,uid,page)
html = download_page(url).json()
# print(html)
# print(type(html)) #
parse_html(html)
JS动态渲染的页面不止Ajax一种,有些网站,不能直接分析Ajax来抓取(会有一些加密解密算法),难以直接找出其规律
例如:中国青年网:页面由JS生成但不包含Ajax请求
ECharts官网:图形都是经过JS计算之后生成
淘宝网:其Ajax接口含有很多加密参数
那么如何解决这些问题?
Selenium 是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作。同时,还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScript动态渲染的页面来说,此种抓取方式非常有效。
但是它的速度很慢,不推荐使用
在使用时要先声明浏览器对象
Selenium支持很多的浏览器,Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端浏览器。另外,也支持无界面浏览器PhantomJS
通过对象,向浏览器发起请求
from selenium import webdriver
browser = webdriver.Chrome()
browser = webdriver.Firefox()
运行后,弹出Chrome浏览器
注意,需要安装浏览器驱动,火狐、谷歌都行
https://github.com/mozilla/geckodriver/releases
https://npm.taobao.org/mirrors/chromedriver/2.41/
将下载好的chromedriver.exe放入Python安装路径下的Script文件夹内
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
# 1. 通过浏览器驱动打开浏览器
browser = webdriver.Chrome()
#2. 通过浏览器访问网址
browser.get('http://www.baidu.com')
# 2.1 节点查找,根据id=kw查找输入的表框对象
input = browser.find_element_by_id('kw')
# 写入信息
input.send_keys('python')
# 写入回车
input.send_keys(Keys.ENTER)
# 休眠10秒关闭
time.sleep(10)
# 3.关闭浏览器
browser.close()
运行可以发现自动打开了百度网页并搜索‘python’