「已注销」 2021-04-16 19:17 采纳率: 66.7%
浏览 221
已采纳

求助大神。Python爬取某报纸,似乎遇到传递值,爬不出内容。麻烦帮助修改代码,万分感谢。

网页其中的源代码:

<dt>本期版面导航</dt>
<div class="dd-box">
<dd>
<a class="page-name" href="index.html?date={<!-- -->{jdate}}&page={<!-- -->{pnumber}}">{<!-- -->{pnumber}}版:{<!-- -->{pname}}</a>


<dt>本版新闻列表(<span id="news-num">0</span>)</dt>
<div class="dd-box news-list">
<dd><a href="detail.html?date={<!-- -->{jdate}}&id={<!-- -->{id}}&page={<!-- -->{pageNo}}" target="_blank"><i>●</i>{<!-- -->{title}}</a></dd>

Python代码:

import requests
import bs4
import os
import datetime
import time


def fetchUrl(url):
    '''
    功能:访问 url 的网页,获取网页内容并返回
    参数:目标网页的 url
    返回:目标网页的 html 内容
    '''

    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
    }

    r = requests.get(url, headers=headers)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    return r.text


def getPageList(year, month, day):
    '''
    功能:获取当天报纸的各版面的链接列表
    参数:年,月,日
    '''
    url = 'https://www.shobserver.com/staticsg/res/html/journal/index.html?date=' + year + '-' + month + '-' + day + '&page=01'
    html = fetchUrl(url)
    bsobj = bs4.BeautifulSoup(html, 'html.parser')
    pageList = bsobj.find('div', attrs={'class': 'dd-box'}).find_all('dd')
    linkList = []

    for page in pageList:
        tempList = page.find_all('a')
        for temp in tempList:
            link = temp["href"]
            if 'index.html' in link:
                url = 'https://www.shobserver.com/staticsg/res/html/journal/' + link
        linkList.append(url)

    return linkList


def getTitleList(year, month, day, pageUrl):
    '''
    功能:获取报纸某一版面的文章链接列表
    参数:年,月,日,该版面的链接
    '''
    html = fetchUrl(pageUrl)
    bsobj = bs4.BeautifulSoup(html, 'html.parser')
    titleList = bsobj.find('div', attrs={'class': 'dd-box news-list'}).find_all('dd')
    linkList = []

    for title in titleList:
        tempList = title.find_all('a')
        for temp in tempList:
            link = temp["href"]
            if 'detail.html' in link:
                url = 'https://www.shobserver.com/staticsg/res/html/journal/' + link
        linkList.append(url)
    return linkList


def getContent(html):
    '''
    功能:解析 HTML 网页,获取新闻的文章内容
    参数:html 网页内容
    '''
    bsobj = bs4.BeautifulSoup(html, 'html.parser')

    # 获取文章 标题
    title = bsobj.find_all('div', attrs={'class': 'con-title'})
    content1 = ''
    for p1 in title:
        content1 += p1.text + '\n'
        # print(content1)

    # 获取文章 内容
    pList = bsobj.find_all('div', attrs={'class': 'txt-box'})
    content = ''
    for p in pList:
        content += p.text + '\n'
        # print(content)

    # 返回结果 标题+内容
    resp = content1 + content
    return resp


def saveFile(content, path, filename):
    '''
    功能:将文章内容 content 保存到本地文件中
    参数:要保存的内容,路径,文件名
    '''
    # 如果没有该文件夹,则自动生成
    if not os.path.exists(path):
        os.makedirs(path)

    # 保存文件
    with open(path + filename, 'w', encoding='utf-8') as f:
        f.write(content)


def download_rmrb(year, month, day, destdir):
    '''
    功能:网站 某年 某月 某日 的新闻内容,并保存在 指定目录下
    参数:年,月,日,文件保存的根目录
    '''
    pageList = getPageList(year, month, day)
    for page in pageList:
        titleList = getTitleList(year, month, day, page)
        for url in titleList:
            # 获取新闻文章内容
            html = fetchUrl(url)
            content = getContent(html)

            # 生成保存的文件路径及文件名
            temp = url.split('=')[-2].split('&')[0].split('-')
            pageNo = temp[0]
            titleNo = temp[0] if int(temp[0]) >= 10 else '0' + temp[0]
            path = destdir + '/' + year + month + day + '/'
            fileName = year + month + day + '-' + pageNo + '-' + titleNo + '.txt'

            # 保存文件
            saveFile(content, path, fileName)


if __name__ == '__main__':
    '''
    主函数:程序入口
    '''
    # 爬取指定日期的新闻
    newsDate = input('请输入要爬取的日期(格式如 20210916 ):')

    year = newsDate[0:4]
    month = newsDate[4:6]
    day = newsDate[6:8]

    download_rmrb(year, month, day, 'D:02/cqrb')
    print("爬取完成:" + year + month + day)

劳烦大神指导解决,万分感谢。

  • 写回答

5条回答 默认 最新

  • 机灵鹤 Python领域新星创作者 2021-04-19 20:12
    关注
    import requests
    import bs4
    import os
    import datetime
    import time
    import json
     
    def fetchUrl(url):
        '''
        功能:访问 url 的网页,获取网页内容并返回
        参数:目标网页的 url
        返回:目标网页的 html 内容
        '''
        headers = {
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
        }
        r = requests.get(url, headers=headers)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    
    def saveFile(content, path, filename):
        '''
        功能:将文章内容 content 保存到本地文件中
        参数:要保存的内容,路径,文件名
        '''
        # 如果没有该文件夹,则自动生成
        if not os.path.exists(path):
            os.makedirs(path)
        # 保存文件
        with open(path + filename, 'w', encoding='utf-8') as f:
            f.write(content)
    
    def download_rmrb(year, month, day, destdir):
        '''
        功能:网站 某年 某月 某日 的新闻内容,并保存在 指定目录下
        参数:年,月,日,文件保存的根目录
        '''
        url = 'https://www.shobserver.com/staticsg/data/journal/' + year + '-' + month + '-' + day + '/navi.json'
        html = fetchUrl(url)
        jsonObj = json.loads(html)
    
        for page in jsonObj["pages"]:
            pageName = page["pname"]
            pageNo = page["pnumber"]
            print(pageNo, pageName)
            for article in page["articleList"]:
                title = article["title"]
                subtitle = article["subtitle"]
                pid = article["id"]
                url = "https://www.shobserver.com/staticsg/data/journal/" + year + '-' + month + '-' + day + "/" + str(pageNo) + "/article/" + str(pid) + ".json"
                print(pid, title, subtitle)
    
                html = fetchUrl(url)
                cont = json.loads(html)["article"]["content"]
                bsobj = bs4.BeautifulSoup(cont, 'html.parser')
                content = title + subtitle + bsobj.text
                print(content)
                
                path = destdir + '/' + year + month + day + '/' + str(pageNo) + " " + pageName + "/"
                fileName = year + month + day + '-' + pageNo + '-' + str(pid) + "-" + title + '.txt'
                saveFile(content, path, fileName)
    
    if __name__ == '__main__':
        '''
        主函数:程序入口
        '''
        # 爬取指定日期的新闻
        newsDate = input('请输入要爬取的日期(格式如 20210916 ):')
        year = newsDate[0:4]
        month = newsDate[4:6]
        day = newsDate[6:8]
        download_rmrb(year, month, day, 'cqrb')
        print("爬取完成:" + year + month + day)
    

    这个网站的内容是动态加载出来的,并非人民日报那样的静态网页(就是说数据是通过其他请求获取到,然后加载到网页中的)

    我看了一下,这个要比人民日报简单一些,它的版面列表和文章列表放在了同一个请求中(人民日报每个版面要单独请求一次文章列表)

    上面的代码简单调整了一下,仅供参考

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 需要数据库运行的图片
  • ¥15 如何获取vue-video-editor?
  • ¥100 vs2019 mfc程序如何实现64*64/48*48大小的真彩色工具栏
  • ¥15 全志v3s耳机音频输出口怎么外接功放
  • ¥15 华为ensp使用基本ACL限制公司网络访问
  • ¥15 帮我做下照片上的PLC题
  • ¥15 labview2022 使用modbus报缺少依赖?
  • ¥15 谷歌地图是不是不开通结算功能,api会使用不了哦
  • ¥15 unity腾讯云对象存储机型适配
  • ¥15 求全国交通咨询模拟代码,要求如下,可以完全在dev c++运行