动态网页抓取
动态网页通过AJAX技术对网页进行异步更新。抓取动态网页中动态加载的内容方法有两种:
1、通过浏览器审查元素解析地址。
使用网页的“检查”功能,在Network左下方的”名称“中找到真正的评论文件“list?callback=jQuery112405799739079336084_1676512332637”即可查看动态加载的评论内容。
代码参考:
import requests
import json
link = """https://api-zero.livere.com/v1/comments/list?callback=jQuery1124042306030021060637_1676357251666&limit=10&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1676357251668"""
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56'}
r = requests.get(link,headers=headers)
json_string = r.text
json_string = json_string[json_string.find('{'):-2] #仅提取字符串中符合json格式的部分
#从第一个左大括号提取,最后的两个字符-括号分号不取
json_data = json.loads(json_string) #把字符串格式的响应体数据转化为json数据
comment_list = json_data['results']['parents']
for eachone in comment_list:
message = eachone['content']
print(message)
2、通过Selenium模拟浏览器抓取
以火狐浏览器为例。
仍然使用检查功能定位到要查找的元素,用CSS选择器查找元素最后输出。
Selenium选择元素的方法有很多,具体如下:
# 利用CSS选择器查找
inputTag = driver.find_element(By.CSS_SELETOR, "value")
# 利用ID查找
inputTag = driver.find_element(By.ID, "value")
# 利用类名查找
inputTag = driver.find_element(By.CLASS_NAME, "value")
# 利用name属性查找
inputTag = driver.find_element(By.NAME, "value")
# 利用标签名查找
inputTag = driver.find_element(By.TAG_NAME, "value")
# 利用xpath查找
inputTag = driver.find_element(By.XPATH, "value")
另外Selenium还可以使用Click单击元素,send_keys模拟按键输入,Clear清除元素内容,Submit提交表单等。
最后给出一个例子实现具体的操作:
from selenium import webdriver
import time
driver = webdriver.Firefox(executable_path = r'C:\Users\Administrator\Desktop\geckodriver.exe')
driver.implicitly_wait(20) # 隐性等待,最长等20秒
#把上述地址改成你电脑中geckodriver.exe程序的地址
driver.get("http://www.santostang.com/2018/07/04/hello-world/")
time.sleep(5)
for i in range(0,3):
# 下滑到页面底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") #执行该语句让浏览器加载出button的html
# 转换iframe,再找到查看更多,点击
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR,"iframe[title='라이브리 - 댓글영역']")) #解析iframe
#load_more = driver.find_element(By.CSS_SELECTOR,“button[data-page='%d‘]“%(i,)) #找到元素
load_more = driver.find_element(By.CSS_SELECTOR,'button[data-page=\'%d\']'%(i+1,)) #应该是正则定位
load_more.click() #模拟点击并加载,就会加载多10个评论
# 把iframe又转回去,因为解析iframe后,下哈的代码就用不了了,所以又要转回未解析的iframe
driver.switch_to.default_content()
time.sleep(5) #等待两秒加载评论
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR,"iframe[title='라이브리 - 댓글영역']"))
comments = driver.find_elements(By.CSS_SELECTOR,'div.reply-content')
for eachcomment in comments:
content = eachcomment.find_element(By.TAG_NAME,'p')
print (content.text)
driver.switch_to.default_content() #执行页面滑动的脚本需要将driver转换到正常模式
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(4)
3、Selenium高级操作
使用Selenium模拟浏览器的加载往往速度会较慢,因此Selenium还可通过以下方法来加快爬取速度。
(1)控制CSS的加载
通过控制网页的外观和元素放置位置来减少页面抓取时间,代码如下:
# 控制 css
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference("permissions.default.stylesheet",2)
driver = webdriver.Firefox(firefox_profile=fp, executable_path = r'C:\Users\Administrator\Desktop\geckodriver.exe')
#把上述地址改成你电脑中geckodriver.exe程序的地址
driver.get("http://www.santostang.com/2018/07/04/hello-world/")
(2)控制图片文件的显示
当不需要抓取网页中的图片时,可以控制图片不显示来加快速度。代码如下:
# 限制图片的加载
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference("permissions.default.image",2)
driver = webdriver.Firefox(firefox_profile=fp, executable_path = r'C:\Users\Administrator\Desktop\geckodriver.exe')
#把上述地址改成你电脑中geckodriver.exe程序的地址
driver.get("http://www.santostang.com/2018/07/04/hello-world/")
(3)控制JavaScript的运行
如果不需要网页动态加载部分的内容,可禁止JavaScript的运行来停止网页的异步更新。代码如下:
# 限制 JavaScript 的执行
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference("javascript.enabled", False)
driver = webdriver.Firefox(firefox_profile=fp, executable_path = r'C:\Users\Administrator\Desktop\geckodriver.exe')
#把上述地址改成你电脑中geckodriver.exe程序的地址
driver.get("http://www.santostang.com/2018/07/04/hello-world/")