c 语言写的爬虫,抓取豆瓣上所有科幻电影 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
luohaha
V2EX    程序员

c 语言写的爬虫,抓取豆瓣上所有科幻电影

  •  5
     
  •   luohaha 2015-12-24 16:42:38 +08:00 10578 次点击
    这是一个创建于 3667 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先给自己定个目标,抓取豆瓣上所有的科幻电影的名称和类型信息,并保存文件。代码越短越好。下面是我的代码:

    #include<cspider/spider.h> typedef struct { char *getTitle[20]; char *getDesc[20]; int size; } Movie; //开始入口的 url char *begin = "www.douban.com/tag/%E7%A7%91%E5%B9%BB/movie"; void p(cspider_t *cspider, char *d, char *url, void *user_data) { Movie *movie = (Movie*)malloc(sizeof(Movie)); char *urls[20]; int sizeTitle = xpath(d, "//div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/div[@class='mod movie-list']/dl/dd/a", movie->getTitle, 20); int sizeDesc = xpath(d, "//div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/div[@class='mod movie-list']/dl/dd/div[@class='desc']", movie->getDesc, 20); int sizeUrl = xpath(d, "//div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/div[@class='paginator']/a/@href", urls, 20); movie->size = sizeTitle; saveString(cspider, (void*)movie, LOCK); char *newUrl[sizeUrl]; int i; //拼接成新的 url for (i = 0; i < sizeUrl; i++) { newUrl[i] = (char*)malloc(sizeof(char) * (strlen(begin) + strlen(urls[i]) + 1)); strcat(newUrl[i], begin); strcat(newUrl[i], urls[i]); } //添加新 url 到任务队列 if (movie->size > 0) { addUrls(cspider, newUrl, sizeUrl); } //回收 freeStrings(newUrl, sizeUrl); freeStrings(urls, sizeUrl); freeStrings(movie->getTitle, sizeTitle); freeStrings(movie->getDesc, sizeDesc); free(movie); } void s(void *str, void *user_data) { Movie *get = (Movie*)str; FILE *file = (FILE*)user_data; int i; for (i = 0; i < get->size; i++) { fprintf(file, "名称:%s\n", get->getTitle[i]); fprintf(file, "类别:%s\n", get->getDesc[i]); } } int main() { cspider_t *spider = init_cspider(); char *agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:42.0) Gecko/20100101 Firefox/42.0"; char *cookie = "bid=s3/yuH5Jd/I; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1450940218%2C%22http%3A%2F%2Fmovie.douban.com%2Ftag%2F%22%5D; _pk_id.100001.8cb4=8196f325b29ea5c3.1444265431.9.1450943478.1449364495.; ll=108288; viewed=1130500_24708145_6433169_4843567_1767120_5318823_1899158_1271597; __utma=30149280.927537245.1446813674.1449139583.1450940286.5; __utmz=30149280.1450940286.5.5.utmcsr=book.douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/; ps=y; [email protected]; push_noty_num=0; push_doumail_num=7; ap=1; _pk_ses.100001.8cb4=*; gr_user_id=5f4ee24f-d7bc-4b0b-9322-ceb1d208ee36; __utmb=30149280.17.10.1450940286; __utmc=30149280; ct=y; as=http://www.douban.com/tag/%E7%A7%91%E5%B9%BB/movie"; cs_setopt_url(spider, begin); cs_setopt_useragent(spider, agent); cs_setopt_cookie(spider, cookie); FILE *file = fopen("./movies.txt", "wb+"); //指向自定义的解析函数,和数据持久化函数 cs_setopt_process(spider, p, NULL); cs_setopt_save(spider, s, file); return cs_run(spider); } 

    一共 60 行左右,还可以。就是得手动回收内存,还有字符串处理,这两点使得代码比较丑陋,和 python 和 java 没得比。我用的爬虫框架是cspider。大家觉得,如果要让这个爬虫框架更完善,让我们用 c 写爬虫更爽,还需要实现什么呢?

    第 1 条附言    2015-12-25 15:38:17 +08:00

    cspider 的项目地址在 https://github.com/luohaha/CSpider ,欢迎来 star 和 fork !

    第 2 条附言    2015-12-25 15:49:20 +08:00

    cspider 爬虫框架的目标就是让我们用 c 语言写爬虫时,能像用 python 写爬虫那么方便。虽然道路遥远~~

    第 3 条附言    2015-12-25 22:52:34 +08:00
    多谢几位好心人提醒,豆瓣下逐页抓取是获取不到完整的豆瓣电影的,所以上述方法并不能获取到所有的科幻电影。。
    54 条回复    2016-01-01 18:32:21 +08:00
    TJT
        1
    TJT  
       2015-12-24 17:00:22 +08:00 via Android   1
    然后你就这么随便把 cookie 发上来了?
    luohaha
        2
    luohaha  
    OP
       2015-12-24 17:06:48 +08:00
    @TJT 忘了删了。。。
    zhy
        3
    zhy  
       2015-12-24 17:21:28 +08:00
    楼主自己写的,别不好意思嘛 -.-
    mzer0
        4
    mzer0  
       2015-12-24 17:39:17 +08:00 via iPhone
    cookie 怎么来的?
    luohaha
        5
    luohaha  
    OP
       2015-12-24 17:48:59 +08:00
    @mzer0 浏览器上
    mzer0
        6
    mzer0  
       2015-12-24 17:52:31 +08:00 via iPhone
    @luohaha 万一用的是 session 怎么办
    luohaha
        7
    luohaha  
    OP
       2015-12-24 18:44:44 +08:00
    @mzer0 这里用 cookie 是因为豆瓣会给没有 cookie 的客户端返回 403 。。
    luohaha
        8
    luohaha  
    OP
       2015-12-24 18:47:19 +08:00
    @zhy 哈哈
    jise
        9
    jise  
       2015-12-24 21:11:26 +08:00
    Mark~
    yxzblue
        10
    yxzblue  
       2015-12-24 23:35:01 +08:00
    厉害!
    just1
        11
    just1  
       2015-12-24 23:44:02 +08:00 via Android
    @mzer0 session 只是时效性,到期换一个不就好了
    jugelizi
        12
    jugelizi  
       2015-12-25 00:00:37 +08:00
    楼主的 QQ 哈啊哈
    oojiayu
        13
    oojiayu  
       2015-12-25 00:11:38 +08:00
    fxxkgw
        14
    fxxkgw  
       2015-12-25 08:55:41 +08:00
    学习了。
    quietin
        15
    quietin  
       2015-12-25 10:22:18 +08:00
    网页上带页码下标的并不是它的所有电影。。。
    luohaha
        16
    luohaha  
    OP
       2015-12-25 11:27:13 +08:00
    @quietin 什么意思?我抓取的是豆瓣上分类为科幻的所有的电影。
    luohaha
        17
    luohaha  
    OP
       2015-12-25 11:27:36 +08:00
    @oojiayu 。。求不调戏。
    zyearn
        18
    zyearn  
       2015-12-25 12:07:00 +08:00   1
    之前用 C++写过一个基于事件的知乎爬虫,底层全部纯手写,不依赖任何库,有兴趣的可以看看... https://github.com/zyearn/zhihuCrawler
    glogo
        19
    glogo  
       2015-12-25 12:58:43 +08:00
    233333
    quietin
        20
    quietin  
       2015-12-25 13:04:34 +08:00
    @luohaha 我的意思是网页结构解析的电影只是分类下的一部分而已,豆瓣并没有把某一分类下的所有电影暴露出来
    jise
        21
    jise  
       2015-12-25 13:31:26 +08:00 via Android
    @zyearn c++面向对象的特征和强大 stl 使得结构设计,以及字符串处理等方面要远方便于纯 c.
    luohaha
        22
    luohaha  
    OP
       2015-12-25 15:09:17 +08:00
    @quietinwww.douban.com/tag/%E7%A7%91%E5%B9%BB/movie 这里是科幻电影的第一页,爬虫爬取这一页后,在这页的底部会有其它页的链接,爬虫会将这些链接再次加入任务队列,继续往下抓取。因为提供了 bloom filter ,所以也不用担心会有重复 url 的问题。
    pypy
        23
    pypy  
       2015-12-25 15:14:58 +08:00
    求教: C 写爬虫的优势在哪儿?
    luohaha
        24
    luohaha  
    OP
       2015-12-25 15:29:23 +08:00
    @pypy 说实话,在爬虫这种探索式的应用场景下, c 语言并不合适
    pypy
        25
    pypy  
       2015-12-25 15:36:58 +08:00
    @luohaha 所以你用 C 写爬虫只是为了练手吗?准备未来将 C 应用到什么场景呢?
    luohaha
        26
    luohaha  
    OP
       2015-12-25 15:41:41 +08:00
    @pypy 我做了一个 c 语言的爬虫框架 cspider ,上面这个爬虫就是用 cspider ( https://github.com/luohaha/CSpider )写的。做 cspider 的目的就是要让我们用 c 语言写爬虫时也能够像 python 一样方便和高效。当然,这个框架好比较早期,现阶段离目标还比较远,还需要不断地努力和完善。
    quietin
        27
    quietin  
       2015-12-25 16:45:50 +08:00
    @luohaha 我的意思就是你把下面那页码都抓了也不是全部的,你自己看看那链接的 start ,连 1000 都不到就不给你数据了
    luohaha
        28
    luohaha  
    OP
       2015-12-25 16:57:01 +08:00
    @quietin 我在浏览器上看的,到了 35 页豆瓣电影科幻分类就没有电影了,不知道是不是科幻电影就这么多?
    quietin
        29
    quietin  
       2015-12-25 17:05:03 +08:00
    @luohaha 明显不是,自己思考吧
    luohaha
        30
    luohaha  
    OP
       2015-12-25 17:11:15 +08:00
    @quietin 大神求教,我在浏览器上也看不到啊!
    luohaha
        31
    luohaha  
    OP
       2015-12-25 17:16:29 +08:00
    @quietin 我觉得就是只有这么多,至少从这个入口进去只有这么多~
    luohaha
        32
    luohaha  
    OP
       2015-12-25 17:29:27 +08:00
    @quietin 我在豆瓣选电影的页面,选科幻后,一直点击加载更多,最后也是只有这么多部~
    Killian
        33
    Killian  
       2015-12-25 18:08:10 +08:00
    一般网站会做 大页数 翻页请求优化 比如只返回你 35 的数据 因为这种查询性能很低
    luohaha
        34
    luohaha  
    OP
       2015-12-25 19:19:09 +08:00
    @Killian 我作为一个正常用户,用浏览器访问豆瓣电影,翻到 35 页之后没有电影了,这是翻页请求优化?连用户都不用正常使用的优化。。
    kelos
        35
    kelos  
       2015-12-25 19:53:29 +08:00
    像一些 web 的通讯工作之类的,你们都可以抓?
    geekboy
        36
    geekboy  
       2015-12-25 20:00:04 +08:00
    前几天用 java 在抓,现在豆瓣 apikey 不让申请了,我也遇到过几次 403~
    quietin
        37
    quietin  
       2015-12-25 21:32:43 +08:00
    @luohaha 忘了多谢你给我科普抓取过程和布隆过滤器了
    luohaha
        38
    luohaha  
    OP
       2015-12-25 21:51:18 +08:00
    @geekboy 是吗?之前还申请过 douban 的 apikey 来做过一个应用。
    luohaha
        39
    luohaha  
    OP
       2015-12-25 21:52:22 +08:00
    @kelos 什么意思?就是正常的爬虫抓取啊。
    njutree
        40
    njutree  
       2015-12-25 22:02:32 +08:00
    @luohaha 正常用户翻到 35 页也说明了用户的搜索不准确,用户应该做的是使用更准确的词再搜索才是更好的方式。不然除了给爬虫的人有便利其实意义不大,而且做过后端的人都知道分布式分页的问题。
    luohaha
        41
    luohaha  
    OP
       2015-12-25 22:23:56 +08:00
    @njutree 好吧确实没有遇见过这么判别爬虫的。。一般都是根据抓取间隔, ip 等。。不过我无聊的时候会在一个分类下,一页一页地翻找电影看,如果真是你说的这样,看来以前我都是被豆瓣当成爬虫了。。
    luohaha
        42
    luohaha  
    OP
       2015-12-25 22:27:12 +08:00
    @njutree 你在做后端的时候会这么过滤爬虫吗?能给推荐一下一些这方面的博客吗?
    decaywood
        43
    decaywood  
       2015-12-25 22:38:34 +08:00
    cookie 写死了,你得引入 cookie 过期重新获取功能,不然有点废
    luohaha
        44
    luohaha  
    OP
       2015-12-25 22:43:04 +08:00
    @decaywood 嗯嗯,会改进的,多谢啦
    decaywood
        45
    decaywood  
       2015-12-25 22:46:30 +08:00
    java 版的股票爬虫也写过一个, https://github.com/decaywood/XueQiuSuperSpider ,爬虫这东西个人认为,可以根据抓取数据的生命周期划分一下模块,每个模块提供相应的可拔插机制,方便程序进行技术迭代,可以有效提高程序的生命力、
    luohaha
        46
    luohaha  
    OP
       2015-12-25 22:49:59 +08:00
    @decaywood Thanks!
    lx19930805
        47
    lx19930805  
       2015-12-26 10:34:07 +08:00
    我比较好奇的是楼上说的,一般人只能看到几页,后面更多的看不到了.
    对于刚接触的我来说,我比较想知道如何获取更多.

    不过我发现一个问题?为什么我直接改后面的页数回车后不能直接跳到指定页数,而是刷新第一页呢?
    njutree
        48
    njutree  
       2015-12-26 21:47:54 +08:00
    @luohaha 我觉得你没有看懂我在说啥,本质并不是为了屏蔽爬虫。
    luohaha
        49
    luohaha  
    OP
       2015-12-26 21:58:05 +08:00
    @njutree 的确,我后面才理解了。。
    angryRabbit
        50
    angryRabbit  
       2015-12-26 22:35:27 +08:00
    就想问一下,楼主写单元测试了吗?
    luohaha
        51
    luohaha  
    OP
       2015-12-26 22:41:12 +08:00
    @angryRabbit 写了,不过我习惯最后删掉。。
    luohaha
        52
    luohaha  
    OP
       2015-12-26 22:43:17 +08:00
    @angryRabbit 我想象不出不写测试单元,如何开发稍大点的程序
    kelos
        53
    kelos  
       2015-12-27 18:35:57 +08:00
    @luohaha 你看看阿里的 web 版钉钉,抓包根本就没有信息,这样的工具,联系人信息,能抓出来?
    wizardforcel
        54
    wizardforcel  
       2016-01-01 18:32:21 +08:00
    为啥不用 go 写

    go 就是没有分号的 c 语言

    并且处理字符串还方便一些
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     950 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 20:15 PVG 04:15 LAX 12:15 JFK 15:15
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86