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

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

```c
#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; ue=965166527@qq.com; 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]( https://github.com/luohaha/CSpider)。大家觉得,如果要让这个爬虫框架更完善,让我们用 c 写爬虫更爽,还需要实现什么呢?
9957 次点击
所在节点    程序员
54 条回复
jise
2015-12-25 13:31:26 +08:00
@zyearn c++面向对象的特征和强大 stl 使得结构设计,以及字符串处理等方面要远方便于纯 c.
luohaha
2015-12-25 15:09:17 +08:00
@quietinwww.douban.com/tag/%E7%A7%91%E5%B9%BB/movie 这里是科幻电影的第一页,爬虫爬取这一页后,在这页的底部会有其它页的链接,爬虫会将这些链接再次加入任务队列,继续往下抓取。因为提供了 bloom filter ,所以也不用担心会有重复 url 的问题。
pypy
2015-12-25 15:14:58 +08:00
求教: C 写爬虫的优势在哪儿?
luohaha
2015-12-25 15:29:23 +08:00
@pypy 说实话,在爬虫这种探索式的应用场景下, c 语言并不合适。
pypy
2015-12-25 15:36:58 +08:00
@luohaha 所以你用 C 写爬虫只是为了练手吗?准备未来将 C 应用到什么场景呢?
luohaha
2015-12-25 15:41:41 +08:00
@pypy 我做了一个 c 语言的爬虫框架 cspider ,上面这个爬虫就是用 cspider ( https://github.com/luohaha/CSpider )写的。做 cspider 的目的就是要让我们用 c 语言写爬虫时也能够像 python 一样方便和高效。当然,这个框架好比较早期,现阶段离目标还比较远,还需要不断地努力和完善。
quietin
2015-12-25 16:45:50 +08:00
@luohaha 我的意思就是你把下面那页码都抓了也不是全部的,你自己看看那链接的 start ,连 1000 都不到就不给你数据了
luohaha
2015-12-25 16:57:01 +08:00
@quietin 我在浏览器上看的,到了 35 页豆瓣电影科幻分类就没有电影了,不知道是不是科幻电影就这么多?
quietin
2015-12-25 17:05:03 +08:00
@luohaha 明显不是,自己思考吧
luohaha
2015-12-25 17:11:15 +08:00
@quietin 大神求教,我在浏览器上也看不到啊!
luohaha
2015-12-25 17:16:29 +08:00
@quietin 我觉得就是只有这么多,至少从这个入口进去只有这么多~
luohaha
2015-12-25 17:29:27 +08:00
@quietin 我在豆瓣选电影的页面,选科幻后,一直点击加载更多,最后也是只有这么多部~
Killian
2015-12-25 18:08:10 +08:00
一般网站会做 大页数 翻页请求优化 比如只返回你 35 的数据 因为这种查询性能很低
luohaha
2015-12-25 19:19:09 +08:00
@Killian 我作为一个正常用户,用浏览器访问豆瓣电影,翻到 35 页之后没有电影了,这是翻页请求优化?连用户都不用正常使用的优化。。
kelos
2015-12-25 19:53:29 +08:00
像一些 web 的通讯工作之类的,你们都可以抓?
geekboy
2015-12-25 20:00:04 +08:00
前几天用 java 在抓,现在豆瓣 apikey 不让申请了,我也遇到过几次 403~
quietin
2015-12-25 21:32:43 +08:00
@luohaha 忘了多谢你给我科普抓取过程和布隆过滤器了
luohaha
2015-12-25 21:51:18 +08:00
@geekboy 是吗?之前还申请过 douban 的 apikey 来做过一个应用。
luohaha
2015-12-25 21:52:22 +08:00
@kelos 什么意思?就是正常的爬虫抓取啊。
njutree
2015-12-25 22:02:32 +08:00
@luohaha 正常用户翻到 35 页也说明了用户的搜索不准确,用户应该做的是使用更准确的词再搜索才是更好的方式。不然除了给爬虫的人有便利其实意义不大,而且做过后端的人都知道分布式分页的问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/245884

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX