欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python爬取百度文库

程序员文章站 2022-07-03 21:03:49
...

Python爬取百度文库

爬取网址:https://wenku.baidu.com/view/aa31a84bcf84b9d528ea7a2c.html

1、分析爬取的接口

直接分析手机版的接口:https://wk.baidu.com/view/aa31a84bcf84b9d528ea7a2c?pcf=2&pcf=2&pcf=2&pcf=2&pcf=2
一开始用selenium模拟浏览器点击,获取网页源码后,然后在源码里面获取文本内容
Python爬取百度文库
可以模拟点击继续阅读,但是点击加载更多不能模拟点击。
Python爬取百度文库
所以换了个思路,找接口文本是ajax加载的,直接模拟浏览器点击也可以获取。
Python爬取百度文库
每次点击加载更多,就会多出来几个接口。
接下来就是模拟接口提交的参数了。
Python爬取百度文库

2、获取参数

这几个参数可以直接在网页源码里面获取,并不是很困难。
直接搜索md5sum,可以看到参数。
Python爬取百度文库
刚刚在获取接口筛选的时候就是筛选7210afedd7358a5bd48649cf6dad0de5这个参数

    response = requests.get(url, headers=headers).text
    result = re.search(
        r'&md5sum=(.*)&sign=(.*)&rtcs_flag=(.*)&rtcs_ver=(.*?)".*rsign":"(.*?)",', response, re.M | re.I)  # 寻找参数
    reader = {
        "md5sum": result.group(1),
        "sign": result.group(2),
        "rtcs_flag": result.group(3),
        "rtcs_ver": result.group(4),
        "width": 176,	
        "type": "org",
        "rsign": result.group(5)
    }

还缺少三个参数,pn、rn、callback。
pn和rn的参数,是pn开始获取的页面,rn是获取几页
callback: sf_edu_wenku_retype_doc_jsonp_1_1后面的参数1,1是pn和rn。这个有限制,一次最多同时获取10页的信息,所以不能一次获取超过10页以上的页面信息。
接下来是range参数:
Python爬取百度文库
这个参数是每页的range参数的合在一块的

比如:range: 0-16174就是第一页的id
     range:16175-31688_31689-49449_49450-68119_68120-86618就是2,3,4,5页的id

所以上面的参数信息都可以获取,并且直接在网页源码里面获取。
获取参数的代码:

headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Mobile Safari/537.36"
}  # 模拟手机


def get_num(url):
    response = requests.get(url, headers=headers).text
    result = re.search(
        r'&md5sum=(.*)&sign=(.*)&rtcs_flag=(.*)&rtcs_ver=(.*?)".*rsign":"(.*?)",', response, re.M | re.I)  # 寻找参数
    reader = {
        "md5sum": result.group(1),
        "sign": result.group(2),
        "rtcs_flag": result.group(3),
        "rtcs_ver": result.group(4),
        "width": 176,	
        "type": "org",
        "rsign": result.group(5)
    }

    result_page = re.findall(
        r'merge":"(.*?)".*?"page":(.*?)}', response)  # 获取每页的标签
    doc_url = "https://wkretype.bdimg.com/retype/merge/" + url[29:-5]  # 网页的前缀
    n = 0
    for i in range(len(result_page)):  # 最大同时一次爬取10页
        if i % 10 is 0:
            doc_range = '_'.join([k for k, v in result_page[n:i]])
            reader['pn'] = n + 1
            reader['rn'] = 10
            reader['callback'] = 'sf_edu_wenku_retype_doc_jsonp_%s_10' % (
                reader.get('pn'))
            reader['range'] = doc_range
            n = i
            get_page(doc_url, reader)
    else:  # 剩余不足10页的
        doc_range = '_'.join([k for k, v in result_page[n:i + 1]])
        reader['pn'] = n + 1
        reader['rn'] = i - n + 1
        reader['callback'] = 'sf_edu_wenku_retype_doc_jsonp_%s_%s' % (
            reader.get('pn'), reader.get('rn'))
        reader['range'] = doc_range
        get_page(doc_url, reader)

3、获取信息里面的内容

直接用response获取之后是unciode格式的,要转换成中文。

def get_page(url, data):
    response = requests.get(url, headers=headers, params=data).text
    response = response.encode(
        'utf-8').decode('unicode_escape')  # unciode转为utf-8 然后转为中文
    response = re.sub(r',"no_blank":true', '', response)  # 清洗数据
    result = re.findall(r'c":"(.*?)"}', response)  # 寻找文本匹配
    result = '\n'.join(result)
    print(result)

完整的源码

import requests
import re
import json
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Mobile Safari/537.36"
}  # 模拟手机


def get_num(url):
    response = requests.get(url, headers=headers).text
    result = re.search(
        r'&md5sum=(.*)&sign=(.*)&rtcs_flag=(.*)&rtcs_ver=(.*?)".*rsign":"(.*?)",', response, re.M | re.I)  # 寻找参数
    reader = {
        "md5sum": result.group(1),
        "sign": result.group(2),
        "rtcs_flag": result.group(3),
        "rtcs_ver": result.group(4),
        "width": 176,	
        "type": "org",
        "rsign": result.group(5)
    }

    result_page = re.findall(
        r'merge":"(.*?)".*?"page":(.*?)}', response)  # 获取每页的标签
    doc_url = "https://wkretype.bdimg.com/retype/merge/" + url[29:-5]  # 网页的前缀
    n = 0
    for i in range(len(result_page)):  # 最大同时一次爬取10页
        if i % 10 is 0:
            doc_range = '_'.join([k for k, v in result_page[n:i]])
            reader['pn'] = n + 1
            reader['rn'] = 10
            reader['callback'] = 'sf_edu_wenku_retype_doc_jsonp_%s_10' % (
                reader.get('pn'))
            reader['range'] = doc_range
            n = i
            get_page(doc_url, reader)
    else:  # 剩余不足10页的
        doc_range = '_'.join([k for k, v in result_page[n:i + 1]])
        reader['pn'] = n + 1
        reader['rn'] = i - n + 1
        reader['callback'] = 'sf_edu_wenku_retype_doc_jsonp_%s_%s' % (
            reader.get('pn'), reader.get('rn'))
        reader['range'] = doc_range
        get_page(doc_url, reader)


def get_page(url, data):
    response = requests.get(url, headers=headers, params=data).text
    response = response.encode(
        'utf-8').decode('unicode_escape')  # unciode转为utf-8 然后转为中文
    response = re.sub(r',"no_blank":true', '', response)  # 清洗数据
    result = re.findall(r'c":"(.*?)"}', response)  # 寻找文本匹配
    result = '\n'.join(result)
    print(result)

if __name__ == '__main__':
    url = "https://wenku.baidu.com/view/aa31a84bcf84b9d528ea7a2c.html"
    get_num(url)