抓取受保护的电子邮件

Posted

技术标签:

【中文标题】抓取受保护的电子邮件【英文标题】:Scraping of protected email 【发布时间】:2016-08-23 00:26:57 【问题描述】:

我需要从网站上抓取电子邮件。 它在浏览器中可见,但是当我尝试使用 requests\BeautifulSoup 抓取它时,我得到了这个:“[电子邮件保护]”

我可以使用 Selenium 执行此操作,但需要更多时间,我想知道是否可以使用 requests\BeautifulSoup 抓取这些电子邮件?也许需要使用一些库来处理 js。

电子邮件标签:

<span id="signature_email"><a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="30425f5e70584346515c5c531e535f5d">[email&#160;protected]</a><script data-cfhash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p)tryt=document.currentScript||function()for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]();if(t&&(c=t.previousSibling))p=t.parentNode;if(a=c.getAttribute('data-cfemail'))for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)p.removeChild(t)catch(u)()/* ]]> */</script></span></span> <span class="separator">|</span>

【问题讨论】:

这些邮件是否来自邮件列表?你不能简单地从邮件列表中获取它们吗? 不,电子邮件在网页上。 你能显示你提出请求的代码吗?您是否包含用户代理?一个指向页面的链接也会很有帮助,这样我们就可以看到电子邮件是如何显示的 BeautifulSoup 不评估 javascript。所以我认为你必须坚持使用 Selenium... 【参考方案1】:

从 CF 标记,在您提供的 html 中,我假设您正在抓取一个 cloudflare 站点。他们提供了一项功能来混淆列出的电子邮件 (see here),该功能对 HTML 中的地址进行加密,并使用 JavaScript 对其进行解密。因此,使用 selenium 您会看到电子邮件地址,但使用请求时您不会。

由于可以很容易地从 JavaScript 中获取解密方法,因此您可以在 Python 中编写自己的解密方法。

在 JavaScript 中,

(function () 
    try 
        var s, a, i, j, r, c, l = document.getElementById("__cf_email__");
        a = l.className;
        if (a) 
            s = '';
            r = parseInt(a.substr(0, 2), 16);
            for (j = 2; a.length - j; j += 2) 
                c = parseInt(a.substr(j, 2), 16) ^ r;
                s += String.fromCharCode(c);
            
            s = document.createTextNode(s);
            l.parentNode.replaceChild(s, l);
        
     catch (e) 
)();

在 Python 中,

def decodeEmail(e):
    de = ""
    k = int(e[:2], 16)

    for i in range(2, len(e)-1, 2):
        de += chr(int(e[i:i+2], 16)^k)

    return de

【讨论】:

太棒了!索瓦,非常感谢你!效果很好。【参考方案2】:

所有语言的代码是here:

Javascript

function cfDecodeEmail(encodedString) 
    var email = "", r = parseInt(encodedString.substr(0, 2), 16), n, i;
    for (n = 2; encodedString.length - n; n += 2)
        i = parseInt(encodedString.substr(n, 2), 16) ^ r;
        email += String.fromCharCode(i);
    
    return email;


console.log(cfDecodeEmail("543931142127353935313e352e7a373b39")); // usage

Python

def cfDecodeEmail(encodedString):
    r = int(encodedString[:2],16)
    email = ''.join([chr(int(encodedString[i:i+2], 16) ^ r) for i in range(2, len(encodedString), 2)])
    return email

print cfDecodeEmail('543931142127353935313e352e7a373b39') # usage

PHP

function cfDecodeEmail($encodedString)
  $k = hexdec(substr($encodedString,0,2));
  for($i=2,$email='';$i<strlen($encodedString)-1;$i+=2)
    $email.=chr(hexdec(substr($encodedString,$i,2))^$k);
  
  return $email;


echo cfDecodeEmail('543931142127353935313e352e7a373b39'); // usage

package main

import (
    "bytes"
    "strconv"
)

func cf(a string) (s string) 
    var e bytes.Buffer
    r, _ := strconv.ParseInt(a[0:2], 16, 0)
    for n := 4; n < len(a)+2; n += 2 
        i, _ := strconv.ParseInt(a[n-2:n], 16, 0)
        e.WriteString(string(i ^ r))
    
    return e.String()


func main() 
    email := cf("543931142127353935313e352e7a373b39") // usage
    print(email)
    print("\n")

C++

#include <iostream>
#include <string>

using namespace std;

string cfDecodeEmail(string encodedString);

int main()

    cout << cfDecodeEmail("543931142127353935313e352e7a373b39") << endl;


string cfDecodeEmail(string encodedString)

    string email;
    char xorKey = stoi( encodedString.substr(0, 2), nullptr, 16);
    for( unsigned i = 2; i < encodedString.length(); i += 2)
        email += stoi( encodedString.substr(i, 2), nullptr, 16) ^ xorKey;

    return email;

C#

using System;

public class Program

    public static string cfDecodeEmail(string encodedString)
    
        string email = "";
        int r = Convert.ToInt32(encodedString.Substring(0, 2), 16), n, i;
        for (n = 2; encodedString.Length - n > 0; n += 2)
        
            i = Convert.ToInt32(encodedString.Substring(n, 2), 16) ^ r;
            char character = (char)i;
            email += Convert.ToString(character);
        

        return email;
    

    public static void Main(string[] args)
    
        Console.WriteLine(cfDecodeEmail("543931142127353935313e352e7a373b39")); // usage
    

【讨论】:

【参考方案3】:

根据上述算法,我用 Ruby 编写了代码来解析 [protected email] 和 nokogiri

def decode_email(e)
  r = Integer(e[0,2], 16)
  (2..e.length - 2).step(2).map do |j|
    c = Integer(e[j,2], 16) ^ r
    c.chr
  end.join('')
end

【讨论】:

以上是关于抓取受保护的电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

Office 365 受保护的视图破坏 Excel 宏

Mcafee Email-Gateway 阻挡受保护附件

谷歌电子表格脚本 - 保护工作表的权限

Spring oauth2 指定受保护和不受保护的资源

得力西开关上的ELE是啥意思

在 R 中抓取受密码保护的网站