先贴爬虫程序下载地址:http://pan.baidu.com/s/1c2lxl1e

下载解压后 可直接运行 其中的 run.bat;或者你手动打开命令行执行:Joynet examples\SpiderZhihu.lua

大家不妨先下载下来玩一玩(可以修改配置,在examples目录下的ZhihuConfig.lua,添加感兴趣的关键字)

这个爬虫程序作为我写的Lua网络库 Joynet 的示例。

主要使用了异步Connect/HTTP/HTTPS 访问知乎搜索页面,譬如 https://www.zhihu.com/search?type=content&q=test 就是搜索 test 相关的问题。

拿到它的response 采用字符串搜索其中的各个question的url 地址。然后进行访问。在拿到question的页面内容后查找其中的图片相关url地址,然后再访问图片服务器下载到本地。

整个爬虫的代码在:https://github.com/IronsDu/Joynet/blob/master/examples/SpiderZhihu.lua#L118

一点问题:一般而言,开多个协程(链接)的话速度会提高很多。但在知乎爬虫中(访问知乎)并没有体现,反而更慢。我猜测与同时开多个链接到知乎时,知乎服务器做了速度限制。

(而且会给我返回部分 429 错误码···)

(我不知道该如何优化并发请求策略,以达到速度最快,且不会让服务器给我返回错误)

如果你无法访问github,可以看下面我复制过来的爬虫源码:

package.path = "./?.lua;./src/?.lua;./libs/?.lua;"

local ZhihuConfig = require "examples.ZhihuConfig"
local TcpService = require "TcpService"
local HttpClient = require "HttpClient"

local picTypes = {"png", "jpg", "jpeg"}

local requestedPicNum = 0
local requestdPic = {}  --当前已经发出请求的图片集合
local totalPicNum = 0   --当前已经完成请求的图片数量

local zhihuAddres = GetIPOfHost("www.zhihu.com")
local picAddres = {}    --pic http 服务器ip地址集合,key 为域名
UtilsCreateDir(ZhihuConfig.saveDir)

local function singleCo(f)
    -- 不开启协程,因为经过测试发现,同时开多个链接到zhihu时,速度反而下降,通过访问百度进行对比,发现可能是zhihu服务器(故意)设置锁导致的
    if false then
        coroutine_start(function ()
            f()
        end)
    else
        f()
    end
end

-- 访问图片地址,下载成功则保存到文件
local function requestPic(clientService, pic_url, dirname, qoffset)
    local s,e = string.find(pic_url, "https:%/%/")
    local _,hostEnd = string.find(pic_url, "%.com")
    local host = string.sub(pic_url, e+1, hostEnd)
    local url = string.sub(pic_url, hostEnd+1, string.len(pic_url))

    print(os.date().." start request :"..pic_url)

    if picAddres[host] == nil then
        picAddres[host] = GetIPOfHost(host)
    end

    local response = HttpClient.Request(clientService, picAddres[host], 443, true, "GET", url,  host)
    if response ~= nil then
        local f = io.open(ZhihuConfig.saveDir.."\\"..dirname.."\\"..qoffset.."\\"..string.sub(url, 2, string.len(url)), "w+b")
        f:write(response)
        f:flush()
        f:close()
        f=nil
        print(os.date().." recv pic :"..pic_url.." success")
        totalPicNum = totalPicNum + 1
    else
        print(os.date().." recv pic :"..pic_url.." failed")
    end
end

-- 访问问题页面
local function requestQuestion(clientService, question_url, dirname, qoffset)
    UtilsCreateDir(ZhihuConfig.saveDir.."\\"..dirname)
    UtilsCreateDir(ZhihuConfig.saveDir.."\\"..dirname.."\\"..qoffset)

    local fname = ZhihuConfig.saveDir.."\\"..dirname.."\\".."questions_address.txt"
    print(fname)
    local f = io.open(fname, "a+")
    f:write(question_url.."\r\n")
    f:flush()
    f:close()
    f=nil

    local response = HttpClient.Request(clientService, zhihuAddres, 443, true, "GET", question_url, "www.zhihu.com")
    if response ~= nil then
        for _,picType in ipairs(picTypes) do
            local pos = 1

            while true do
                --TODO (优化匹配代码以及图片后缀)
                --查找此问题页面中的图片地址
                local s, e = string.find(response, "https:%/%/pic%d.zhimg.com%/%w*%_r%."..picType, pos)

                if s ~= nil then
                    local pic_url = string.sub(response, s, e)
                    if not requestdPic[pic_url] then
                        requestdPic[pic_url] = true
                        requestedPicNum = requestedPicNum + 1
                        singleCo(function ()
                                --访问图片
                                requestPic(clientService, pic_url, dirname, qoffset)
                            end)
                        end

                    pos = e
                else
                    print("no more pic in question "..question_url)
                    break
                end
            end
        end
    end
end

local function urlEnCode(w)
    local pattern="[^%w%d%._%-%* ]"
    s=string.gsub(w,pattern,function(c)
        local c=string.format("%%%02X",string.byte(c))
        return c
    end)
    s=string.gsub(s," ","+")
    return s
end  

local isAllCompleted = false

function userMain()
    local clientService = TcpService:New()
    clientService:createService()

    coroutine_start(function()
        -- 访问知乎搜索页面,搜索配置的关键字的相关问题
        for k,v in pairs(ZhihuConfig.querys) do
            for i=1,v.count do
                local response = HttpClient.Request(clientService, zhihuAddres, 80, false, "GET", "/search", "www.zhihu.com", {type="content",q=urlEnCode(v.q), offset=v.startOffset+10*(i-1)})
                local pos = 1
                if response ~= nil then
                    while true do
                        --查找问题页面地址
                        local s, e = string.find(response, "\"%/question%/%d*\"", pos)
                        if s ~= nil then
                            pos = e
                            local question_url = string.sub(response, s+1 , e-1)

                            print("request question_url :"..question_url)
                            singleCo(function ()
                                --访问问题页面
                                requestQuestion(clientService, question_url, v.dirname, v.startOffset+10*(i-1))
                            end)
                        else
                            print("no more question, will break")
                            break
                        end
                    end
                end
            end
        end

        isAllCompleted = true
    end)

    coroutine_start(function ()
        while true do
            coroutine_sleep(coroutine_running(), 1000)
            print("Current Completed Pic Num : "..totalPicNum)
            print("Current requested pic num: "..requestedPicNum)
            if isAllCompleted then
                print("all pic completed, you can close process")
                break
            end
        end
    end)
end

coroutine_start(function ()
    userMain()
end)

while true
do
    CoreDD:loop()
    while coroutine_pengdingnum() > 0
    do
        coroutine_schedule()
    end
end

  

Joynet示例:知乎爬虫(搜索关键字相关回答,并下载其中的---图(mei)片(nv))的更多相关文章

  1. C#分析搜索引擎URL得到搜索关键字,并判断页面停留时间以及来源页面

    前台代码: var start; var end; var state; var lasturl = document.referrer; start = new Date($.ajax({ asyn ...

  2. C# 分析搜索引擎url 得到搜索关键字

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. java使用itex读取pdf,并搜索关键字,为其盖章

    导读:近期要做一个根据关键字定位pdf的盖章位置的相关需求,其中关键字可配置多个(包含pdf文档中可能不存在的关键字),当页面显示盖章完成时,打开pdf显示已经损坏. 排查后发现,当itext搜索的关 ...

  4. 【2022知乎爬虫】我用Python爬虫爬了2300多条知乎评论!

    您好,我是 @马哥python说,一枚10年程序猿. 一.爬取目标 前些天我分享过一篇微博的爬虫: https://www.cnblogs.com/mashukui/p/16414027.html 但 ...

  5. Java爬虫搜索原理实现

    permike 原文 Java爬虫搜索原理实现 没事做,又研究了一下爬虫搜索,两三天时间总算是把原理闹的差不多了,基本实现了爬虫搜索的原理,本次实现还是俩程序,分别是按广度优先和深度优先完成的,广度优 ...

  6. 在 Angular 中实现搜索关键字高亮

    在 Angular 中,我们不应该试图直接修改 DOM 的内容,当需要更新 DOM 内容的时候,应该修改的其实是我们的数据模型,也就是 $scope 中的数据,Angular 会帮助我们将修改之后的数 ...

  7. 仿百度壁纸客户端(五)——实现搜索动画GestureDetector手势识别,动态更新搜索关键字

    仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Frag ...

  8. google 搜索关键字技巧

    google 搜索关键字技巧 来源  https://www.cnblogs.com/qiudabai/articles/9143328.html inurl: 用于搜索网页上包含的URL. 这个语法 ...

  9. 帝国cms搜索关键字调用标签(showsearch)怎么用

    前面ytkah介绍了如何让帝国CMS7.2搜索模板支持动态标签调用,现在我们来说说怎么调用帝国cms搜索关键字调用标签(showsearch).在帝国cms后台那边的使用方法:[showsearch] ...

随机推荐

  1. excel分组求和

    =SUMPRODUCT((C2:C99=F2)*(B2:B99)) 说明: C2:C99=F2 找到C2到C99之间的等于F2的值 如果有多个判断条件,采用*来管理 B2:B99 求和

  2. POJ 2378 Tree Cutting (DFS)

    题目链接:http://poj.org/problem?id=2378 一棵树,去掉一个点剩下的每棵子树节点数不超过n/2.问有哪些这样的点,并按照顺序输出. dfs回溯即可. //#pragma c ...

  3. Android 通过ViewFlipper实现广告轮播功能并可以通过手势滑动进行广告切换

    为了实现广告轮播功能,在网上找了很多方法,有的效果很好,但是代码太麻烦,并且大多是用的viewpager,总之不是很满意. 于是看了一下sdk有个控件是ViewFlipper,使用比较方便,于是尝试了 ...

  4. html 4.01速查手册

    来自 W3School 的 HTML 快速参考.可以打印它,以备日常使用. HTML Basic Document <html> <head> <title>Doc ...

  5. date之Hi时间的思考

    工作中用到需要一个判断当前时间是否在 23:50到1:00之间的一段程序,在和别人的讨论中基本上有以下两种做法 1.分别获取时分进行判断和比较 <?php function check_time ...

  6. Linux之sed,awk(流编辑器)

    sed:  s----substitute(替换) 1. 文本替换(使用-i选项,可以将结果应用于原文件) many people在进行替换之后,借助重定向来保存文件(未使用-i选项): $ sed  ...

  7. kindeditor 上传图片 显示绝对 路径

    在前台页面上 效果图 另外附上 urlType 属性的 参数说明: 改变站内本地URL,可设置空.relative.absolute.domain. 空为不修改URL,relative为相对路径,ab ...

  8. MES取所有部门的函数实例

    USE [ChangHong]GO/****** Object: UserDefinedFunction [dbo].[FN_GetDeptCode] Script Date: 04/26/2016 ...

  9. 机器学习笔记之人工神经网络(ANN)

    人工神经网络(ANN)提供了一种普遍而且实际的方法从样例中学习值为实数.离散值或向量函数.人工神经网络由一系列简单的单元相互连接构成,其中每个单元有一定数量的实值输入,并产生单一的实值输出. 上面是一 ...

  10. Java常见排序算法之归并排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...