使用python从网页获取链接 - 更好地替代Selenium

时间:2018-02-24 10:00:16

标签: python selenium web-scraping hyperlink

我一直在浏览这个问题,并为我的问题找到了一些工作,但是想知道是否有更好的解决方案。

特别是,我需要从网页获取所有pdf文件的链接 - 例如:http://stock.walmart.com/investors/financial-information/annual-reports-and-proxies/default.aspx

我最初尝试使用简单的东西(我正在使用Python3):

import requests
from bs4 import BeautifulSoup
import urllib
import os

base_url = 'http://stock.walmart.com/investors/financial-information/annual-reports-and-proxies/default.aspx'
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}

r = requests.get(url=base_url, headers=headers)
soup = BeautifulSoup(r.text)
links = soup.findAll('a', href=True)
for tag in links:
    tag['href'] = urllib.parse.urljoin(base_url, tag['href'])

    if os.path.splitext(os.path.basename(tag['href']))[1] == '.pdf':
        print(tag['href'])

但这没有做,因为我错过了所有PDF链接。我不是这方面的专家,但阅读它似乎是因为它们是用JavaScript动态呈现的,或者通过后续的POST请求获得。

因此,我尝试了第二种方法,使用Selenium:

driver = webdriver.Chrome('./chromedriver')  
driver.get(url)

elems = driver.find_elements_by_xpath("//a[@href]")

print([link for link in url_list if link[-4:].lower() == '.pdf'])

这很有效,但对于我来说这看起来很容易。因此:

  1. 我是否在第一种方法中遗漏了某些东西,这可能会使它起作用?一位朋友建议只使用命令行中的wget,它似乎可以工作并找到所有pdf链接(!!),因此可能有一种简单的方法可以做到这一点...
  2. 如果我们真的需要使用网络驱动程序,那么最轻的选择是什么?我不想使用Chrome并打开浏览器窗口 - 我正在阅读PhantomJS但不确定
  3. 我们如何处理重新指示?第二种方法会照顾它们吗?
  4. 一般而言,任何其他完成任务的提示都非常受欢迎。我应该看看scrapy吗?或者那会出现同样的问题吗?

    非常感谢。

1 个答案:

答案 0 :(得分:1)

硒...

一个真正通用的解决方案必须考虑到许多现代网页使用JavaScript来呈现其内容的事实。因此,缺少JavaScript运行时的任何工具或库(例如requestsimport capybara from capybara.dsl import page import re @capybara.register_driver("selenium_chrome_headless") def init_selenium_chrome_headless_driver(app): from selenium.webdriver.chrome.options import Options from capybara.selenium.driver import Driver chrome_options = Options() chrome_options.add_argument("--headless") return Driver(app, browser="chrome", chrome_options=chrome_options) capybara.current_driver = "selenium_chrome_headless" page.visit(url) links = page.find_all("link", # Match only URLs ending in ".pdf" href=re.compile(r"\.pdf$"), # Assuming you expect, and would like to wait # for, at least one PDF link on the page minimum=1) urls = [link["href"] for link in links] )都无法访问此类内容。需要一个JavaScript运行时,实际上意味着需要一个浏览器,而Selenium是控制浏览器最强大的方式。

......无头Chrome ......

对于“轻量级”方法,PhantomJS当然是一种选择,但随着Chrome等主流浏览器开始提供越来越可靠的无头操作,它的支持和随后的价值已经减弱。在这一点上,我强烈建议使用无头Chrome,而不是PhantomJS。

......和(作为奖励)Capybara

虽然Selenium为您提供了控制浏览器的基本工具,但它将处理现代异步Web应用程序作为读者的练习。例如,如果加载页面上的内容需要一段时间,该怎么办? Selenium要求您反复明确地管理它。

capybara-py通过在Selenium上提供一个层来帮助解决这个问题,除了其他方面之外,它还可以透明地同步您的交互,无论您是在加载页面还是填写表单字段或点击链接和按钮:

materials[i] = new THREE.MeshLambertMaterial({ map:texture });