返回顶部
首页 > 资讯 > 精选 >如何使用Shell构建多进程的CommandlineFu爬虫
  • 154
分享到

如何使用Shell构建多进程的CommandlineFu爬虫

2023-06-16 22:06:30 154人浏览 独家记忆
摘要

小编给大家分享一下如何使用shell构建多进程的CommandlineFu爬虫,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!CommandlineFu 

小编给大家分享一下如何使用shell构建多进程的CommandlineFu爬虫,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

CommandlineFu 是一个记录脚本片段的网站,每个片段都有对应的功能说明和对应的标签。我想要做的就是尝试用 shell 写一个多进程的爬虫把这些代码片段记录在一个 org 文件中。

参数定义

这个脚本需要能够通过 -n 参数指定并发的爬虫数(默认为 CPU 核的数量),还要能通过 -f 指定保存的 org 文件路径(默认输出到 stdout)。

#!/usr/bin/env bash proc_num=$(nproc)store_file=/dev/stdoutwhile getopts :n:f: OPT; do    case $OPT in        n|+n)            proc_num="$OPTARG"            ;;        f|+f)            store_file="$OPTARG"            ;;        *)            echo "usage: ${0##*/} [+-n proc_num] [+-f org_file} [--]"            exit 2    esacdoneshift $(( OPTIND - 1 ))OPTIND=1

解析命令浏览页面

我们需要一个进程从 CommandlineFu 的浏览列表中抽取各个脚本片段的 URL,这个进程将抽取出来的 URL 存放到一个队列中,再由各个爬虫进程从进程中读取 URL 并从中抽取出对应的代码片段、描述说明和标签信息写入 org 文件中。

这里就会遇到三个问题:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 进程之间通讯的队列如何实现

  3. 如何从页面中抽取出 URL、代码片段、描述说明、标签等信息

  4. 多进程对同一文件进行读写时的乱序问题

实现进程之间的通讯队列

这个问题比较好解决,我们可以通过一个命名管道来实现:

queue=$(mktemp --dry-run)mkfifo ${queue}exec 99<>${queue}trap "rm ${queue} 2>/dev/null" EXIT
从页面中抽取想要的信息

从页面中提取元素内容主要有两种方法:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 对于简单的 html 页面,我们可以通过 sedgrepawk 等工具通过正则表达式匹配的方式来从 HTML 中抽取信息。

  3. 通过 html-xml-utils 工具集中的 hxselect 来根据 CSS 选择器提取相关元素。

这里我们使用 html-xml-utils 工具来提取:

function extract_views_from_browse_page(){    if [[ $# -eq 0 ]];then        local html=$(cat -)    else        local html="$*"    fi    echo ${html} |hxclean |hxselect -c -s "\n" "li.list-group-item > div:nth-child(1) > div:nth-child(1) > a:nth-child(1)::attr(href)"|sed 's@^@https://www.commandlinefu.com/@'} function extract_nextpage_from_browse_page(){    if [[ $# -eq 0 ]];then        local html=$(cat -)    else        local html="$*"    fi    echo ${html} |hxclean |hxselect -s "\n" "li.list-group-item:nth-child(26) > a"|grep '>'|hxselect -c "::attr(href)"|sed 's@^@Https://www.commandlinefu.com/@'}

这里需要注意的是:hxselect 对 HTML 解析时要求遵循严格的 XML 规范,因此在用 hxselect 解析之前需要先经过 hxclean 矫正。另外,为了防止 HTML 过大,超过参数列表长度,这里允许通过管道的形式将  HTML 内容传入。

循环读取下一页的浏览页面,不断抽取代码片段 URL 写入队列

这里要解决的是上面提到的第三个问题: 多进程对管道进行读写时如何保障不出现乱序? 为此,我们需要在写入文件时对文件加,然后在写完文件后对文件解锁,在 shell 中我们可以使用 flock 来对文件进行枷锁。 关于 flock 的使用方法和注意事项,请参见另一篇博文 linux shell flock 文件锁的用法及注意事项。

由于需要在 flock 子进程中使用函数 extract_views_from_browse_page,因此需要先导出该函数:

export -f extract_views_from_browse_page

由于网络问题,使用 curl 获取内容可能失败,需要重复获取:

function fetch(){    local url="$1"    while ! curl -L ${url} 2>/dev/null;do        :    done}

collector 用来从种子 URL 中抓取待爬的 URL,写入管道文件中,写操作期间管道文件同时作为锁文件:

function collector(){    url="$*"    while [[ -n ${url} ]];do        echo "从$url中抽取"        html=$(fetch "${url}")        echo "${html}"|flock ${queue} -c "extract_views_from_browse_page >${queue}"        url=$(echo "${html}"|extract_nextpage_from_browse_page)    done    # 让后面解析代码片段的爬虫进程能够正常退出,而不至于被阻塞.    for ((i=0;i<${proc_num};i++))    do        echo >${queue}    done}

这里要注意的是, 在找不到下一页 URL 后,我们用一个 for 循环往队列里写入了 =proc_num= 个空行,这一步的目的是让后面解析代码片段的爬虫进程能够正常退出,而不至于被阻塞。

解析脚本片段页面

我们需要从脚本片段的页面中抽取标题、代码片段、描述说明以及标签信息,同时将这些内容按 org 模式的格式写入存储文件中。

  function view_page_handler()  {      local url="$1"      local html="$(fetch "${url}")"      # headline      local headline="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > h2:nth-child(1)")"      # command      local command="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > div:nth-child(2) > span:nth-child(2)"|pandoc -f html -t org)"      # description      local description="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > div.description"|pandoc -f html -t org)"      # tags      local tags="$(echo ${html} |hxclean |hxselect -c -s ":" ".functions > a")"      if [[ -n "${tags}" ]];then          tags=":${tags}"      fi      # build org content      cat <<EOF |flock -x ${store_file} tee -a ${store_file}* ${headline}      ${tags} :PROPERTIES::URL:       ${url}:END: ${description}#+begin_src shell${command}#+end_src EOF  }

这里抽取信息的方法跟上面的类似,不过代码片段和描述说明中可能有一些 HTML 代码,因此通过 pandoc 将之转换为 org 格式的内容。

注意***输出 org 模式的格式并写入存储文件中的代码不要写成下面这样:

    flock -x ${store_file} cat <<EOF >${store_file}    * ${headline}\t\t ${tags}    ${description}    #+begin_src shell    ${command}    #+end_srcEOF

它的意思是使用 flock 对 cat 命令进行加锁,再把 flock 整个命令的结果通过重定向输出到存储文件中,而重定向输出的这个过程是没有加锁的。

spider 从管道文件中读取待抓取的 URL,然后实施真正的抓取动作。

function spider(){    while :    do        if ! url=$(flock ${queue} -c 'read -t 1 -u 99 url && echo $url')        then            sleep 1            continue        fi         if [[ -z "$url" ]];then            break        fi        view_page_handler ${url}    done}

这里要注意的是,为了防止发生死锁,从管道中读取 URL 时设置了超时,当出现超时就意味着生产进程赶不上消费进程的消费速度,因此消费进程休眠一秒后再次检查队列中的 URL。

组合起来

collector "https://www.commandlinefu.com/commands/browse" & for ((i=0;i<${proc_num};i++))do    spider &donewait

抓取其他网站

通过重新定义 extract_views_from_browse_pageextract_nextpage_from-browse_pageview_page_handler 这几个函数, 以及提供一个新的种子 URL,我们可以很容易将其改造成抓取其他网站的多进程爬虫。

例如通过下面这段代码,就可以用来爬取 xkcd 上的漫画:

function extract_views_from_browse_page(){    if [[ $# -eq 0 ]];then        local html=$(cat -)    else        local html="$*"    fi    max=$(echo "${html}"|hxclean |hxselect -c -s "\n" "#middleContainer"|grep "Permanent link to this comic" |awk -F "/" '{print $4}')    seq 1 ${max}|sed 's@^@https://xkcd.com/@'} function extract_nextpage_from_browse_page(){    echo ""} function view_page_handler(){    local url="$1"    local html="$(fetch "${url}/")"    local image="https:$(echo ${html} |hxclean |hxselect -c -s "\n" "#comic > img:nth-child(1)::attr(src)")"    echo ${image}    wget ${image}} collector "https://xkcd.com/" &

以上是“如何使用Shell构建多进程的CommandlineFu爬虫”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: 如何使用Shell构建多进程的CommandlineFu爬虫

本文链接: https://www.lsjlt.com/news/285657.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何使用Shell构建多进程的CommandlineFu爬虫
    小编给大家分享一下如何使用Shell构建多进程的CommandlineFu爬虫,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!CommandlineFu ...
    99+
    2023-06-16
  • Python爬虫进阶之如何使用urllib库
    这篇文章主要介绍了Python爬虫进阶之如何使用urllib库,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。python的数据类型有哪些python的数据类型:1. 数字类型...
    99+
    2023-06-14
  • 如何使用ip代理池进行爬虫
    这篇文章主要讲解了“如何使用ip代理池进行爬虫”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用ip代理池进行爬虫”吧!1、使用前需要做一个测试,就是测试这个ip是否有效。方法是用cur...
    99+
    2023-06-20
  • python3爬虫中多线程的使用示例
    这篇文章主要介绍了python3爬虫中多线程的使用示例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。本文教程操作环境:windows7系统、Python 3.9.1,DELL...
    99+
    2023-06-14
  • 如何使用PHP编写爬虫程序
    在互联网时代,信息就像一条无休无止的河流,源源不断地涌出来。有时候我们需要从Web上抓取一些数据,以便分析或者做其他用途。这时候,爬虫程序就显得尤为重要。爬虫程序,顾名思义,就是用来自动化地获取Web页面内容的程序。 作为一门广泛应用的编程...
    99+
    2023-09-03
    php 爬虫 开发语言
  • 如何分析Python多线程在爬虫中的应用
    本篇文章为大家展示了如何分析Python多线程在爬虫中的应用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。作为测试工程师经常需要解决测试数据来源的问题,解决思路无非是三种:直接从生产环境拷贝真实数据...
    99+
    2023-06-04
  • 详解如何利用Nodejs构建多进程应用
    目录前言进程的创建和使用多核利用率创建子进程进程间通信 IPC总结前言 JavaScript 主线程运行在单个进程的单个线程上。这样做的好处是: 程序状态是单一的,在没有多线程的情况...
    99+
    2022-11-13
    Nodejs构建多进程应用 Nodejs 多进程
  • 如何构造一个C#语言的爬虫程序
    本篇内容介绍了“如何构造一个C#语言的爬虫程序”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!   转CS...
    99+
    2024-04-02
  • 如何构造C#语言的爬虫蜘蛛程序
    这篇文章主要介绍了如何构造C#语言的爬虫蜘蛛程序的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何构造C#语言的爬虫蜘蛛程序文章都会有所收获,下面我们一起来看看吧。   C#...
    99+
    2024-04-02
  • 如何在python中使用proxybroker构建一个爬虫免费IP代理池
    今天就跟大家聊聊有关如何在python中使用proxybroker构建一个爬虫免费IP代理池,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。python可以做什么Python是一种编程...
    99+
    2023-06-06
  • 如何使用Webpack构建多页面程序
    这篇文章给大家分享的是有关如何使用Webpack构建多页面程序的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。原理将每个页面所在的文件夹都看作是一个单独的单页面程序目录,配置多个entry以及html-webpac...
    99+
    2023-06-14
  • 如何使用Docker Swarm搭建分布式爬虫集群
    今天小编给大家分享一下如何使用Docker Swarm搭建分布式爬虫集群的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获...
    99+
    2024-04-02
  • 如何使用Python中的多线程和协程实现一个高性能的爬虫
    如何使用Python中的多线程和协程实现一个高性能的爬虫导语:随着互联网的快速发展,爬虫技术在数据采集和分析中扮演着重要的角色。而Python作为一门强大的脚本语言,具备多线程和协程的功能,可以帮助我们实现高性能的爬虫。本文将介绍如何使用P...
    99+
    2023-10-22
    多线程 协程 高性能
  • Python爬虫的并发编程如何应用
    这篇文章主要讲解了“Python爬虫的并发编程如何应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python爬虫的并发编程如何应用”吧!什么是并发编程并发编程是指在一个时间段内,能够执行...
    99+
    2023-07-06
  • php如何使用多进程
    这篇文章给大家分享的是有关php如何使用多进程的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码:<php class process{ public ...
    99+
    2024-04-02
  • Python爬虫如何使用浏览器的cookies browsercookie
    这篇文章给大家介绍Python爬虫如何使用浏览器的cookies browsercookie,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。很多用Python的人可能都写过网络爬虫,自动化获取网络数据确实是一件令人愉悦的...
    99+
    2023-06-02
  • 如何使用webpack构建多页面应用
    这篇文章给大家分享的是有关如何使用webpack构建多页面应用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。需求来看下我们的需求:使用webpack-dev-server做开发时...
    99+
    2024-04-02
  • PHP中如何使用Shell和Git来构建框架?
    在Web开发中,构建一个高效、可扩展的框架是非常重要的。PHP作为一门流行的Web开发语言,有许多优秀的框架可以使用。但是,如果你想自己构建一个框架,你可以使用Shell和Git来帮助你完成这个任务。 Shell是一个命令行工具,可以用于...
    99+
    2023-10-20
    shell git 框架
  • 如何使用 PHP 构建多页面网站
    php 多页面网站构建指南:创建清晰的文件夹结构,以分离不同页面。使用 html 模板(template.php)作为每个页面的基础。为主页(index.php)添加内容。为其他页面(如...
    99+
    2024-05-03
    php 多页面网站 php7 apache nginx
  • PHP中如何使用Memcache缓存技术对于爬虫进行优化
    随着互联网技术的发展,网络爬虫越来越被用于数据挖掘、搜索引擎等领域。而大规模的数据采集和处理不仅需要更高效的爬虫算法,同时需要优化处理数据的速度和减少资源消耗。在这个过程中,缓存技术发挥了重要作用,为数据处理和应用的性能提供了帮助。本文介绍...
    99+
    2023-05-16
    PHP Memcache 缓存技术
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作