python抓取动态网页(如何抓取网页特定数据的爬虫,我是怎么做到的)

优采云 发布时间: 2021-09-16 14:05

  python抓取动态网页(如何抓取网页特定数据的爬虫,我是怎么做到的)

  最近,我的朋友让我帮助设计一个能够捕获网页特定数据的爬虫程序。我认为这个计划的实施非常简单。只需通过相应的URL获取HTML页面代码,然后解析HTML以获取所需的数据。然而,在实践中,我发现我原来认为的太简单了。页面上有很多数据不能简单地从HTML源代码中捕获,因为页面上显示的很多数据实际上是在JS代码运行时通过Ajax从远程服务器获取后动态加载到页面中的。因此,不可能简单地读取HTML源代码以获得所需的数据。例如,我们打开京东主页,在搜索框中输入关键词“无极白凤丸”。退货页面显示60个商品项目,如下图所示:

  

  打开JS控制台,选择元素,单击左上角的箭头,然后将箭头移动到该项。我们可以在HTML中看到它对应的元素:

  

  我们可以看到,页面上显示的项对应于ID为“gl-i-wrap”的div控件,这意味着如果我们想从HTML中获取页面上显示的信息,我们必须从HTML代码中获取具有给定ID的div组件并分析其内容。问题是,如果右键单击调出其页面源代码,然后查找字符串“gl-i-wrap”,您会发现它只收录30项,但计算页面上显示60项,即30项信息无法通过HTML代码直接获取。额外的30项信息实际上是在特定条件下触发一段JS代码后通过Ajax从服务器获得的,然后添加到dom中。因此,我们不能简单地从页面对应的HTML中获取它。我通过搜索发现,在线通信的解决方案是分析JS代码的那一部分来获取这些数据,然后研究如何以类似逆向工程的方式构造HTTP请求,然后模拟发送这些请求来获取数据。我认为这种方法存在一系列问题。首先,您必须分析大量难以理解的JS代码,因此您可以想象工作量和难度。其次,如果这种方法网站将来改变了数据采集方法,您必须再次进行逆向工程。因此,这种方法非常不经济。如何简单方便地获取动态加载的数据。只要产品信息显示在页面上,就可以通过dom获取。因此,如果我们有办法在浏览器中获得DOM模型,我们就可以读取动态加载的数据。由于冗余数据是在页面被拉下后通过Ajax触发给定的JS代码动态获取的,所以如果我们可以通过代码控制浏览器加载网页,那么让浏览器拉下页面,然后读取浏览器页面对应的DOM,就可以得到动态加载的数据。经过一些调查,我们发现称为selenium的控件可以通过代码动态控制浏览器。例如,让浏览器加载一个特定的页面,让浏览器下拉该页面,然后在浏览器中加载该页面的HTML代码,这样我们就可以使用它轻松抓取动态页面数据。首先,通过命令PIP install selenium下载控件。如果我们想用它来控制Chrome浏览器,我们还需要下载chromedriver控件。首先,确定您使用的chrome版本。chromedriver必须与当前使用的chrome版本完全相同。通过以下链接下载:

  请记住选择与您的Chrome浏览器一致的下载版本。之后,我们可以启动浏览器并通过以下代码加载具有给定URL的网页:

  

op = webdriver.ChromeOptions()

webdriver.Chrome('/Users/apple/Documents/chromedriver/chromedriver', chrome_options = op)

driver.get('https://www.jd.com/')

  运行上述代码后,您可以启动浏览器,看到他打开京东主页。此时,我想在搜索框中自动输入关键词。通过HTML源代码,发现搜索框对应的ID为“key”。因此,我们可以通过以下代码在搜索框中输入关键词模拟人工输入,然后模拟点击enter按钮实现搜索请求:

  

search_box = driver.find_element_by_id('key')

search_box.send_keys(word)

search_box.send_keys(Keys.ENTER)

timeout = 10

try:

print("wait page...")

WebDriverWait(driver, timeout)

except TimeoutException:

print("Timed out waiting for page to load")

finally:

  由于浏览器和代码不再在同一进程中运行,我们需要调用webdriverwait并等待一段时间,以便浏览器完全加载页面。接下来,为了触发特定的JS代码以获得动态加载的数据,我们需要模拟人们下拉页面的动作:

  

SCROLL_PAUSE_TIME = 0.5

last_height = driver.execute_script("return document.body.scrollHeight")

while True: #将页面滑动到底部

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

time.sleep(SCROLL_PAUSE_TIME)

new_height = driver.execute_script("return document.body.scrollHeight")

if new_height == last_height:

break

last_height = new_height

  执行上述代码后,您会发现浏览器页面将自动下降到底部,因此JS将发送一个Ajax请求以从服务器获取另外30个项目的数据。然后我们将执行一段JS代码来获取body组件对应的HTML源代码,然后获取ID为gl-i-wrap的div对象。此时我们会看到它返回60个对应的组件,这意味着可以获得页面上的所有产品数据:

  

page_source = driver.execute_script("return document.body.innerHTML;")

bs = BeautifulSoup(page_source, 'html.parser')

info_divs = bs.find_all("div", {"class" : "gl-i-wrap"})

print(len(info_divs)) #这里输出结果为60

  这样,我们可以读取所有页面上显示的商品价格信息。这种方法比解析JS代码,然后反向构造HTTP请求来获取页面上动态加载的数据要简单、方便和容易得多。有关详细说明和调试演示,请单击“阅读原文”查看视频

  本文由微信官方账号-编码迪士尼(gh_c9f933e7765d)分享。p>

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线