51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 2004|回复: 0
打印 上一主题 下一主题

一文谈谈我对Python爬虫的理解(2)

[复制链接]
  • TA的每日心情
    无聊
    昨天 09:19
  • 签到天数: 933 天

    连续签到: 5 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2021-10-20 14:53:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    怎么写爬虫
      网页世界多姿多彩、亿万网页资源供你选择,面对不同的页面,怎么使自己编写的爬虫程序够稳健、持久,这是一个值得讨论的问题。
      俗话说,磨刀不误砍柴工,在开始编写爬虫之前,很有必要掌握一些基本知识:
      ·网页的结构是HTML,爬虫的目标就是解析HTML,获取目标字段并保存
      ·客户端展现的网页由浏览器渲染,客户端和服务端的信息交互依靠HTTP协议
      这两句描述体现了一名爬虫开发人员需要掌握的基本知识,不过一名基本的后端或者前端工程师都会这些哈哈,这也说明了爬虫的入门难度极低,从这两句话,你能思考出哪些爬虫必备的知识点呢?
      ·基本的HTML知识,了解HTML才方便目标信息提取
      ·基本的JS知识 ,JS可以异步加载HTML
      ·了解CSS Selector、XPath以及正则,目的是为了提取数据
      ·了解HTTP协议,为后面的反爬虫斗争打下基础
      ·了解基本的数据库操作,为了数据持久化
      有了这些知识储备,接下来就可以选择一门语言,开始编写自己的爬虫程序了,还是按照上一节说的三个步骤,然后以Python为例,说一说要在编程语言方面做那些准备:
      ·网页请求:内置有urllib库,第三方库的话,同步请求可以使用requests,异步请求使用aiohttp
      ·分析HTML结构并提取目标元素:CSS Selector和XPath是目前主流的提取方式,第三方库可以使用Beautiful Soup或者PyQuery
      ·数据持久化:目标数据提取之后,可以将数据保存到数据库中进行持久化,MySQL、MongoDB等,这些都有对应的库支持,当然你也可以保存在硬盘,谁硬盘没点东西对吧(滑稽脸)
      掌握了上面这些,你大可放开手脚大干一场,万维网就是你的名利场,去吧~
      我觉得对于一个目标网站的网页,可以分下面四个类型:
      ·单页面单目标
      ·单页面多目标
      ·多页面单目标
      ·多页面多目标
      具体是什么意思呢,可能看起来有点绕,但明白这些,你之后写爬虫,只要在脑子里面过一遍着网页对应什么类型,然后套上对应类型的程序(写多了都应该有一套自己的常用代码库),那写爬虫的速度,自然不会慢!

      单页面单目标
      通俗来说,就是在这个网页里面,我们的目标就只有一个,假设我们的需求是抓取这部 电影-肖申克的救赎 的名称,首先打开网页右键审查元素,找到电影名称对应的元素位置,如下图所示:

    在某个单一页面内,看目标是不是只有一个,一眼就能看出标题的CSS Selector规则为:#content > h1 > span:nth-child(1),然后用我自己写的常用库,我用不到十行代码就能写完抓取这个页面电影名称的爬虫:
    1. import asyncio

    2. from ruia import Item, TextField

    3. class DoubanItem(Item):
    4.     title = TextField(css_select='#content > h1 > span:nth-child(1)')

    5. async_func = DoubanItem.get_item(url="https://movie.douban.com/subject/1292052/")
    6. item = asyncio.get_event_loop().run_until_complete(async_func)
    7. print(item.title)
    复制代码
    多页面多目标就是此情况下多个url的衍生情况。

      单页面多目标
      假设现在的需求是抓取 豆瓣电影250 第一页中的所有电影名称,你需要提取25个电影名称,因为这个目标页的目标数据是多个item的,因此目标需要循环获取,这就是所谓的单页面多目标了:

    1. import asyncio

    2. from ruia import Item, TextField

    3. class DoubanItem(Item):
    4.     target_item = TextField(css_select='div.item')
    5.     title = TextField(css_select='span.title')

    6.     async def clean_title(self, title):
    7.         if isinstance(title, str):
    8.             return title
    9.         else:
    10.             return ''.join([i.text.strip().replace('\xa0', '') for i in title])


    11. async_func = DoubanItem.get_items(url="https://movie.douban.com/top250")
    12. items = asyncio.get_event_loop().run_until_complete(async_func)
    13. for item in items:
    14.     print(item)
    复制代码
    多页面多目标
      多页面多目标是上述单页面多目标情况的衍生,在这个问题上来看,此时就是获取所有分页的电影名称:

    1. from ruia import TextField, Item, Request, Spider


    2. class DoubanItem(Item):
    3.     """
    4.     定义爬虫的目标字段
    5.     """
    6.     target_item = TextField(css_select='div.item')
    7.     title = TextField(css_select='span.title')

    8.     async def clean_title(self, title):
    9.         if isinstance(title, str):
    10.             return title
    11.         else:
    12.             return ''.join([i.text.strip().replace('\xa0', '') for i in title])


    13. class DoubanSpider(Spider):
    14.     start_urls = ['https://movie.douban.com/top250']
    15.     concurrency = 10

    16.     async def parse(self, res):
    17.         etree = res.html_etree
    18.         pages = ['?start=0&filter='] + [i.get('href') for i in etree.cssselect('.paginator>a')]

    19.         for index, page in enumerate(pages):
    20.             url = self.start_urls[0] + page
    21.             yield Request(
    22.                 url,
    23.                 callback=self.parse_item,
    24.                 metadata={'index': index},
    25.                 request_config=self.request_config
    26.             )

    27.     async def parse_item(self, res):
    28.         items_data = await DoubanItem.get_items(html=res.html)
    29.         res_list = []
    30.         for item in items_data:
    31.             res_list.append(item.title)
    32.         return res_list


    33. if __name__ == '__main__':
    34.     DoubanSpider.start()
    复制代码
    如果网络没问题的话,会得到如下输出:

    注意爬虫运行时间,1s不到,这就是异步的魅力。
      用Python写爬虫,就是这么简单优雅,诸位,看着网页就思考下:
      ·是什么类型的目标类型
      ·用什么库模拟请求
      ·怎么解析目标字段
      ·怎么存储
      一个爬虫程序就成型了,顺便一提,爬虫这东西,可以说是防君子不防小人,robots.txt大部分网站都有(它的目的是告诉爬虫什么可以爬取什么不可以爬取,比如:https://www.baidu.com/robots.txt),各位想怎么爬取,自己衡量。



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-4-20 05:26 , Processed in 0.065954 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表