@echo off
::# History:
::# Date Author Description
::# -------------------------------------------------------------
::# 2/10/2014 Perry Initial created.
::#
::# Note:
::# This source code can be used, modified, and redistributed under the
::# terms of the license agreement that is included in the Spiders package
::# By continuing to use, modify, or redistributed this code you indicate
::# that you have read the license and understand and accept it fully.
::#setlocal enabledelayedexpansion
:begin
::# Architecture
::#
::# ┌───────初始化
::# │ │
::# │ │
::# │ ┌队列空─ ◇
::# │ │ │
::# │ 查表 │
::# │ │ │ ┌─下载
::# │ └────启动──┤
::# │ │ └─下载
::# │ │ ┌─分析
::# │ 启动──┤
::# │ │ └─分析
::# │ 统计
::# │ │
::# ├──无数据───◇
::# │ │
::# └───────存数据
::#
set $sfldb=database.db
set $sdofl=sedTMP.txt
set $dwlfd=download
set $prfx1=$a$b$c
set $tmpx2=$xTmp
set $tmpx3=$uTmp
::# 最多允许同时运行的下载进程数量。
set $tsknm=2
::# 每个下载进程最大处理的数据量。
set $tskmx=5
::# 最多提供给下载进程使用的资源数量。
set $datmx=5
set $tblwp=T_Webpages
set $tblma=T_Mails
set $tbltm=T_Temp1
if "%~1"=="CMB" goto :startCMB
if "%~1"=="DWL" goto :startDWL
if "%~1"=="AYS" goto :startAYS
if "%~1"=="TSK" goto :startTSK
if not "%~1"=="" goto :end
if exist "%$sfldb%" goto :dbReady
::# 创建一个数据表用来储存模板文件。
( gecho create table %$tblwp% \50
gecho wp_id integer primary key autoincrement not null,
gecho wp_url text not null unique,
gecho wp_text text,
gecho wp_status integer default 0,
gecho wp_result integer default 0,
gecho wp_error integer default 0,
gecho wp_parent integer default 0,
gecho wp_access datetime,
gecho wp_update datetime\51;
gecho create table %$tbltm% \50
gecho wp_id integer primary key autoincrement not null,
gecho wp_url text not null unique,
gecho wp_text text,
gecho wp_status integer default 0,
gecho wp_result integer default 0,
gecho wp_error integer default 0,
gecho wp_parent integer default 0,
gecho wp_access datetime,
gecho wp_update datetime\51;
) | sqlite3 "%$sfldb%"
:dbReady
::# 查看当前数据库中是否有内容
set sql=select count(*) from %$tblwp%;
for /f %%i in ('sqlite3 "%$sfldb%" "%sql%" 2^>nul') do (
if %%i gtr 0 goto :cleanStatus)
::# 初始化数据库内容。从网上找了些导航网站。
set Xed=insert into %$tblwp%^(wp_url,wp_status,wp_parent^) values('http://
( gecho begin;
( gecho www.0460.com
gecho www.114la.com
gecho www.1616.net
gecho www.2345.com
gecho www.265.com
gecho www.5566.net
gecho www.726.com
gecho www.baimin.com
gecho www.hao123.com
gecho www.hao360.cn
gecho www.lvse.com
gecho www.tao123.com
gecho www.ttuu.com
) | gawk "{print ENVIRON[\"Xed\"]$1\"',0,0\x29;\"}"
gecho commit;
) | sqlite3 "%$sfldb%"
:cleanStatus
::# 清除上次未完成项目的状态。
sqlite3 "%$sfldb%" "update %$tblwp% set wp_status=0 where wp_status=2;"
for /f "delims==" %%i in ('set $ZX_ 2^>nul') do (
set %%~i=)
:prepareData
set x=0
::# 上次剩余的数据。
for /f %%i in ('set $ZX_ 2^>nul') do set /a x+=1
::# 得到最少数据需求量。
set /a z=$tsknm*$tskmx*2
::# 如果没有数据不足继续增加数据。
if %x% geq %z% goto :allocTasks
::# 清除临时变量。
for /f "delims==" %%i in ('set $ZT_ 2^>nul') do (
set %%~i=)
::# 从数据库中取出一组未被分析过的网址。
::# 如果数据库在此时被锁定(导入数据时)产生错误导致未能更新会自动重试。
:fetchData
set z=0
set sql=select wp_id, wp_url from %$tblwp% where wp_status=0 limit %$datmx%;
for /f "tokens=1,2 delims=^|" %%i in ('sqlite3 "%$sfldb%" "%sql%" 2^>nul') do (
set $ZT_%%~i=%%~j
::# 对已经取得的项目计数。
set /a z+=1)
set sql=update %$tblwp% set wp_status
::# 判断是否取到数据。
if %z% equ 0 goto :fetchError
::# 给取出的数据做个标记。
( gecho begin;
set $ZT_ | sed -r -e "s/.+_([0-9]+)=.+/%sql%=2 where wp_id=\1;/"
gecho commit;) | sqlite3 "%$sfldb%" && goto :appendData
:fetchError
set z=0
::# 更新出错了,重置已经变更的标记。
( gecho begin;
set $ZT_ | sed -r -e "s/.+_([0-9]+)=.+/%sql%=0 where wp_id=\1;/"
gecho commit;) | sqlite3 "%$sfldb%"
::# 清除产生的变量。
for /f "tokens=1,* delims==" %%i in ('set $ZT_ 2^>nul') do (
set %%~i=)
:appendData
::# 新增的数据项。
for /f "tokens=2,* delims==_" %%i in ('set $ZT_ 2^>nul') do (
set $ZX_%%~i=%%~j
set $ZT_%%~i=)
goto :prepareData
::# 分配数据给下载进程。
:allocTasks
::# 检查数据是否足够。
if %x% lss %$tsknm% goto :prepareData
call "%~0" TSK,%$tsknm%
:statistics
::# 统计有多少进程在下载。
set z=0
set c=0
for /f "tokens=2 delims==_" %%i in ('set $ZC_') do (
if exist "%%~i_*.dat1" (
set $ZA_%%~i=%%~i
set /a c+=1)
set /a z+=1)
set /a z-=c
if %z% lss 5 goto :allocTasks
::# if %c% gtr 5 start /min call "%~0",AYS
forfiles /M *.dat1 /C "cmd.exe /c %~1 CMB @fname"
>nul timeout /t 1
goto :statistics
::# 存数据。
:importData
set v1=insert into %$tbltm%(wp_url,wp_status,wp_parent) values('
set v2=update %$tbltm% set wp_status=1, wp_result=
set v3=wp_url,wp_text,wp_status,wp_result,wp_error,wp_parent
set $file=
:findData
::# 找出一个可用的数据文件。
for %%i in (*.dat2) do (
set $file=%%~i
goto :beginImp)
::# 没有文件可用。
goto :statistics
:beginImp
::# 确保文件有效。
if not exist "%$file%" (
goto :findData)
::# 开始导入数据。
( gecho begin;
gecho delete from %$tbltm%;
gecho delete from sqlite_sequence where name='%$tbltm%';
cat "%$file%" | gawk "{if(!a[$1]++) print ENVIRON[\"v1\"]$1\"',0,\"$2\"\x29;\"}"
cat "%$file%" | gawk "{if(!a[$2]++) print ENVIRON[\"v2\"]$3\",wp_error=\"$4\" where wp_id=\"$2\";\"}"
gecho insert into %$tblwp% \50%v3%\51 select %v3% from %$tbltm% where wp_url not in \50select wp_url from %$tblwp%\51;
gecho commit;
) | sqlite3 "%$sfldb%" || (
echo 访问数据库出错,准备重试。
goto :importData)
erase /f /q "%$file%"
::# 继续找下一个文件直接找不到为止。
goto :findData
:startTSK
set c=%~2
:nextTask
set id=
set url=
for /f "tokens=2,* delims==_" %%i in ('set $ZX_ 2^>nul') do (
set id=%%~i
set url=%%~j
goto :getOne)
goto :end
:getOne
start /min call "%~0",DWL,"%id%","%url%"
set $ZC_%id%=%url%
set $ZX_%id%=
set /a x-=1
set /a c-=1
if %c% gtr 0 goto :nextTask
goto :end
:startDWL
::# 下载网页内容并保存到文件。
if "%~3"=="" goto :failDWL
if "%~2"=="" goto :finishDWL
if exist "%~2.dat1" goto :finishDWL
wget --no-check-certificate -c -t2 -T5 -q -O "%~2.dwl" "%~3"
::# if errorlevel 1 goto :failDWL
if not exist "%~2.dwl" goto :failDWL
::# 找出绝对地址。
grep -o -E "https?://[a-z0-9A-Z]+[a-z0-9A-Z\-_\.]+" "%~2.dwl" | sort | uniq -i >"%~2.ays"
::# 计算本次下载的网页中共找出了多少网址。
for /f %%i in ('wc -l "%~2.ays" 2^>nul') do (
set $count=%%i)
rename "%~2.ays" "%~2_%$count%.dat1"
goto :finishDWL
:failDWL
::# 创建一个空文件代表下载完成。
echo.>"%~2_0.dat1"
:finishDWL
if exist "%~2.dwl" erase /f "%~2.dwl"
exit
:startAYS
::# 将数据变成SQL插入语句。
cat "%$sdofl%" | sed -e "s/$/ %$id% %$count% %$error%/">>"%$output%"
::# 清除掉变量。
set %$var%=
::# 一次分析出来的数据少于1000条就暂不存数据库。继续分析。
for /f %%i in ('wc -l "%$output%" 2^>nul') do (
if %%i lss 1000 goto :next)
::# 将分析出来的数据丢给SQLite3异步处理。
start /min call "%~0" IMP
::# 不需要等SQLite3处理完,继续去分析下一个URL。
if %$id% neq 0 goto :startAnalysis
goto :end
:startCMB
for /f "tokens=1,2 delims=_." %%i in (%~2) do (
set id=%%i
set count=%%j
::# 做个标记表示此URL被分析过。
set $ZA_%%i=
set $ZC_%%i=
echo %%i | gawk "{a=$0;for(i=0;i<50-length(a);i++) $0=$0\"\x20\";print \"Analyzed \"$0\"%%j found.\"}"
erase /f %%i_%%j.%%k
)
::# 做个标记表示此URL被分析过。
echo %$first% | gawk "{a=$0;for(i=0;i<50-length(a);i++) $0=$0\"\x20\";print \"Analyzed \"$0\"Found %$count%\"}"
:end
批处理的简单网络爬虫
最新推荐文章于 2024-05-15 16:33:25 发布