国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

使用Shell構(gòu)建多進(jìn)程的CommandlineFu爬蟲

開(kāi)發(fā) 后端
CommandlineFu 是一個(gè)記錄腳本片段的網(wǎng)站,每個(gè)片段都有對(duì)應(yīng)的功能說(shuō)明和對(duì)應(yīng)的標(biāo)簽。我想要做的就是嘗試用 shell 寫一個(gè)多進(jìn)程的爬蟲把這些代碼片段記錄在一個(gè) org 文件中。

[[259230]]

 CommandlineFu 是一個(gè)記錄腳本片段的網(wǎng)站,每個(gè)片段都有對(duì)應(yīng)的功能說(shuō)明和對(duì)應(yīng)的標(biāo)簽。我想要做的就是嘗試用 shell 寫一個(gè)多進(jìn)程的爬蟲把這些代碼片段記錄在一個(gè) org 文件中。

參數(shù)定義

這個(gè)腳本需要能夠通過(guò) -n 參數(shù)指定并發(fā)的爬蟲數(shù)(默認(rèn)為 CPU 核的數(shù)量),還要能通過(guò) -f 指定保存的 org 文件路徑(默認(rèn)輸出到 stdout)。

  1. #!/usr/bin/env bash
  2.  
  3. proc_num=$(nproc)
  4. store_file=/dev/stdout
  5. while getopts :n:f: OPT; do
  6. case $OPT in
  7. n|+n)
  8. proc_num="$OPTARG"
  9. ;;
  10. f|+f)
  11. store_file="$OPTARG"
  12. ;;
  13. *)
  14. echo "usage: ${0##*/} [+-n proc_num] [+-f org_file} [--]"
  15. exit 2
  16. esac
  17. done
  18. shift $(( OPTIND - 1 ))
  19. OPTIND=1

解析命令瀏覽頁(yè)面

我們需要一個(gè)進(jìn)程從 CommandlineFu 的瀏覽列表中抽取各個(gè)腳本片段的 URL,這個(gè)進(jìn)程將抽取出來(lái)的 URL 存放到一個(gè)隊(duì)列中,再由各個(gè)爬蟲進(jìn)程從進(jìn)程中讀取 URL 并從中抽取出對(duì)應(yīng)的代碼片段、描述說(shuō)明和標(biāo)簽信息寫入 org 文件中。

這里就會(huì)遇到三個(gè)問(wèn)題:

  1. 進(jìn)程之間通訊的隊(duì)列如何實(shí)現(xiàn)
  2. 如何從頁(yè)面中抽取出 URL、代碼片段、描述說(shuō)明、標(biāo)簽等信息
  3. 多進(jìn)程對(duì)同一文件進(jìn)行讀寫時(shí)的亂序問(wèn)題

實(shí)現(xiàn)進(jìn)程之間的通訊隊(duì)列

這個(gè)問(wèn)題比較好解決,我們可以通過(guò)一個(gè)命名管道來(lái)實(shí)現(xiàn):

  1. queue=$(mktemp --dry-run)
  2. mkfifo ${queue}
  3. exec 99<>${queue}
  4. trap "rm ${queue} 2>/dev/null" EXIT

從頁(yè)面中抽取想要的信息

從頁(yè)面中提取元素內(nèi)容主要有兩種方法:

  1. 對(duì)于簡(jiǎn)單的 HTML 頁(yè)面,我們可以通過(guò) sedgrepawk 等工具通過(guò)正則表達(dá)式匹配的方式來(lái)從 HTML 中抽取信息。
  2. 通過(guò) html-xml-utils 工具集中的 hxselect 來(lái)根據(jù) CSS 選擇器提取相關(guān)元素。

這里我們使用 html-xml-utils 工具來(lái)提取:

  1. function extract_views_from_browse_page()
  2. {
  3. if [[ $# -eq 0 ]];then
  4. local html=$(cat -)
  5. else
  6. local html="$*"
  7. fi
  8. 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/@'
  9. }
  10.  
  11. function extract_nextpage_from_browse_page()
  12. {
  13. if [[ $# -eq 0 ]];then
  14. local html=$(cat -)
  15. else
  16. local html="$*"
  17. fi
  18. 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/@'
  19. }

這里需要注意的是:hxselect 對(duì) HTML 解析時(shí)要求遵循嚴(yán)格的 XML 規(guī)范,因此在用 hxselect 解析之前需要先經(jīng)過(guò) hxclean 矯正。另外,為了防止 HTML 過(guò)大,超過(guò)參數(shù)列表長(zhǎng)度,這里允許通過(guò)管道的形式將  HTML 內(nèi)容傳入。

循環(huán)讀取下一頁(yè)的瀏覽頁(yè)面,不斷抽取代碼片段 URL 寫入隊(duì)列

這里要解決的是上面提到的第三個(gè)問(wèn)題: 多進(jìn)程對(duì)管道進(jìn)行讀寫時(shí)如何保障不出現(xiàn)亂序? 為此,我們需要在寫入文件時(shí)對(duì)文件加鎖,然后在寫完文件后對(duì)文件解鎖,在 shell 中我們可以使用 flock 來(lái)對(duì)文件進(jìn)行枷鎖。 關(guān)于 flock 的使用方法和注意事項(xiàng),請(qǐng)參見(jiàn)另一篇博文 Linux shell flock 文件鎖的用法及注意事項(xiàng)

由于需要在 flock 子進(jìn)程中使用函數(shù) extract_views_from_browse_page,因此需要先導(dǎo)出該函數(shù):

  1. export -f extract_views_from_browse_page

由于網(wǎng)絡(luò)問(wèn)題,使用 curl 獲取內(nèi)容可能失敗,需要重復(fù)獲取:

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

collector 用來(lái)從種子 URL 中抓取待爬的 URL,寫入管道文件中,寫操作期間管道文件同時(shí)作為鎖文件:

  1. function collector()
  2. {
  3. url="$*"
  4. while [[ -n ${url} ]];do
  5. echo "從$url中抽取"
  6. html=$(fetch "${url}")
  7. echo "${html}"|flock ${queue} -c "extract_views_from_browse_page >${queue}"
  8. url=$(echo "${html}"|extract_nextpage_from_browse_page)
  9. done
  10. # 讓后面解析代碼片段的爬蟲進(jìn)程能夠正常退出,而不至于被阻塞.
  11. for ((i=0;i<${proc_num};i++))
  12. do
  13. echo >${queue}
  14. done
  15. }

這里要注意的是, 在找不到下一頁(yè) URL 后,我們用一個(gè) for 循環(huán)往隊(duì)列里寫入了 =proc_num= 個(gè)空行,這一步的目的是讓后面解析代碼片段的爬蟲進(jìn)程能夠正常退出,而不至于被阻塞。

解析腳本片段頁(yè)面

我們需要從腳本片段的頁(yè)面中抽取標(biāo)題、代碼片段、描述說(shuō)明以及標(biāo)簽信息,同時(shí)將這些內(nèi)容按 org 模式的格式寫入存儲(chǔ)文件中。

  1. function view_page_handler()
  2. {
  3. local url="$1"
  4. local html="$(fetch "${url}")"
  5. # headline
  6. local headline="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > h1:nth-child(1)")"
  7. # command
  8. 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)"
  9. # description
  10. local description="$(echo ${html} |hxclean |hxselect -c -s "\n" ".col-md-8 > div.description"|pandoc -f html -t org)"
  11. # tags
  12. local tags="$(echo ${html} |hxclean |hxselect -c -s ":" ".functions > a")"
  13. if [[ -n "${tags}" ]];then
  14. tags=":${tags}"
  15. fi
  16. # build org content
  17. cat <<EOF |flock -x ${store_file} tee -a ${store_file}
  18. * ${headline} ${tags}
  19.  
  20. :PROPERTIES:
  21. :URL: ${url}
  22. :END:
  23.  
  24. ${description}
  25. #+begin_src shell
  26. ${command}
  27. #+end_src
  28.  
  29. EOF
  30. }

這里抽取信息的方法跟上面的類似,不過(guò)代碼片段和描述說(shuō)明中可能有一些 HTML 代碼,因此通過(guò) pandoc 將之轉(zhuǎn)換為 org 格式的內(nèi)容。

注意***輸出 org 模式的格式并寫入存儲(chǔ)文件中的代碼不要寫成下面這樣:

  1. flock -x ${store_file} cat <<EOF >${store_file}
  2. * ${headline}\t\t ${tags}
  3. ${description}
  4. #+begin_src shell
  5. ${command}
  6. #+end_src
  7. EOF

它的意思是使用 flock 對(duì) cat 命令進(jìn)行加鎖,再把 flock 整個(gè)命令的結(jié)果通過(guò)重定向輸出到存儲(chǔ)文件中,而重定向輸出的這個(gè)過(guò)程是沒(méi)有加鎖的。

spider 從管道文件中讀取待抓取的 URL,然后實(shí)施真正的抓取動(dòng)作。

  1. function spider()
  2. {
  3. while :
  4. do
  5. if ! url=$(flock ${queue} -c 'read -t 1 -u 99 url && echo $url')
  6. then
  7. sleep 1
  8. continue
  9. fi
  10.  
  11. if [[ -z "$url" ]];then
  12. break
  13. fi
  14. view_page_handler ${url}
  15. done
  16. }

這里要注意的是,為了防止發(fā)生死鎖,從管道中讀取 URL 時(shí)設(shè)置了超時(shí),當(dāng)出現(xiàn)超時(shí)就意味著生產(chǎn)進(jìn)程趕不上消費(fèi)進(jìn)程的消費(fèi)速度,因此消費(fèi)進(jìn)程休眠一秒后再次檢查隊(duì)列中的 URL。

組合起來(lái)

  1. collector "https://www.commandlinefu.com/commands/browse" &
  2.  
  3. for ((i=0;i<${proc_num};i++))
  4. do
  5. spider &
  6. done
  7. wait

抓取其他網(wǎng)站

通過(guò)重新定義 extract_views_from_browse_pageextract_nextpage_from-browse_pageview_page_handler 這幾個(gè)函數(shù), 以及提供一個(gè)新的種子 URL,我們可以很容易將其改造成抓取其他網(wǎng)站的多進(jìn)程爬蟲。

例如通過(guò)下面這段代碼,就可以用來(lái)爬取 xkcd 上的漫畫:

  1. function extract_views_from_browse_page()
  2. {
  3. if [[ $# -eq 0 ]];then
  4. local html=$(cat -)
  5. else
  6. local html="$*"
  7. fi
  8. max=$(echo "${html}"|hxclean |hxselect -c -s "\n" "#middleContainer"|grep "Permanent link to this comic" |awk -F "/" '{print $4}')
  9. seq 1 ${max}|sed 's@^@https://xkcd.com/@'
  10. }
  11.  
  12. function extract_nextpage_from_browse_page()
  13. {
  14. echo ""
  15. }
  16.  
  17. function view_page_handler()
  18. {
  19. local url="$1"
  20. local html="$(fetch "${url}/")"
  21. local image="https:$(echo ${html} |hxclean |hxselect -c -s "\n" "#comic > img:nth-child(1)::attr(src)")"
  22. echo ${image}
  23. wget ${image}
  24. }
  25.  
  26. collector "https://xkcd.com/" &
責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
相關(guān)推薦

2024-03-08 12:17:39

網(wǎng)絡(luò)爬蟲Python開(kāi)發(fā)

2021-02-25 11:19:37

谷歌Android開(kāi)發(fā)者

2017-06-30 10:12:46

Python多進(jìn)程

2020-11-18 09:06:04

Python

2016-02-26 15:28:45

CasperJSWeb爬蟲

2009-04-21 09:12:45

Java多進(jìn)程運(yùn)行

2024-08-26 08:39:26

PHP孤兒進(jìn)程僵尸進(jìn)程

2019-02-26 11:15:25

進(jìn)程多線程多進(jìn)程

2010-07-15 12:51:17

Perl多進(jìn)程

2013-01-30 15:07:59

Shell

2017-04-25 15:20:11

Python進(jìn)程mpi4py

2010-07-15 13:13:21

Perl多進(jìn)程

2021-06-16 07:21:39

AndroidAndroid系統(tǒng)多進(jìn)程通訊

2022-04-19 20:39:03

協(xié)程多進(jìn)程

2023-12-13 09:56:13

?多進(jìn)程多線程協(xié)程

2012-08-08 09:32:26

C++多進(jìn)程并發(fā)框架

2022-07-11 10:23:42

云原生Python多核CPU

2016-01-11 10:29:36

Docker容器容器技術(shù)

2021-10-12 09:52:30

Webpack 前端多進(jìn)程打包

2024-03-29 06:44:55

Python多進(jìn)程模塊工具
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

超清福利视频| 国产精品高颜值在线观看| 欧美经典一区| 日本91av在线播放| 色狠狠一区二区三区| 亚洲视频国产视频| 亚洲性色av| 国产精品亚洲一区二区三区在线 | 日本大片在线播放| 亚洲欧美色图小说| a视频在线看| 亚洲一区免费视频| 国产在线一二| 国产精品久久久爽爽爽麻豆色哟哟| 曰本人一级毛片免费完整视频| 精品久久久久久| 国产一二在线观看| 亚洲免费av电影| 日韩一区二区中文| 一二三四中文字幕| 在线视频亚洲一区| 国产女人在线视频| 97se亚洲国产综合自在线不卡| 欧美一区在线直播| 日本蜜桃在线观看| 都市激情亚洲色图| 4kfree性满足欧美hd18| 亚洲图片激情小说| 你懂的视频在线观看| 日韩女同互慰一区二区| 成人搞黄视频| 三年中国国语在线播放免费| 国产九色精品成人porny| 麻豆亚洲一区| 日韩在线一区二区| 亚洲欧美在线网| 久久精品免费观看| 无码熟妇人妻av在线电影| 成人av网站在线观看| 秋霞无码一区二区| 国产精品色一区二区三区| 成人福利视频在| 欧美午夜精品久久久久久久| 伊人免费在线| 亚洲美女www午夜| 亚洲专区**| 国产精品免费视频xxxx| 国产精品一国产精品k频道56| 色一情一区二区三区四区| 韩国毛片一区二区三区| 免费无码av片在线观看| 一区二区三区欧美亚洲| 一色桃子在线| 欧美变态凌虐bdsm| 国产精品传媒麻豆hd| 日本精品中文字幕| 欧美久久视频| 成年丰满熟妇午夜免费视频| 久久精品网站免费观看| 青青草观看免费视频在线| 欧美精品一区二区蜜臀亚洲| 国内不卡的一区二区三区中文字幕| 国产精品成人va在线观看| 亚洲毛片播放| 妺妺窝人体色www在线小说| 亚洲成人中文在线| 高清在线视频不卡| 欧美亚洲成人精品| 久久狠狠婷婷| 白浆爆出在线观看| 精品久久人人做人人爽| 欧美a级网站| 日本一区二区三不卡| 国产精品全国免费观看高清| 黄色av网站在线免费观看| 亚洲香蕉伊综合在人在线视看 | 高清在线成人网| 亚洲精华国产| 精品性高朝久久久久久久| 日韩av影院| 亚洲韩国在线| 亚洲精品国产精华液| 牛牛精品在线| 国产精品视频久久久| 国产一区福利在线| 在线资源免费观看| 日韩一区二区三区国产| 激情久久综合| 污视频网站观看| 欧美不卡视频一区| 一道在线中文一区二区三区| 亚洲一区精品视频| 香蕉加勒比综合久久| 456成人影院在线观看| 成人免费在线一区二区三区| 国产三级精品三级| 综合久久2019| 国产精品吴梦梦| 99精品视频一区二区三区| 婷婷免费在线视频| 日韩免费在线观看视频| 国产成a人亚洲精| av在线1区2区| 国产精选久久久久久| 久久午夜羞羞影院免费观看| 黄色大片在线| 国产伦精品一区二区三区四区免费| 欧美韩国一区二区| 欧美一区久久久| 久久精精品视频| 一本色道久久综合狠狠躁的推荐| 日本一区二区三区视频在线看 | 成人免费视频网站在线看| 日韩激情av在线播放| 欧美精品一卡| 在线看的你懂得| 午夜精品久久久99热福利| 国产99久久久久| 欧美videos另类精品| 国产精品一区二区三区在线观| 亚洲精品国产高清久久伦理二区| 欧美第一在线视频| 大伊香蕉精品视频在线| 日韩国产一区三区| 免费看精品久久片| 亚洲色图美国十次| 欧美精品一区在线| 欧美精品丝袜久久久中文字幕| 国产精品成人a在线观看| 国产一级大片| 热99久久精品| 一区二区日韩电影| 精品国产乱码久久久久久1区2匹| 黄色漫画在线免费观看| 欧美一级bbbbb性bbbb喷潮片| 国产精品蜜臀av| 亚洲欧美tv| 美女免费免费看网站| 国产v综合ⅴ日韩v欧美大片| 亚洲激情中文1区| 日韩精品水蜜桃| 男男激情在线| 欧美日韩另类丝袜其他| 精品乱码亚洲一区二区不卡| 九九视频精品免费| 欧美网站免费| 男女午夜刺激视频| 国产精品白嫩美女在线观看| 欧美日韩加勒比精品一区| 91精品国产乱码久久久久久久| 成人午夜电影在线观看| 麻豆精品传媒视频| 日韩精品视频在线观看网址| 成人av在线资源| silk一区二区三区精品视频 | 国色天香2019中文字幕在线观看| 国产精品国产自产拍高清av王其 | 麻豆精品视频在线观看视频| 日韩在线免费| 超碰成人福利网| 3d动漫啪啪精品一区二区免费| 欧美色爱综合网| 久久丁香综合五月国产三级网站| 都市激情亚洲一区| 亚洲精品乱码久久久久久自慰| 欧美亚洲另类制服自拍| 在线观看视频一区| 国产在线视频一区二区三区| 日韩欧美中文在线观看| 香蕉视频在线观看免费| 久久久久一区二区三区| 自拍亚洲一区欧美另类| 亚洲欧美色综合| 中文高清一区| 欧美性www| 午夜亚洲成人| 国内外成人激情免费视频| 国模极品一区二区三区| 在线免费观看视频一区| 国产一区三区三区| 视频一区中文| av在线小说| eeuss在线播放| 免费成人在线观看av| 在线视频精品一| 天天做天天摸天天爽国产一区 | 国产一二三在线| 99热手机在线观看| 久草精品电影| 欧美国产精品人人做人人爱| 一本大道久久a久久综合婷婷| 国精产品一区一区三区mba桃花| 大香伊人久久精品一区二区| 婷婷五月在线视频| 欧美一级片中文字幕| 国内视频一区二区| 久久69精品久久久久久久电影好 | 在线成人www免费观看视频| 亚洲aⅴ网站| www.亚洲免费|