会员可以在此提问,百战程序员老师有问必答
对大家有帮助的问答会被标记为“推荐”
看完课程过来浏览一下别人提的问题,会帮你学得更全面
截止目前,同学们一共提了 132647个问题
Python 全系列/第十六阶段:Python 爬虫开发/爬虫基础(旧) 646楼
Python 全系列/第十六阶段:Python 爬虫开发/移动端爬虫开发- 647楼

from bs4 import BeautifulSoup
import bs4
import requests


# 获取网页内容

def get_html_text(url):
    try:
        head = {'User-Agent': 'Chrome/10'}
        r = requests.get(url, headers=head)
        r.raise_for_status
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ''


# 解析网页内容,保存到列表中

def save_to_list(lst, html):
    soup = BeautifulSoup(html, 'html.parser')
    for tr in soup('tbody')[0].children:
       if isinstance(tr,bs4.element.Tag):
           tds=tr('td')
           lst.append([tds[0].text, tds[1].text, tds[2].text, tds[3].text])


# 打印排名内容

def print_info(lst, start_num,end_num):
    for i in range(start_num,end_num+1):
        u = lst[i]
        # print(ulist)
        print("{0:^15}{1:^15}{2:^15}{3:^15}".format(u[0],u[1],u[2],u[3]))
def main():
    url = 'https://www.dxsbb.com/news/46725.html'
    lst = []
    html = get_html_text(url)
    save_to_list(lst,html)
    print_info(lst,0,100)


if __name__ == '__main__':
    main()
    
 老师,这是一个获取大学排名的定向爬虫,有个问题,就是输出来的内容不对齐,请问怎么处理?如下所示请问怎么处理?

输入内容如下:

 排名             名称             所在地           生源质量分     

       1            清华大学            北京             100      

       2            北京大学            北京            96.4      

       3          中国科学技术大学          安徽            92.1      

       4            复旦大学            上海            91.5      

       5           中国人民大学           北京            90.8      

       6           上海交通大学           上海            90.5      

       7            南京大学            江苏            88.4      

       8            同济大学            上海             87       

       9            浙江大学            浙江            86.3      

      10           上海财经大学           上海            86.2      

      11            南开大学            天津            85.9      

      12          北京航空航天大学          北京            85.4      

      13           中央财经大学           北京            85.2      

      14           北京师范大学           北京            85.1      

      15            武汉大学            湖北            84.4      

      16          对外经济贸易大学          北京            84.2      

      17           西安交通大学           陕西            83.6      

      18            天津大学            天津            82.5      

      19           华中科技大学           湖北            82.4      

      20           北京理工大学           北京            82.1      

      21            东南大学            江苏            81.8      

      22           北京外国语大学          北京            81.8      

      23            中山大学            广东            81.1      

      24           中国政法大学           北京            80.8      

      25           华东师范大学           上海            79.4      

      26           哈尔滨工业大学          黑龙江           78.2      

      27           北京邮电大学           北京            78.2      

      28            厦门大学            福建            77.9      

      29           上海外国语大学          上海            77.5      

      30           西北工业大学           陕西            77.1      

      31           西南财经大学           四川            76.6      

      32            中南大学            湖南             76       

      33           大连理工大学           辽宁            75.8      

      34           中国传媒大学           北京            75.8      

      35            四川大学            四川            75.7      

      36           电子科技大学           四川            75.4      

      37          中南财经政法大学          湖北            75.1      

      38           华南理工大学           广东            74.8      

      39            吉林大学            吉林            74.4      

      40          南京航空航天大学          江苏            74.4      

      41            湖南大学            湖南            74.2      

      42            重庆大学            重庆            73.8      

      43           北京科技大学           北京            73.8      

      44           北京交通大学           北京            73.5      

      45            山东大学            山东            73.4      

      46           华东理工大学           上海            72.9      

      47          西安电子科技大学          陕西            72.2      

      48           天津医科大学           天津            72.1      

      49           南京理工大学           江苏            71.8      

      50           中国农业大学           北京             71       

      51           华中师范大学           湖北            70.2      

      52           中国海洋大学           山东             70       

      53           哈尔滨工程大学          黑龙江           69.8      

      54           中央民族大学           北京            69.8      

      55           华北电力大学           北京            69.7      

      56           北京中医药大学          北京            69.7      

      57            暨南大学            广东            69.6      

      58            苏州大学            江苏            69.5      

      59           武汉理工大学           湖北            69.4      

      60            东北大学            辽宁             69       

      61            兰州大学            甘肃            68.7      

      62           中国药科大学           江苏            68.4      

      63            东华大学            上海            68.2      

      64            河海大学            江苏            68.1      

      65           北京林业大学           北京             68       

      66           河北工业大学           河北            67.9      

      67           北京工业大学           北京            67.3      

      68            江南大学            江苏            67.2      

      69           北京化工大学           北京            67.1      

      70           西南交通大学           四川            66.8      

      71            上海大学            上海            66.7      

      72           南京师范大学           江苏            66.4      

      73         中国地质大学(武汉)         湖北            65.3      

      74         中国地质大学(北京)         北京            65.1      

      75            西北大学            陕西            64.6      

      76           东北师范大学           吉林            64.5      

      77            长安大学            陕西            64.4      

      78         中国矿业大学(北京)         北京             64       

      79           华中农业大学           湖北            63.7      

      80           合肥工业大学           安徽            63.7      

      81            广西大学            广西            63.5      

      82         中国石油大学(华东)         山东            63.3      

      83           陕西师范大学           陕西            63.3      

      84           南京农业大学           江苏             63       

      85           湖南师范大学           湖南            62.8      

      86            福州大学            福建            62.6      

      87           大连海事大学           辽宁            62.3      

      88          西北农林科技大学          陕西            62.1      

      89            西南大学            重庆            61.1      

      90           中国矿业大学           江苏             61       

      91            云南大学            云南            60.3      

      92           太原理工大学           山西            60.3      

      93           华南师范大学           广东             60       

      94           北京体育大学           北京             60       

      95         中国石油大学(北京)         北京            59.5      

      96            安徽大学            安徽            59.2      

      97           东北林业大学           黑龙江           58.2      

      98           东北农业大学           黑龙江            58       

      99            辽宁大学            辽宁            57.9      

      100           南昌大学            江西            52.4      


Python 全系列/第十六阶段:Python 爬虫开发/爬虫反反爬- 649楼

import requests
from fake_useragent import UserAgent
from lxml import etree
import os

def get_header():
    location = os.getcwd() + '/fake_useragent.json'
    ua = UserAgent(path=location)
    return ua.chrome

#发送请求
class Downloader():
    def do_download(self,url):
        print(url)
        hearders = {'User-Agent':get_header()}
        resp = requests.get(url,hearders=hearders)
        if resp.status_code == 200:
            resp.encoding = 'utf-8'
            return resp.text

#数据解析
class Parser():
    def do_parse(self,html):
        e = etree.HTML(html)
        contents = [div.xpath('string(.)').strip() for div in e.xpath('//div[@class="content"]')]
        urls = ['https://www.qiushibaike.com{}'.format(url) for url in e.xpath('//ul[@class="pagination"]/li/a/@href')]
        return contents,urls

#数据保存
class Dataoutput():
    def do_save(self,datas):
        with open('duanzi.txt1','a',encoding='utf-8') as f:
            for data in datas:
                f.write(data + '\n')



#url管理器
class URLManager():
    def __init__(self):
        self.new_url = set()
        self.old_url = set()
        #加入一个url
    def add_new_url(self,url):
        if url is not None and url != '' and url not in self.old_url:
            self.new_url.add(url)
        #加入多个url
    def add_new_urls(self,urls):
        for url in urls:
            self.add_new_url(url)
        #获取一个url
    def get_new_url(self):
        url = self.new_url.pop()
        self.old_url.add(url)
        return url
        #获取还有多少个url要爬取
    def get_new_url_size(self):
        return len(self.new_url)

        #获取是否还有url要爬取
    def have_new_url(self):
        return self.get_new_url_size()>0

#调度器
class Scheduler:
    def __init__(self):
        self.downloader = Downloader()
        self.parser = Parser()
        self.data_out_put = Dataoutput()
        self.url_manager = URLManager()
    def start(self,url):
        self.url_manager.add_new_url(url)
        while self.url_manager.have_new_url():
            url = self.url_manager.get_new_url()
            html = self.downloader.do_download(url)
            datas,urls = self.parser.do_parse(html)
            self.data_out_put.do_save(datas)
            self.url_manager.add_new_urls(urls)



if __name__ == '__main__':
    scheduler = Scheduler()
    url = 'https://www.qiushibaike.com/text/'
    scheduler.start(url)

image.png

老师,这个报错是哪儿有问题呢,没想明白

Python 全系列/第十六阶段:Python 爬虫开发/爬虫反反爬- 650楼
Python 全系列/第十六阶段:Python 爬虫开发/爬虫基础(旧) 656楼

import requests
from lxml import etree
from bs4 import BeautifulSoup
import re
from pyquery import PyQuery as pq


# 爬虫第一步:获取网页源代码
# 对指定url发送请求
class GetHtml(object):
    """
    接收到url后使用requests模块发送请求
    请求方式:默认get,可选择get/post
    url的参数:可选arg,默认字典类型
    """

    def __init__(self, url):
        self.url = url
        self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}

    def get_html(self, data_type='text', mode='get', arg={}, top=1):
        """如果mode为get,则准备发送get请求,判断arg是否为空来决定是否携带参数去发送请求"""
        print(f"{(int(top)-1)*'    '}正在爬取的网址是:{self.url} #################### 属于第{top}级页面")
        # 判断mode,确定发送请求的方式
        if mode == 'get':
            # 判断是否需要携带参数发送get请求
            if arg:
                # 携带参数发送get请求
                response = requests.get(url=self.url, headers=self.headers, params=arg)
            else:
                # 未携带参数发送get请求
                response = requests.get(url=self.url, headers=self.headers)
        # 判断mode,确定发送请求的方式
        elif mode == 'post':
            # 判断是否需要携带参数发送post请求
            if arg:
                # 携带参数发送post请求
                response = requests.post(url=self.url, headers=self.headers, data=arg)
            else:
                # 未携带参数发送post请求
                response = requests.post(url=self.url, headers=self.headers)

        # 判断http响应码是否为200, 200表示http/https请求成功
        if response.status_code == 200:
            # 判断需要返回的数据类型是否为文本格式
            if data_type == 'text':
                return response.text
            # 判断需要返回的数据类型是否为二进制格式
            elif data_type == 'content':
                return response.content
            # 判断需要返回的数据类型是否为json格式
            elif data_type == 'json':
                return response.json()


# 聚焦爬虫第二步:解析网页源代码
# 解析html并以列表的形式返回数据
class Parser(object):
    """
    传入html源码信息和相应的解析表达式,计算出对应的数据并以列表的形式返回
    必选参数:html,解析表达式ex
    解析方式默认为xpath,可选re/xpath/bs4/pyquery
    """

    def __init__(self, html, mode='xpath'):
        self.html = html
        self.mode = mode

    def parser(self, ex, flag=False, content=''):
        if self.mode == 'xpath':
            # 以xpath方式解析传入的html
            e = etree.HTML(self.html)
            data = e.xpath(ex)
        elif self.mode == 'bs4':
            # 以BeautifulSoup方式解析传入的html
            soup = BeautifulSoup(self.html, 'lxml')
            data = soup.select(ex)
        elif self.mode == 're':
            # 以正则方式解析传入的html
            data = re.findall(ex, self.html)
        elif self.mode == 'pyquery':
            # 以pyquery方式解析传入的html
            doc = pq(self.html)
            data = doc(ex)

        if flag:
            urls = []
            for i in data:
                if not i.startswith('http'):
                    url = content + i
                urls.append(i)

            return urls
        # 返回解析后的数据,数据类型为列表
        return data


# 爬虫第三步:将获取到的数据存储为文件
# 将传入的数据存储到文件中
class SaveFile(object):
    """
    将传入的数据存储到文件中
    必选参数:file_path, data
    写入模式:默认为w,可选w、a、wb等
    """
    def save(self, file_path, data, mode='w'):
        if mode == 'w' or mode == 'a':
            # 以文本格式存储传入的数据
            for date in data:
                with open(file_path, mode, encoding='utf-8') as fp:
                    fp.write(date)
        elif mode == 'wb' or mode == 'ab':
            # 以二进制格式存储传入的数据
            for date in data:
                with open(file_path, mode) as fp:
                    fp.write(data)


# 爬虫之类级别写法:第四部分——Url管理器
class UrlManager(object):
    """url管理器:收集未爬取过的url,记录已经爬取过的url,并对待爬取的url列表进行去重"""
    def __init__(self):
        self.url_num = 0
        self.urls = []
        self.old_urls = []

    # url去重
    def remove_duplicates(self, urls):
        """除去urls中重复的值"""
        # 用来存储处理后的每一个url
        list1 = []

        # 使用切片创建urls的副本,避免循环中删除urls的值后导致列表索引超出的错误
        for i in urls[::]:
            # 判断i是否已经在list1列表里了
            if i not in list1:
                # 如果i不在list1里面,则将i添加到list1里面
                list1.append(i)
                # 将查找并处理后的i从urls里删除
                urls.remove(i)

        # 返回处理后的urls,数据类型:列表

        return list1

    # 添加单个url到待爬的url列表中
    def add_url(self, url):
        """将传入的url添加到待爬的url列表中"""
        # 传入的url不能在已经爬取过的url列表中,也不能在还未爬取过的url的列表中
        if url not in self.old_urls and url not in self.urls:
            # 如果出入的url符合条件,则将传入的url添加到待爬取的url列表中
            self.urls.append(url)
            # 添加完url后将待爬取的url的数量+1
            self.url_num += 1

    # 添加多个url到待爬取的url列表中
    def add_urls(self, urls):
        """将传入的多个url去重并添加到待爬取的url列表中"""
        # 调用方法对传入的多个url进行去重处理
        urls = self.remove_duplicates(urls)
        for url in urls:
            # 使用循环逐个调用方法添加url到待爬取的url列表中
            self.add_url(url)

    # 从待爬取的url列表中拿出一个url
    def get_url(self):
        """从待爬取的url列表中获取一个url,并对url是否已经爬取了做记录"""
        # 如果还有未爬取过的url,取出待爬取的url列表中的第一个url,并从待爬取的url列表中删除该url
        if self.urls:
            url = self.urls.pop(0)
            # 将待爬取的url列表中url的总数量减1
            self.url_num -= 1
            # 如果已爬取过的url列表中没有url,那么将url添加到已爬取过的url列表中
            if url not in self.old_urls:
                self.old_urls.append(url)

        return url


# 爬虫之类级别写法:第五部分——调度器
class Spider(object):
    def __init__(self, url):
        self.url = url
        self.url_manager = UrlManager()

    def start(self, content=''):
        self.url_manager.add_url(self.url)
        url = self.url_manager.get_url()
        get_html = GetHtml(url)
        html = get_html.get_html('text', 'get', arg={}, top=1)
        ex = '//ul[@id="pins"]/li/a/@href'
        parse = Parser(html=html, mode='xpath')
        urls = parse.parser(ex, True)
        self.url_manager.add_urls(urls)
        save = SaveFile()
        img_num = 1
        while self.url_manager.url_num:
            url = self.url_manager.get_url()
            get_html = GetHtml(url)
            html = get_html.get_html('text', 'get', top=2)
            parse = Parser(html)
            if len(self.url_manager.old_urls) < 24:
                max_num = parse.parser('//div[@class="pagenavi"]/a[last()-1]/span/text()')[0]
                for i in range(1, int(max_num)):
                    detail_url = url + f'/{i}'
                    self.url_manager.add_url(detail_url)
            else:
                src = parse.parser('//div[@class="main-image"]/p/a/img/@src')[0]
                get_data = GetHtml(src)
                get_data.headers = {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
                    'referer': 'https://www.mzitu.com/'
                }
                img_data = get_data.get_html('content', 'get', top=3)
                file_path = f'./image文件/meizi/{img_num}' + '.jpg'
                save.save(file_path, img_data, mode='wb')
                img_num += 1


if __name__ == "__main__":
    # url = 'https://www.qiushibaike.com/text/'
    url = 'https://www.mzitu.com/'
    spider = Spider(url)
    spider.start()

老师,我根据视频写了一个类似框架的爬虫类,出了一个大问题,我用它爬取妹子图网站的时候,爬取的速度非常慢,如果是糗图百科的段子就非常快,如何优化这个问题。我用这个框架爬取十张图片的时间都够我直接写线性代码爬完一整个图集了

Python 全系列/第十六阶段:Python 爬虫开发/爬虫反反爬- 657楼

课程分类

百战程序员微信公众号

百战程序员微信小程序

©2014-2025百战汇智(北京)科技有限公司 All Rights Reserved 北京亦庄经济开发区科创十四街 赛蒂国际工业园
网站维护:百战汇智(北京)科技有限公司
京公网安备 11011402011233号    京ICP备18060230号-3    营业执照    经营许可证:京B2-20212637