链接到事件点击时如何从网站抓取数据?

How to scrape data from a website when linked to event clicks?

我正在尝试从 Tripadvisor.com 个网页 scrape/extract company/hotel 的网站。我在检查页面时没有看到网站 url。关于如何使用 python 提取网站 url 的任何想法? 提前道歉,因为我最近才开始 'web scraping in Python.' 谢谢。

例如请看图中的两个红色箭头。当我 select 网站 link 时,它会将我带到“http://www.i-love-my-india.com/” - 这是我想使用 Python 提取的内容。

Tripadvisor url

使用 Selenium 试试这个:

import time
from selenium import webdriver

browser = webdriver.Firefox(executable_path="C:\Users\Vader\geckodriver.exe")
# Must install geckodriver (handles your browser)- see instructions on
# http://selenium-python.readthedocs.io/installation.html.
# Change the path to where your geckodriver file is.

browser.get('https://www.tripadvisor.co.uk/Attraction_Review-g304551-d4590508-Reviews-Ashok_s_Taxi_Tours-New_Delhi_National_Capital_Territory_of_Delhi.html')
browser.find_element_by_css_selector('.blEntry.website').click()

#browser.window_handles # Results is 2 tabs opened. 

browser.switch_to.window(browser.window_handles[1]) # changes the browser to 
                                                    # the second one

time.sleep(1) # When I went directly I was getting a 'blank' result, so I put
              # a little delay and it worked (I really do not know why).

res = browser.current_url # the URL

print(res)

browser.quit() # Closes the browser

Selenium

如果您查看该元素,您会注意到重定向 URL 存在(data-ahref 属性),但它在 JS 源代码中的某处进行了编码和解码。不幸的是,它们被缩小和混淆了,因此很难找到解码器函数。因此你有两个选择:

跟随重定向

这就是 Roberval _T_ suggested in his :点击该元素,等待一段时间让页面加载到另一个选项卡中,抓住 URL。这是一个完全有效的答案,在我看来值得点赞,但是当由于某种原因所需的数据不可用时,我总是尝试以下小技巧:

抓取移动网页

抓取移动页面的明显优势是它们比桌面页面更轻量级。但通常,当桌面版本出于某种原因试图隐藏数据时,移动网站也会显示数据。在这种情况下,可以立即抓取移动版本中的所有信息(地址、主页、phone),而无需显式加载 URL。这是我使用移动用户代理 运行 selenium 时页面的样子:

使用 IPhone 的用户代理的示例代码:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

url = 'https://www.tripadvisor.co.uk/Attraction_Review-g304551-d4590508-Reviews-Ashok_s_Taxi_Tours-New_Delhi_National_Capital_Territory_of_Delhi.html'
chrome_options = Options()
chrome_options.add_argument('--user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1')
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get(url)

element = driver.find_element_by_css_selector('div.website.contact_link')
link = element.text
driver.quit()
print(link)

我会推荐使用硒。

我的回答可以看作是对@Roberval T 建议的改进。我认为他的回答非常适合这个特殊情况。

这是我的解决方案。我将指出一些差异以及我认为您应该考虑它们的原因:

import sys

# Selenium
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException


# I would use argparse for example
try:
    assert len(sys.argv) == 2
    url = sys.argv[1]
except AssertionError:
    # Invalid arguments
    sys.exit()

# Set up the driver
driver = webdriver.Chrome()
driver.get(url)

# Try to load the page a wait until it's loaded
try:
    poll_frequency = 5
    data_section_id = "taplc_location_detail_header_attractions_0"
    data_section = WebDriverWait(driver, poll_frequency).until(EC.presence_of_element_located((By.ID, data_section_id)))
except TimeoutException:
    # Could not load page
    sys.exit()

# Get the third child ( relative to the data section div that we get by ID )
try:
    third_child = data_section.find_elements_by_xpath("./*")[2]
except IndexError:
    sys.exit()

# Get the child immediatly under that ( that's how the structure looks)
container_div = third_child.find_elements_by_xpath("./*")[0]
clickable_element = container_div.find_elements_by_xpath("./*")[3]

# Click the node
clickable_element.click()

# Switch tabs
driver.switch_to.window(driver.window_handles[1])

try:
    new_page = WebDriverWait(driver, poll_frequency).until(EC.presence_of_element_located((By.TAG_NAME, "body")))
except TimeoutError:
    sys.exit()

print(driver.current_url)
assert driver.current_url == "http://www.i-love-my-india.com/"

driver.quit()
  1. 首先,在我看来,你应该使用selenium's特定的等待机制而不是time.sleep()。这将使您能够更好地微调您的刮刀,也将使其更加可靠。我建议您查看 WebDriverWait

  2. 其次,我个人的偏好是避免使用class selectors。我并不是说他们错了。但经验告诉我,它们可以很容易地改变,而且经常在多个地方使用相同的 class (这就是为什么它是 class )。在这种特殊情况下,选择使用 CSS class 是有效的,因为 class 在一个地方使用。

    • 如果在下一个版本中,在另一个地方使用相同的 class 会怎样?

    • 虽然也不能保证遵循结构,但更改的可能性较小。

  3. 使用Chrome。由于版本 59,Google Chrome 有一个 headless 选项。在我看来,使用 then Firefox 要容易得多。使用 Firefox 将需要您在生产机器上安装 运行 一个 x server 服务,并通过 geckodriverFirefox 实例连接到该服务器。您可以使用 Chrome.

  4. 跳过所有这些

希望对您有所帮助!