编写一个python脚本,递归遍历页面上的链接

时间:2012-06-04 17:48:07

标签: python

我正在为我的学校做一个项目,我想比较一下骗局邮件。我找到了这个网站:http://www.419scam.org/emails/ 现在我想做的是将每个骗局保存在单独的文档中,然后我可以分析它们。 到目前为止,这是我的代码:

import BeautifulSoup, urllib2

address='http://www.419scam.org/emails/'
html = urllib2.urlopen(address).read()
f = open('test.txt', 'wb')
f.write(html)
f.close()

这样就以文本格式保存了整个html文件,现在我想剥离文件并将html链接的内容保存到诈骗中:

<a href="2011-12/01/index.htm">01</a> 
<a href="2011-12/02/index.htm">02</a> 
<a href="2011-12/03/index.htm">03</a>

如果我得到了,我仍然需要更进一步,打开另一个href。知道如何在一个python代码中做到这一点?

谢谢!

5 个答案:

答案 0 :(得分:5)

您在BeautifulSoup中选择了正确的工具。从技术上讲,你可以在一个脚本中完成所有操作,但你可能想要对其进行分割,因为看起来你将要处理成千上万的电子邮件,所有这些都是单独的请求 - 这将需要一个而

This page会给你很多帮助,但这里只是一段代码片段,可以帮助你入门。这将获取所有html标签,这些标签是电子邮件的索引页面,提取其href链接并在URL的前面添加一些内容,以便可以直接访问它们。

from bs4 import BeautifulSoup
import re
import urllib2
soup = BeautifulSoup(urllib2.urlopen("http://www.419scam.org/emails/"))
tags = soup.find_all(href=re.compile("20......../index\.htm")
links = []
for t in tags:
    links.append("http://www.419scam.org/emails/" + t['href'])

're'是Python的正则表达式模块。在第五行中,我告诉BeautifulSoup找到汤中的所有标签,其href属性与正则表达式匹配。我选择这个正则表达式只获取电子邮件索引页面而不是该页面上的所有href链接。我注意到索引页链接具有所有URL的模式。

拥有所有正确的'a'标签,然后我循环遍历它们,通过执行t ['href']从href属性中提取字符串并将其余的URL附加到字符串的前面,以获得原始字符串网址。

通过阅读该文档,您应该了解如何扩展这些技术以获取单个电子邮件。

答案 1 :(得分:3)

您可能还会在requestslxml.html中找到价值。请求是另一种发出http请求的方法,lxml是解析xml和html内容的替代方法。

有很多方法可以搜索html文档,但您可能希望从cssselect开始。

import requests
from lxml.html import fromstring

url = 'http://www.419scam.org/emails/'
doc = fromstring(requests.get(url).content)

atags = doc.cssselect('a')

# using .get('href', '') syntax because not all a tags will have an href
hrefs = (a.attrib.get('href', '') for a in atags)

或使用.iterlinks()的评论中的建议。请注意,如果您只需要“a”标记,则仍需要进行过滤。无论哪种方式,.make_links_absolute()调用都可能会有所帮助。这是你的功课,所以玩吧。

doc.make_links_absolute(base_url=url)

hrefs = (l[2] for l in doc.iterlinks() if l[0].tag == 'a')

接下来为您...如何循环并打开所有单个垃圾链接。

答案 2 :(得分:2)

要获取页面上的所有链接,您可以使用BeautifulSoup。看看this page,它可以提供帮助。它实际上告诉你如何做你需要的。

要保存所有页面,您可以执行与当前代码相同的操作,但是在循环中会迭代您已经提取并存储的所有链接,例如,在列表中。

答案 3 :(得分:2)

您可以使用HTML parser并指定要搜索的对象类型。

from HTMLParser import HTMLParser
import urllib2

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            for attr in attrs:
                if attr[0] == 'href':
                    print attr[1]

address='http://www.419scam.org/emails/'
html = urllib2.urlopen(address).read()
f = open('test.txt', 'wb')
f.write(html)
f.close()

parser = MyHTMLParser()
parser.feed(html)

答案 4 :(得分:2)

使用lxml + XPathurllib2找到解决方案:

#!/usr/bin/env python2 -u
# -*- coding: utf8 -*-

import cookielib, urllib2
from lxml import etree

cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
page = opener.open("http://www.419scam.org/emails/")
page.addheaders = [('User-agent', 'Mozilla/5.0')]
reddit = etree.HTML(page.read())

# XPath expression : we get all links under body/p[2] containing *.htm
for node in reddit.xpath('/html/body/p[2]/a[contains(@href,".htm")]'):
    for i in node.items():
        url  = 'http://www.419scam.org/emails/' + i[1]
        page = opener.open(url)
        page.addheaders = [('User-agent', 'Mozilla/5.0')]

        lst = url.split('/')
        try:
            if lst[6]: # else it's a "month" link
                filename = '/tmp/' + url.split('/')[4] + '-' + url.split('/')[5]
                f = open(filename, 'w')
                f.write(page.read())
                f.close()
        except:
            pass

# vim:ts=4:sw=4