【问题标题】:Scraping URLs from web pages using Selenium Python (NSFW)使用 Selenium Python (NSFW) 从网页中抓取 URL
【发布时间】:2017-02-13 21:47:48
【问题描述】:

我正在通过尝试编写脚本来抓取 xHamster 来学习 Python。如果有人熟悉该网站,我正在尝试将给定用户视频的所有 URL 专门写入 .txt 文件。

目前,我已经设法从特定页面上抓取 URL,但是有多个页面,我正在努力循环浏览页面数量。

在下面的尝试中,我评论了我试图读取下一页 URL 的位置,但它当前打印的是 None。任何想法为什么以及如何解决这个问题?

当前脚本:

#!/usr/bin/env python

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--incognito")

driver = webdriver.Chrome(chrome_options=chrome_options)

username = **ANY_USERNAME**
##page = 1
url = "https://xhams***.com/user/video/" + username + "/new-1.html"

driver.implicitly_wait(10)
driver.get(url)

links = [];
links = driver.find_elements_by_class_name('hRotator')
#nextPage = driver.find_elements_by_class_name('last')

noOfLinks = len(links)
count = 0

file = open('x--' + username + '.txt','w')
while count < noOfLinks:
    #print links[count].get_attribute('href')
    file.write(links[count].get_attribute('href') + '\n');
    count += 1

file.close()
driver.close()

我尝试循环浏览页面:

#!/usr/bin/env python

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--incognito")

driver = webdriver.Chrome(chrome_options=chrome_options)

username = **ANY_USERNAME**
##page = 1
url = "https://xhams***.com/user/video/" + username + "/new-1.html"

driver.implicitly_wait(10)
driver.get(url)

links = [];
links = driver.find_elements_by_class_name('hRotator')
#nextPage = driver.find_elements_by_class_name('colR')

## TRYING TO READ THE NEXT PAGE HERE
print driver.find_element_by_class_name('last').get_attribute('href')

noOfLinks = len(links)
count = 0

file = open('x--' + username + '.txt','w')
while count < noOfLinks:
    #print links[count].get_attribute('href')
    file.write(links[count].get_attribute('href') + '\n');
    count += 1

file.close()
driver.close()

更新:

我在下面使用了 Philippe Oger 的答案,但修改了以下两种方法以适用于单页结果:

def find_max_pagination(self):
    start_url = 'https://www.xhamster.com/user/video/{}/new-1.html'.format(self.user)
    r = requests.get(start_url)
    tree = html.fromstring(r.content)
    abc = tree.xpath('//div[@class="pager"]/table/tr/td/div/a')
    if tree.xpath('//div[@class="pager"]/table/tr/td/div/a'):
        self.max_page = max(
            [int(x.text) for x in tree.xpath('//div[@class="pager"]/table/tr/td/div/a') if x.text not in [None, '...']]
        )
    else:
        self.max_page = 1

    return self.max_page

def generate_listing_urls(self):
    if self.max_page == 1:
        pages = [self.paginated_listing_page(str(page)) for page in range(0, 1)]
    else:
        pages = [self.paginated_listing_page(str(page)) for page in range(0, self.max_page)]

    return pages

【问题讨论】:

  • 即使您确实导入了 BeautifulSoup,但看起来您根本没有使用它
  • @xbonez 啊,是的,在切换到 Selenium 之前,我最初使用的是 BeautifulSoup。已编辑。
  • 不知道你为什么在这个上使用 Selenium。 Beautifulsoup 或 Lxml 可能是更好的选择。
  • @PhilippeOger 有人建议我使用 Selenium,因为视频可能会动态加载。我的原始代码/问题发布在这里 - reddit.com/r/learnprogramming/comments/5tv2g5/…
  • 它似乎是在 HTML 中硬编码的。 Beautifulsoup 应该可以正常工作。在下面查看我的答案,它提供了一种使用 LXML 的方法。

标签: python selenium web-scraping


【解决方案1】:

在用户页面上,我们实际上可以找出分页的距离,因此我们可以使用列表解析生成用户的每个 url,而不是循环遍历分页,然后逐个抓取。

这是我使用 LXML 的两分钱。如果您只是复制/粘贴此代码,它将返回 TXT​​ 文件中的每个视频 url。您只需要更改用户名。

from lxml import html
import requests


class XXXVideosScraper(object):

    def __init__(self, user):
        self.user = user
        self.max_page = None
        self.video_urls = list()

    def run(self):
        self.find_max_pagination()
        pages_to_crawl = self.generate_listing_urls()
        for page in pages_to_crawl:
            self.capture_video_urls(page)
        with open('results.txt', 'w') as f:
            for video in self.video_urls:
                f.write(video)
                f.write('\n')

    def find_max_pagination(self):
        start_url = 'https://www.xhamster.com/user/video/{}/new-1.html'.format(self.user)
        r = requests.get(start_url)
        tree = html.fromstring(r.content)

        try:
            self.max_page = max(
            [int(x.text) for x in tree.xpath('//div[@class="pager"]/table/tr/td/div/a') if x.text not in [None, '...']]
        )
        except ValueError:
            self.max_page = 1
        return self.max_page

    def generate_listing_urls(self):
        pages = [self.paginated_listing_page(page) for page in range(1, self.max_page + 1)]
        return pages

    def paginated_listing_page(self, pagination):
        return 'https://www.xhamster.com/user/video/{}/new-{}.html'.format(self.user, str(pagination))

    def capture_video_urls(self, url):
        r = requests.get(url)
        tree = html.fromstring(r.content)
        video_links = tree.xpath('//a[@class="hRotator"]/@href')
        self.video_urls += video_links


if __name__ == '__main__':
    sample_user = 'wearehairy'
    scraper = XXXVideosScraper(sample_user)
    scraper.run()

我没有检查用户总共只有 1 页的情况。让我知道这是否正常。

【讨论】:

  • 感谢您的示例。对于用户总共 1 页(例如 unmasker777),它在 ...第 27 行出错,在 find_max_pagination [int(x.text) for x in tree.xpath('//div[@class="pager"] /table/tr/td/div/a') if x.text not in [None, '...']] ValueError: max() arg is an empty sequence
  • 我们可以通过 Try/Except 捕获该错误。让我编辑代码。
猜你喜欢
  • 2019-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 2018-07-20
  • 2019-11-05
相关资源
最近更新 更多