【问题标题】:How does obey robots.txt using Python 2.7?如何使用 Python 2.7 遵守 robots.txt?
【发布时间】:2015-11-08 17:19:41
【问题描述】:

我尝试使用 Python2.7 抓取整个网站:

  • 我使用robotparser解析了robots.txt文件
  • 我通过网站打开每个链接“a”,然后
  • 我将它们添加到要抓取的页面列表中 重点是: 我试图避开 Robots.txt 文件中的所有路径,但它们仍在要抓取的页面列表中。

如何从抓取列表中删除 Robot.txt 路径?

我还没有通过 stackoverflow 找到任何帮助。

我的代码如下:

import robotparser
import urlparse
import urllib
import urllib2
from BeautifulSoup import *

AGENT_NAME = 'PYMOTW'
URL_BASE = 'website'
urls = [URL_BASE]
visited = [URL_BASE] # Create a copy
parser = robotparser.RobotFileParser()
parser.set_url(urlparse.urljoin(URL_BASE, 'robot.txt'))
parser.read()
PATHS = [
    '/..../',

    ]
for path in PATHS:
    print '%6s : %s' % (parser.can_fetch(AGENT_NAME, path), path)
    url = urlparse.urljoin(URL_BASE, path)
    print '%6s : %s' % (parser.can_fetch(AGENT_NAME, url), url)
    robot = [url]
while (len(urls) > 0 and robot != True):
    html = urllib.urlopen(urls[0]).read()
    soup = BeautifulSoup(html) # Parse All HTML using BeautifulSoup
    urls.pop(0)
# Retrieve all of Tags as a list
    for tags in soup.findAll('a', href = True):
        tags['href'] = urlparse.urljoin(URL_BASE, tags['href'])
        if URL_BASE in tags['href'] and tags['href'] not in visited:
            urls.append(tags['href'])
            visited.append(tags['href'])
        c = len(visited)
print visited
print 'page visited', c

【问题讨论】:

  • 欢迎来到 Stack Overflow!我已编辑您的帖子以删除代码 sn-p 功能,该功能仅适用于在 Web 浏览器中运行的 HTML / JavaScript。除了删除 Python 3 标记外,我还修复了拼写并添加了格式以提高可读性。像这样改进您的问题将增加人们阅读您的问题并获得良好答案的机会。
  • 谢谢@AnthonyGeoghegan
  • 嗨@J.F.Sebastian。返回的是 True 值的列表。
  • @J.F.Sebastian - 我更正了给出网址的代码。我有禁止列表,但我不确定如何将其从列表中删除以进行抓取?
  • 您的代码有点不清楚,您想获取robot.txt,并且对于您预定义的每个路径(在PATHS),您只想在robot 允许的情况下访问该页面?

标签: python python-2.7 beautifulsoup


【解决方案1】:

您的脚本中有几个错误。

我重构了很多,并会尝试解释。

  1. 首先,当您想要进行递归时,您正在使用循环(对于每个 您获得的页面,您会获得链接并重做该过程)。
  2. 然后由于我不知道的原因,urlparse.join 失败...(您的 url 被截断),所以我手动连接。
  3. 美汤很重,所以我重构它只解析链接而不是整页。一个页面可以有相对链接和绝对链接,因此您需要同时处理这两者。
  4. robotparser 好像挺傻的,路径一定要准确(/test/test/ 对他来说不一样)。如果没有在 robots.txt 中指定,他也无法理解完整的 url(测试 http://example.com/test 匹配 */test 但不匹配 /test ...)
  5. 编辑:我通过过滤匹配的 url 使脚本更加强大。

这个给我:

import robotparser
import urlparse
import urllib
from BeautifulSoup import BeautifulSoup, SoupStrainer

AGENT_NAME = 'PYMOTW'
URL_BASE = 'http://www.dcs.bbk.ac.uk/~martin/sewn/ls3'
DOMAIN = urlparse.urlparse(URL_BASE).hostname
visited = ['/']  # Create a copy

parser = robotparser.RobotFileParser()
parser.set_url(URL_BASE  + '/robots.txt')
parser.read()


def process_url(url):
    # transform relative paths
    parsed_path = urlparse.urlparse(url)
    if not parsed_path.hostname:
        url = URL_BASE  + url

    # check domain
    if parsed_path.hostname != DOMAIN:
        print 'External domain ignored: %s' % parsed_path.hostname

    # ensure we are allowed to fetch url
    if not parser.can_fetch(AGENT_NAME, parsed_path.path):
        print 'Not allowed to fetch %s' % parsed_path.path
        return

    # ensure we did not already visit it
    if url in visited:
        print 'Ignoring already visited %s' % url
        return

    print 'Visiting: %s' % url
    html = urllib.urlopen(url).read()
    visited.append(url)
    links = BeautifulSoup(html, parseOnlyThese=SoupStrainer('a', href=True))

    # Retrieve all of Tags as a list
    for link in links:
        parsed_link = urlparse.urlparse(link['href'])
        if len(link['href']) is 0:
            print 'Ignoring empty link'
        elif link['href'][0] == '#':
            print 'Ignoring hash link %s' % link['href']
        elif parsed_path.hostname and parsed_link.scheme not in [None, 'http', 'https']:
            print 'Ignoring non http(s) links %s' % link['href']
        else:
            process_url(link['href'])

PATHS = [
    '/testpage.html',
    '/files/',
    '/images/',
    '/private/'
]
for path in PATHS:
    process_url(path)

【讨论】:

  • 我还没有定义函数。我是初学者,所以我尝试用我的基本知识创建一个爬行程序。你的更正对我来说很清楚。我非常了解递归,即使它们在函数内部(对我来说是第一次)但是我有一些问题: - 为什么将所有域堆叠在访问的变量中?我可以只为域 /ls3/... 工作吗? - 在 def process_url(url) 中:我不清楚变量:url = URL_BASE + url (url?) 它是函数中的参数:process_url?
  • 如果在域之外,您可以过滤以不抓取。在print 'Visiting: %s' % url 之前添加一个新的 if 条件。另请注意,此“机器人”不会跟踪它所在的域,并且总是在前面加上 URL_BASE 变量。是的,url 是函数process_url 的参数,但由于它可以是绝对路径或相对路径,我将其重新定义为始终以绝对 url 结尾。
  • @Cyrbil 如果我在 print 'Visiting: %s' %url 之前插入一个新条件,程序将继续读取机器人而不是我真正需要抓取的标签。要阅读我的链接,我必须创建一个新功能?我不清楚。如果我正在抓取相反的部分,我该如何抓取页面。 “机器人”到底是什么意思?
  • @Cyrbil - 分析程序,它没有进入函数。它从循环外的 PATHS 中抓取“/testpage.html”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 2017-04-13
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2021-11-17
  • 1970-01-01
相关资源
最近更新 更多