python抓取动态网页(Python网络爬虫从入门到实践(第2版)作者博客的HelloWorld文章为例)

优采云 发布时间: 2022-03-17 23:07

  python抓取动态网页(Python网络爬虫从入门到实践(第2版)作者博客的HelloWorld文章为例)

  内容

  1 动态爬取技术介绍

  AJAX(Asynchronous Javascript And XML)的价值在于可以通过在后台与服务器交换少量数据来异步更新网页。这意味着可以在不重新加载整个页面的情况下更新页面的某些部分。一方面减少了网页重复内容的下载,另一方面节省了流量,因此AJAX得到了广泛的应用。

  有两种动态网页抓取方法可以从使用 AJAX 加载的动态网页中抓取动态加载的内容:

  2 解析真实地址抓取

  以《Python网络爬虫从入门到实践(第2版)》作者博客的Hello World文章为例,目标是抓取文章下的所有评论。文章网址是:

  步骤 01 打开“检查”功能。在 Chrome 浏览器中打开 Hello World文章。右键单击页面任意位置,在弹出的弹出菜单中单击“检查”命令。

  Step 02 找到真正的数据地址。单击页面中的网络选项并刷新网页。此时,Network 将显示浏览器从 Web 服务器获取的所有文件。一般这个过程就变成了“抓包”。

  从文件中快速找到评论数据所在文件的方法: 搜索评论内容可以快速定位到具体评论所在的文件。

  Step 03 爬取真实评论数据地址。既然找到了真实地址,就可以直接使用requests请求这个地址来获取数据了。

  步骤 04 从 json 数据中提取注释。您可以使用 json 库来解析数据并从中提取所需的数据。

  import requests

import json

link = "https://api-zero.livere.com/v1/comments/list?callback=jQuery112408626354130815113_1646567623361&limit=10&repSeq=4272904&requestPath=/v1/comments/list&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1646567623363"

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'}

r = requests.get(link, headers=headers)

# 获取json的string

json_string = r.text

json_string = json_string[json_string.find('{'):-2] # 从第一个左大括号提取,最后的两个字符-括号和分号不取

json_data = json.loads(json_string)

comment_list = json_data['results']['parents']

for eachone in comment_list:

message = eachone['content']

print(message)

  接下来可以使用for循环爬取多页评论数据。可以对比不同页面的真实地址,找出参数的差异,改变discount参数的值来切换页面。

  import requests

import json

def single_page_comment(link):

headers = {

'User-Agent': 'https://api-zero.livere.com/v1/comments/list?callback=jQuery112407919796508302595_1646571637355&limit=10&offset=2&repSeq=4272904&requestPath=/v1/comments/list&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1646571637361'}

r = requests.get(link, headers=headers)

# 获取json的string

json_string = r.text

json_string = json_string[json_string.find('{'):-2] # 从第一个左大括号提取,最后的两个字符-括号和分号不取

json_data = json.loads(json_string)

comment_list = json_data['results']['parents']

for eachone in comment_list:

message = eachone['content']

print(message)

max_comments = 50 # 设置要爬取的最大评论数

for page in range(1,max_comments // 10 + 1):

link1 = "https://api-zero.livere.com/v1/comments/list?callback=jQuery112407919796508302595_1646571637355&limit=10&offset="

link2 = "&repSeq=4272904&requestPath=/v1/comments/list&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1646571637361"

page_str = str(page)

link = link1 + page_str + link2

print(link)

single_page_comment(link)

  3 通过 Selenium 模拟浏览器抓取

  有些网站非常复杂,使用“inspect”功能很难找到调用页面的URL。另外,有些数据的真实地址的URL也很复杂,有些网站为了避免这些爬取,会对地址进行加密,造成一些变量的混淆。因此,这里有另一个介绍。一种方法是使用浏览器渲染引擎。使用浏览器直接显示网页时解析 HTML、应用 CSS 样式和执行 JavaScript 的语句。通俗的讲,就是通过浏览器渲染的方式,把爬取的动态页面变成爬取的静态页面。

  在这里,抓取是使用 Python 的 Selenium 库来模拟浏览器完成的。Selenium 是用于 Web 应用程序测试的工具。

  3.1 Selenium 基本介绍

  浏览器驱动下载地址:

  铬合金:

  Edge:Microsoft Edge 驱动程序 - Microsoft Edge 开发人员

  Firefox:发布 · mozilla/geckodriver · GitHub

  Safari:Safari 10 中的 WebDriver 支持 网络套件

  使用Selenium打开浏览器和网页,代码如下:

  from selenium import webdriver

driver = webdriver.Firefox()

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

  3.2 Selenium 实践案例

  步骤 01 找到评论的 HTML 代码标签。使用Chrome打开文章页面,右键该页面,在弹出的快捷菜单中点击“检查”命令。

  Step 02 尝试获取评论数据。对原打开页面的代码数据使用如下代码,获取第一条评论数据。

  from selenium import webdriver

driver = webdriver.Firefox()

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

# 转化iframe

driver.switch_to.frame(driver.find_element(by='css selector', value='iframe[title="livere-comment"]'))

# 获取css标签为div.reply-content

comment = driver.find_element(by='css selector', value='div.reply-content')

content = comment.find_element(by='tag name', value='p')

print(content.text)

  3.3 Selenium 获取 文章 的所有评论

  如果要获取所有评论,需要一个可以自动点击“+10查看更多”的脚本,这样所有评论才能显示出来。所以我们需要找到“+10 查看更多”的元素地址,然后让 Selenium 模拟点击并加载评论。具体代码如下:

  from selenium import webdriver

import time

driver = webdriver.Firefox()

driver.implicitly_wait(10) # 隐性等待,最长等10秒

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

time.sleep(5)

# 下滑到页面底部(左下角)

driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")

print("wait for 3 seconds")

time.sleep(3)

for i in range(1, 19):

# 转换iframe,再找到查看更多,点击

driver.switch_to.frame(driver.find_element(by="css selector", value="iframe[title='livere-comment']"))

# load_more = driver.find_element(by="css selector", value="button[data-page=\'%d\']'%i")

if i > 11:

x_path = './/div[@class="more-wrapper"]/button[' + str(i - 9) + ']'

else:

x_path = './/div[@class="more-wrapper"]/button[' + str(i) + ']'

load_more = driver.find_element(by="xpath", value=x_path)

load_more.send_keys("Enter") # 点击前先按下Enter,可以解决因跳转点击时出现失去焦点而导致的click单击无效的情况

load_more.click()

# 把iframe又转回去

driver.switch_to.default_content()

print("Click and waiting loading --- please waiting for 5s")

time.sleep(5)

driver.switch_to.frame(driver.find_element(by="css selector", value="iframe[title='livere-comment']"))

comments = driver.find_elements(by="css selector", value="div.reply-content")

for each_comment in comments:

content = each_comment.find_element(by="tag name", value="p")

print(content.text)

driver.switch_to.default_content()

driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")

time.sleep(2)

  Selenium 中常用的元素操作方法如下:

  from selenium import webdriver

import time

driver = webdriver.Firefox()

driver.implicitly_wait(10) # 隐性等待,最长等10秒

driver.get("http://www.santostang.com/")

time.sleep(5)

user = driver.find_element(by="name", value="username")

user.send_keys("123456")

pwd = driver.find_element(by="password") # 找到密码输入框

pwd.clear() # 清除密码输入框内容

pwd.send_keys("******") # 在框中输入密码

driver.find_element(by="id", value="loginBtn").click() # 单击登录

  除了简单的鼠标操作,Selenium 还可以实现复杂的双击、拖放操作。此外,Selenium 还可以获取网页中每个元素的大小,甚至可以模拟键盘的操作。

  3.4 Selenium 的高级操作

  常用的加快Selenium爬取速度的方法有:

  3.4.1 控制 CSS

  在爬取过程中,只爬取页面的内容。CSS 样式文件用于控制页面的外观和元素的放置,对内容没有影响。因此,我们可以限制网页上 CSS 的加载,以减少爬取时间。其代码如下:

  # 控制CSS

from selenium import webdriver

# 使用fp控制CSS的加载

fp = webdriver.FirefoxOptions()

fp.set_preference("permissions.default.stylesheet", 2)

driver = webdriver.Firefox(options=fp)

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

  3.4.2 限制图片加载

  如果不需要抓取网页上的图片,最好禁止图片加载。限制图片加载可以帮助我们大大提高网络爬虫的效率。

  # 限制图片的加载

from selenium import webdriver

fp = webdriver.FirefoxOptions()

fp.set_preference("permissions.default.image", 2)

driver = webdriver.Firefox(options=fp)

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

  3.4.3 控制 JavaScript 的执行

  如果要爬取的内容不是通过 JavaScript 动态加载的,我们可以通过禁止 JavaScript 的执行来提高爬取的效率。因为大多数网页使用 JavaScript 异步加载大量内容,我们不仅不需要这些内容,而且加载它们会浪费时间。

  # 限制JavaScript的执行

from selenium import webdriver

fp=webdriver.FirefoxOptions()

fp.set_preference("javascript.enabled",False)

driver=webdriver.Firefox(options=fp)

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

  参考

  [1] 唐松.2019.Python网络爬虫从入门到实践(第2版)[M]. 北京:机械工业出版社

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线