龟仔龟龟 发表于 2020-2-22 19:21

用python爬取限时免费开放的全部的高教社文科类教材资源

本帖最后由 龟仔龟龟 于 2020-2-27 18:54 编辑

## 前言
最近学习了**Python** , 看到悬赏板块有坛友求批量下载
https://www.52pojie.cn/forum.php?mod=viewthread&tid=1112761&extra=page%3D1%26filter%3Dspecialtype%26specialtype%3Dreward
资源地址:
https://ct.hep.com.cn/public/page/wk.html
于是本着练习的目的实现了上述功能,下面贴上代码,本人刚学没多久,如觉得代码简陋,请勿喷,最好能提些意见供大家学习。

## 代码

```python
#!/usr/bin/python3
#演示平台Windows10
#Mac、Linux系统请自行更改目录

import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import os
import time

#资料保存的根目录
root = 'F:\\book\\'

#构造浏览器访问头
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36",
         "Referer":"https://ct.hep.com.cn/"}

#创建一个列表
#存储资料一级下载地址(因为会有两个302跳转)
resource_urls = []
for i in range(25,1151,25):
   
    # 这些数字是通过分析得来的
    # URL的构造同理(开发者控制台分析)
    resource_url = 'https://ct.hep.com.cn/public/page/wk-listData.html?' + \
      'pageConfig=%257B%2522start%2522%253A' + str(i) + \
      '%252C%2522limit%2522%253A25%252C%2522condition%2522%253A%255B%255D%257D'
    resource_urls.append(resource_url)

#创建两个列表
#分别存储二级下载地址和书名
download_urls = []
book_names = []      

for resource_url in resource_urls:

    #提取页面信息
    r = requests.get(url = resource_url, headers = headers)
    r.encoding = r.apparent_encoding
    soup = BeautifulSoup(r.text, 'lxml')
    name = soup

    #进一步提取信息
    soup = soup.find_all('div', 'col-lg-2 col-md-2 col-sm-6 col-xs-6 btnDown')
    names = name.find_all('div', 'col-lg-6 col-md-6 col-sm-12 col-xs-12')
   
    for name in names:
      book_names.append(name.get_text())

    #从一级下载界面提取URL
    for elem in soup:
      elem = elem.find('a')
      elem = elem.get('href')
      
      #转换为我们需要的最终下载URL
      sep = elem.split('/')
      complete_url = 'http://2d.hep.com.cn/api/v1/pan/resources/' + sep[-2] + '/download'
      download_urls.append(complete_url)
               
#分别下载资料
for i in range(len(book_names)):

    #path为资料完整路径
    path = root + book_names + '.rar'
    if not os.path.exists(root):
      os.mkdir(root)
    if not os.path.exists(path):
      print(book_names + '下载中')
      try:
            #构造随机浏览器访问头
            ua = UserAgent()
            ua = ua.random
            headers = {"User-Agent":ua, "Referer":"https://ct.hep.com.cn/"}
            res = requests.get(url = download_urls, headers = headers)
            if (res.status_code == 200):
                with open(path, 'wb') as f:
                  f.write(res.content)
                  print(book_names + '下载完毕\n')
                  time.sleep(5)
            else:
                print(book_names + '下载失败')
      except Exception:
            pass                  
```

**刚才添加了休眠时间,防止请求过快,会封IP,一次没下完,下次运行可以接着**
**第一部分(1-300)打包下载**: https://csueducn-my.sharepoint.com/personal/bobmaster_csu_edu_cn/_layouts/52/download.aspx?share=ERFpStkcTC1Hu0FybkRuU7QBnN7ZgvwzVqtsp21ZO-m8bg

**第二部分(301-600)打包下载**:https://csueducn-my.sharepoint.com/personal/bobmaster_csu_edu_cn/_layouts/52/download.aspx?share=EeH28z_N6rhArnwN_YmOOqIB8FQidtIWCRyY1gP6yno1Ng
**后面部分自行改代码,服务器空间不够了,你们就把for i in range(len(book_names)):改为for i in range(600.len(book_names)):**
**为了方便大家使用,我将程序打包成了可执行文件**
**对于想自己批量下载的,我将提取链接的代码贴在了(https://www.52pojie.cn/forum.php?mod=redirect&goto=findpost&ptid=1113195&pid=30185680)楼**
windows: https://fly.myroad.fun/software/win/python_spider.exe
macOS: https://fly.myroad.fun/software/mac/python_spider
## 效果图

badyun 发表于 2020-2-23 10:37

本帖最后由 badyun 于 2020-2-23 10:39 编辑

嗯。。。那个悬赏帖子里面的json是我贴出来的,不过我取得方法跟你不太一样,你前面解析步骤多了,造成请求次数多了

我代码一共这么多

    let s = await superagent.post('https://ct.hep.com.cn/public/page/wk-listData.html')
      .type('form')
      .send({
            pageConfig: encodeURI(JSON.stringify({ "start": 0, "limit": 2000, "condition": [] }))
      })
    let $ = cheerio.load(s.text)
    let e = []
    $('.row').each((i, ele) => {
      e.push({
            title: $(ele).find('.col-xs-12').text(),
            name: $(ele).find('.name').text(),
            path: 'http://2d.hep.com.cn/api/v1/pan/resources/' + $(ele).find('a').attr('href').replace('/download', '').replace('http://www.hep.com.cn/pan/r/', '') + '/download'
      })
    })
    fs.writeFileSync('./book.json', JSON.stringify(e, null, '\t'))


他post请求的pageConfig的参数通过url解码可以获取到一个json对象,

里面start关键字是起始项,limit是一页多少个。

而他总个数是1162条,

所以直接start为0,limit为任何一个大于等于1162的数,就可以获取到所有书籍链接


龟仔龟龟 发表于 2020-2-24 21:52

本帖最后由 龟仔龟龟 于 2020-2-24 21:56 编辑

will113 发表于 2020-2-24 20:46
大佬来一个。
对于批量下载很简单啊,就简单改一下代码,把代码后面的下载文件部分删掉,添加一个保存下载链接的操作就可以了
#!/usr/bin/python3
#演示平台Windows10
#Mac、Linux系统请自行更改目录

import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import os
import time

#资料保存的根目录
root = 'F:\\book\\'

#构造浏览器访问头
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36",
         "Referer":"https://ct.hep.com.cn/"}

#创建一个列表
#存储资料一级下载地址(因为会有两个302跳转)
resource_urls = []
for i in range(25,1151,25):

    # 这些数字是通过分析得来的
    # URL的构造同理(开发者控制台分析)
    resource_url = 'https://ct.hep.com.cn/public/page/wk-listData.html?' + \
      'pageConfig=%257B%2522start%2522%253A' + str(i) + \
      '%252C%2522limit%2522%253A25%252C%2522condition%2522%253A%255B%255D%257D'
    resource_urls.append(resource_url)

#创建两个列表
#分别存储二级下载地址和书名
download_urls = []
book_names = []      

for resource_url in resource_urls:

    #提取页面信息
    r = requests.get(url = resource_url, headers = headers)
    r.encoding = r.apparent_encoding
    soup = BeautifulSoup(r.text, 'html.parser')
    name = soup

    #进一步提取信息
    soup = soup.find_all('div', 'col-lg-2 col-md-2 col-sm-6 col-xs-6 btnDown')
    names = name.find_all('div', 'col-lg-6 col-md-6 col-sm-12 col-xs-12')

    for name in names:
      book_names.append(name.get_text())

    #从一级下载界面提取URL
    for elem in soup:
      elem = elem.find('a')
      elem = elem.get('href')

      #转换为我们需要的最终下载URL
      sep = elem.split('/')
      complete_url = 'http://2d.hep.com.cn/api/v1/pan/resources/' + sep[-2] + '/download'
      download_urls.append(complete_url)

#保存下载链接,方便用IDM批量下载
with open('url.txt', 'w', encoding='utf-8') as f:
    for url in download_urls:
      f.write(url + '\n')
    f.close()



#分别下载资料
#for i in range(len(book_names)):

#    #path为资料完整路径
#    path = root + book_names + '.rar'
#    if not os.path.exists(root):
#      os.mkdir(root)
#    if not os.path.exists(path):
#      print(book_names + '下载中')
#      try:
#            #构造随机浏览器访问头
#            ua = UserAgent()
#            ua = ua.random
#            headers = {"User-Agent":ua, "Referer":"https://ct.hep.com.cn/"}
#            res = requests.get(url = download_urls, headers = headers)
#            if (res.status_code == 200):
#                with open(path, 'wb') as f:
#                  f.write(res.content)
#                  f.close()
#                   print(book_names + '下载完毕\n')
#                  time.sleep(5)
#            else:
#                print(book_names + '下载失败')
#      except Exception:
#            pass   


为了方便大家使用,我将程序打包成了可执行文件
windows: https://fly.myroad.fun/software/win/python_spider.exe
macOS: https://fly.myroad.fun/software/mac/python_spider

top倷 发表于 2020-2-22 20:18

马了等于看了

ligxi 发表于 2020-2-26 00:54

本帖最后由 ligxi 于 2020-2-26 01:30 编辑

本来想请问一下楼主,关于这个真实链接"http://2d.hep.com.cn/api/v1/pan/resources/+参数",是在什么地方找到的?
刚刚又去找了一下,原来我忘记看下载文件时的消息头了{:301_1007:}看来我找的还是不够仔细啊!还是得多学习交流,这下可以安心睡觉了{:1_900:}


龟仔龟龟 发表于 2020-2-22 19:54

cocococ 发表于 2020-2-22 19:41
下载了也不会看系列,还是节约网络资源咯,别爬瘫痪了
请求过快会被封Ip的,所以控制了下速度,添加了休眠~~~
也对,关键是用到刀口上。

卫国 发表于 2020-2-22 19:58

Python简单易学,胶水语言

ice-cream 发表于 2020-2-22 19:59

good。。。。

lihaisanhui 发表于 2020-2-22 20:01

龟仔龟龟 发表于 2020-2-22 19:54
请求过快会被封Ip的,所以控制了下速度,添加了休眠~~~
也对,关键是用到刀口上。

fake_useragent库 随机用户代{过}{滤}理(每次都不一样)这样爬小型网站就不会被封了

tomemouse 发表于 2020-2-22 20:01

Python简单易学,胶水语言{:1_913:}

龟仔龟龟 发表于 2020-2-22 20:02

lihaisanhui 发表于 2020-2-22 20:01
fake_useragent库 随机用户代{过}{滤}理(每次都不一样)这样爬小型网站就不会被封了

问题是,是IP被封,应该有限制单ip的请求频率~~~我后面是挂了代{过}{滤}理才发现这个问题的

hshcompass 发表于 2020-2-22 20:17

下载了也不会看系列,还是节约网络资源咯,别爬瘫痪了

lihaisanhui 发表于 2020-2-22 20:18

龟仔龟龟 发表于 2020-2-22 20:02
问题是,是IP被封,应该有限制单ip的请求频率~~~我后面是挂了代{过}{滤}理才发现这个问题的

有没有随机换IP的办法?
页: [1] 2 3 4 5 6 7 8
查看完整版本: 用python爬取限时免费开放的全部的高教社文科类教材资源