动态网页抓取(动态网页抓取文章目录(1)(图) )
优采云 发布时间: 2022-02-21 09:08动态网页抓取(动态网页抓取文章目录(1)(图)
)
动态网页抓取
文章目录
前言
静态网页在浏览器中显示的内容在 HTML 源代码中。
但是由于主流的网站都使用JavaScript来展示网页内容,不像静态网页,在使用JavaScript的时候,很多内容不会出现在HTML源代码中,所以爬取静态网页的技术可能不会工作正常使用。
因此,我们需要使用两种动态网页抓取技术:通过浏览器检查元素解析真实网址和使用 selenium 模拟浏览器。
1 动态爬取示例
通过在后台与服务器交换少量数据,可以异步更新网页。
这意味着可以在不重新加载整个页面的情况下更新页面的某些部分。
一方面减少了网页重复内容的下载,另一方面节省了流量,
与使用 AJAX 网页相比,如果传统网页需要更新内容,则必须重新加载整个网页。因此,AJAX 使 Internet 应用程序更小、更快、更友好。但是AJAX网页的爬取过程比较麻烦。
动态网页示例:
网页下方的评论是用 JavaScript 加载的,这些评论数据不会出现在网页的源代码中。
2 解析真实地址抓取
虽然数据并没有出现在网页的源代码中,但是我们仍然可以找到数据的真实地址,并且请求这个真实地址也可以得到想要的数据。此处使用浏览器的“检查”功能。
点击“Network”,刷新,点击左侧list?callback开头的链接,真实链接如下:
%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=59
点击 JS - preview 可以找到这些评论的内容。
import requests
link = '''https://api-zero.livere.com/v1/comments/list?callback=jQuery112409913001985965064_1613139610757&limit=10
&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1613139610759'''
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63'}
r = requests.get(link, headers=headers)
print('页响应状态码:', r.status_code)
print(r.text)
3 通过 Selenium 模拟浏览器抓取
使用浏览器渲染引擎:直接使用浏览器加载和卸载HTML,应用CSS样式,显示网页时执行Javascript语句
自动打开浏览器加载网页,独立浏览每个网页,顺便抓取数据。
Selenium 测试直接在浏览器中运行,浏览器根据脚本代码自动点击、进入、打开、验证,就像真正的用户在操作一样。
3.1 Selenium安装及基本介绍
点安装硒
3.2个Selenium的实际案例
from selenium import webdriver
import time
# 下载的geckodriver的存储位置
driver = webdriver.Firefox(executable_path=r'F:\Programming\python_bag\geckodriver.exe')
# 隐性等待,最长等20秒
driver.implicitly_wait(20)
# 自动访问的网站
driver.get('http://www.santostang.com/2018/07/04/hello-world')
time.sleep(5)
# 先把所有的评论加载出来
for i in range(0, 5):
# 下滑到页面底部
driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
# 解析iframe框架里面的评论, 注意外边是双引号,里边是单引号
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere-comment']"))
# 找到更多/下一页所在的点击位置
# load_more = driver.find_element_by_css_selector('button.more-btn')
page_next = driver.find_element_by_css_selector('button.page-btn')
# page_next = driver.find_element_by_css_selector('span.z-next')
# 点击“更多”
# load_more.click()
page_next.click()
# 把frame转回去:因为解析frame后,下滑的代码就用不了了,所以又要用下面的代码转回本来未解析的iframe
driver.switch_to.default_content()
time.sleep(2) # 等待2秒,加载评论
driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere-comment']"))
# driver.find_elements_by_css_selector是用CSS选择器查找元素,找到class为’ reply-content '的div元素,注意为elements
comments = driver.find_elements_by_css_selector('div.reply-content')
for each_comment in comments:
# find_element_by_tag_name则是通过元素的tag去寻找,找到comment中的p元素
content = each_comment.find_element_by_tag_name('p')
# 输出p元素中的text文本
print(content.text)
3.3 Selenium 获取 文章 的所有评论
# 自动登录程序
from selenium import webdriver
import time
driver = webdriver.Firefox(executable_path=r'F:\Programming\python_bag\geckodriver.exe')
user = driver.find_element_by_name('username') # 找到用户名输入框
user.clear() # 清除用户名输入框
user.send_keys('1234567') # 在框中输入用户名
pwd = driver.find_element_by_name('password') # 找到密码输入框
pwd.clear() # 清除密码输入框的内容
pwd.send_keys('*******') # 在框中输入密码
driver.find_element_by_id('loginBtn').click() # 单击登录
Selenium 还可以实现简单的鼠标操作,复杂的双击、拖放,获取网页中每个元素的大小,模拟键盘的操作。欲了解更多信息,请参阅
Selenium 官方 网站
3.4 Selenium 的高级操作
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference('permission.default.stylesheet', 2) # stylesheet | 设定不加载css,则参数为2
# firefox_profile=fp控制不加载CSS
driver = webdriver.Firefox(firefox_profile=fp, executable_path=r'F:\Programming\python_bag\geckodriver.exe')
driver.get('http://www.santostang.com/2018/07/04/hello-world/')
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference('permission.default.image', 2) # image | 设定不加载css,则参数为2
# firefox_profile=fp控制不加载CSS
driver = webdriver.Firefox(firefox_profile=fp, executable_path=r'F:\Programming\python_bag\geckodriver.exe')
driver.get('http://www.santostang.com/2018/07/04/hello-world/')
from selenium import webdriver
fp = webdriver.FirefoxProfile()
fp.set_preference('javascript.enabled', False) # image | 设定不加载css,则参数为2
# firefox_profile=fp控制不加载CSS
driver = webdriver.Firefox(firefox_profile=fp, executable_path=r'F:\Programming\python_bag\geckodriver.exe')
driver.get('http://www.santostang.com/2018/07/04/hello-world/')
4 Selenium爬虫实践:深圳短租数据
获取Airbnb深圳前5名的短租房源:名称、价格、评论数、房型、床位数、房客数
网站:爱彼迎深圳
4.1 网站分析
一个房子所有数据的地址是:div._gigle7
价格数据:div._lyarz4r
评论数:span._lcy09umr
房屋名称数据:div._l90019zr
房间类型:小._f7heglr
房间/床位数:span._l4ksqu3j
4.2 项目实践
from selenium import webdriver
import time
driver = webdriver.Firefox(executable_path=r'F:\Programming\python_bag\geckodriver.exe')
for i in range(0, 5):
link = 'http://zh.airbnb.com/s/Shenzhen--China/homes?itmes_offset=' + str(i*18)
# 在虚拟浏览器中打开Airbnb页面
driver.get(link)
# 找到页面中所有的出租房
rent_list = driver.find_elements_by_css_selector('div._gigle7')
# 对于每个出租房
for each_house in rent_list:
# 找到评论数量
try:
comment = each_house.find_element_by_css_selector('span._lcy09umr').text
# except:
finally:
comment = 0
# 找到价格 | 替换掉所有无用字符,只保留价格符号和数字
price = each_house.find_element_by_css_selector('div._lyarz4r').text.replace('每晚', '').replace('价格', '').replace('\n', '')
# 找到名称
name = each_house.find_element_by_css_selector('div._l90019zr').text
# 找到房屋类型、大小
details = each_house.find_element_by_css_selector('small._f7heglr').text
house_type = details.split(' . ')[0] # split将字符串变成列表
bed_number = details.split(' . ')[1]
print('price\t', 'name\t', 'house_type\t', 'bed_number\t', 'comment')
print(price, name, house_type, bed_number, comment)
time.sleep(5)