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模拟浏览器点击,获取网页源码后,然后在源码里面获取文本内容
可以模拟点击继续阅读,但是点击加载更多不能模拟点击。
所以换了个思路,找接口文本是ajax加载的,直接模拟浏览器点击也可以获取。
每次点击加载更多,就会多出来几个接口。
接下来就是模拟接口提交的参数了。
2、获取参数
这几个参数可以直接在网页源码里面获取,并不是很困难。
直接搜索md5sum,可以看到参数。
刚刚在获取接口筛选的时候就是筛选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参数:
这个参数是每页的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)