python如何爬取搜狐新闻文章(图片解密)

首先大概上看了一下文章的内容,大概就是文字和图片:

右击查看网页源代码发现能得到文字和加了密之后的图片:怎么解决这些加了密的图片勒?

我们右击打开检查元素来到Sources,然后全局搜索 www.sohu.com6666,如下所示:

在33795那里 var s = e(o, “www.sohu.com6666”),这个地方调用勒一个e()函数,就是上面第一个框起来的。

那么我们现在在33795这个地方打一个断点。看一下o变量的值是多少,刷新网页查看。

打了断点刷新勒之后的数据为:

o的数据就是我们requests请求到的数据,通过了e()函数的调用之后s变量就是图片的url连接。

如何图片解密?

上面是不是我们可以通过请求拿到那个加密了的之后的密文,其实上述的”www.sohu.com6666″就是一个密钥,上面是一个AES加密的一个算法,具体的我也不清楚,我直接到网上抄了一个相关的代码,调试了之后发现把密钥和密文解密了之后就出图片的url链接了。

解密算法参考:

这里我把我调试好了的解密代码放上来:

from Crypto.Cipher import AES
import base64


BLOCK_SIZE = 16  # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
                chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

# 加密
def aesEncrypt(key, data):
    '''
    AES的ECB模式加密方法
    :param key: 密钥
    :param data:被加密字符串(明文)
    :return:密文
    '''
    key = key.encode('utf8')
    # 字符串补位
    data = pad(data)
    cipher = AES.new(key, AES.MODE_ECB)
    # 加密后得到的是bytes类型的数据,使用Base64进行编码,返回byte字符串
    result = cipher.encrypt(data.encode())
    encodestrs = base64.b64encode(result)
    enctext = encodestrs.decode('utf8')
    # print(enctext)
    return enctext

# 解密
def aesDecrypt(key, data):
    '''

    :param key: 密钥
    :param data: 加密后的数据(密文)
    :return:明文
    '''
    key = key.encode('utf8')
    data = base64.b64decode(data)
    cipher = AES.new(key, AES.MODE_ECB)

    # 去补位
    text_decrypted = unpad(cipher.decrypt(data))
    text_decrypted = text_decrypted.decode('utf8')
    print(text_decrypted)
    return text_decrypted


if __name__ == '__main__':
    # 密钥
    key = 'www.sohu.com6666'
    # data = 'herish acorn'
    # ecdata = aesEncrypt(key, data)
    # 直接传入加密之后的内容即可
    ecdata = 'ltlBByDSz8LS2xDpve58U57gc+l4j9jP6HFD+zMTEU5G5BeZPU3TSXb7V0VX9Tc5Q5/crQO8Hh6MQyTJI419VcaaNXoTNXv1wET9ZD8Nhkc='
    aesDecrypt(key, ecdata)

这里的代码有一个加密和解密的算法,而在我们网页上显示的是加了密之后的密文,那么我们就不需要调用加密函数了,直接将ecdata=”密文”和key =’www.sohu.com6666′ 扔进 aesDecrypt(key, ecdata)这个解密算法就ok,

再一次强调这个是一个关于AES的加密与解密的一个算法。

运行结果:

这样子我们理论上就能得到文字和图片了:

大家可以参考一下俺的完整代码: 我是有很多个url文章爬取的。

# 导入urllib与lxml库
import urllib.request
from lxml import etree
import re
import pandas as pd
from Crypto.Cipher import AES
import base64

# 密钥
key = 'www.sohu.com6666'

BLOCK_SIZE = 16  # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
                chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

def get_data(url):
    # 爬取网页的网址,此网址仅限于本实训使用
    url = url
    # 请求网页获取网页源码
    response=urllib.request.urlopen(url=url)
    html=response.read().decode("utf-8")
    # print(html)
    # 将文本转化为HTML元素树
    parse = etree.HTML(html)
    # 写入xpath路径
    patt=re.compile(r'<p>(.*?)</p>|data-src="(.*?)"', re.S)
    group=patt.findall(html)
    for i in range(len(group)):
        # print(group[i])
        # 输出图片
        if(group[i][0] == ""):
            # print(group[i][1])
            try:
                print(aesDecrypt(key, group[i][1]))
            except:
                continue
        # 输出文章内容
        else:
            print(group[i][0])


def get_url():
    data = pd.read_csv("1.csv", encoding="gbk")
    i = 1
    for url in data.地址URL:
        print("第"+str(i)+"篇文章:" + url)
        i += 1
        get_data(url)



def aesDecrypt(key, data):
    '''

    :param key: 密钥
    :param data: 加密后的数据(密文)
    :return:明文
    '''
    key = key.encode('utf8')
    data = base64.b64decode(data)
    cipher = AES.new(key, AES.MODE_ECB)

    # 去补位
    text_decrypted = unpad(cipher.decrypt(data))
    text_decrypted = text_decrypted.decode('utf8')
    return text_decrypted


if __name__ == '__main__':
    get_url()
    # get_data("http://www.sohu.com/a/471100252_120886")




运行结果:

再补充一下下:这个地方是一个正则表达式,提取文章内容和图片的。

patt=re.compile(r'<p>(.*?)</p>|data-src="(.*?)"', re.S)