html - 从 C 中的 HTML 中提取所有 URL
问题描述
如何使用 C 标准库提取 HTML 中的所有 URL?
我正在尝试使用sscanf()来处理它,但是valgrind给出了错误(我什至不确定代码在调试成功后是否能满足我的要求,所以如果有其他方法,请告诉我)。我将 html 内容存储在一个字符串指针中,有多个 URL(包括绝对 URL 和相对 URL,例如http ://www.google.com、//www.google.com、/a.html、a.html 和等等)在里面。我想一个一个地提取它们并将它们分别存储到另一个字符串指针中。
我也在考虑使用 strstr(),但是我不知道如何获取第二个 url。
我的代码(我在这里跳过断言)使用 sscanf:
int
main(int argc, char* argv[]) {
char *remain_html = (char *)malloc(sizeof(char) * 1001);
char *url = (char *)malloc(sizeof(char) * 101);
char *html = "<A HREF=\"http://www.google.com\">navigation</a>"
"<a href=\"/a.html\">search</a>";
printf("html: %s\n\n", html);
sscanf(html, "<a href=\"%s", remain_html);
printf("after first href tag: %s\n\n", remain_html);
sscanf(remain_html, "%s\">", url);
printf("first web: %s\n\n", url);
sscanf(remain_html, "<a href=\"%s", remain_html);
printf("after second href tag: %s\n\n", remain_html);
free(remain_html);
free(url);
}
valgrind 给出:有条件的跳转或移动取决于未初始化的值。
如果有人可以提供帮助,非常感谢!
解决方案
valgrind警告您有关未初始化的数据(用于测试),考虑到您的程序仅执行sscanf和printf这意味着您的scanf很可能有问题
如果我对您的程序稍作更改以打印sscanf的结果,那么请显示它得到的许多元素:
int
main(int argc, char* argv[]) {
char *remain_html = (char *)malloc(sizeof(char) * 1001);
char *url = (char *)malloc(sizeof(char) * 101);
char *html = "<A class=\"mw-jump-link\" HREF=\"#mw-head\">Jump to navigation</a>"
"<a class=\"mw-jump-link\" href=\"#p-search\">Jump to search</a>";
printf("html: %s\n\n", html);
printf("%d\n", sscanf(html, "<a href=\"%s", remain_html));
printf("after first href tag: %s\n\n", remain_html);
printf("%d\n", sscanf(remain_html, "%s\">", url));
printf("first web: %s\n\n", url);
printf("%d\n", sscanf(remain_html, "<a href=\"%s", remain_html));
printf("after second href tag: %s\n\n", remain_html);
free(remain_html);
free(url);
}
执行是:
pi@raspberrypi:/tmp $ ./a.out
html: <A class="mw-jump-link" HREF="#mw-head">Jump to navigation</a><a class="mw-jump-link" href="#p-search">Jump to search</a>
0
after first href tag:
-1
first web:
-1
after second href tag:
pi@raspberrypi:/tmp $
所以第一个scanf什么都没有(0元素),这意味着它没有设置remain_html ,并且当下一个sscanf使用未定义的行为时,它没有被初始化
因为格式
"<a href=\"%s"
第一个sscanf等待一个由
<a href="
但html开始于
<A class=
这是不同的,所以它从第二个字符停止并且不设置保持_html
使用sscanf不是正确的方法,搜索前缀<a href="可能是大写的,例如使用strcasestr,然后提取 URL 直到结束 "
例子 :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* in case you do not have that function */
char * strcasestr(char * haystack, char *needle)
{
while (*haystack) {
char * ha = haystack;
char * ne = needle;
while (tolower(*ha) == tolower(*ne)) {
if (!*++ne)
return haystack;
ha += 1;
}
haystack += 1;
}
return NULL;
}
int main(int argc, char* argv[]) {
char *html = "<A HREF=\"http://www.google.com\">navigation</a>"
"<a href=\"/a.html\">search</a>";
char * begin = html;
char * end;
printf("html: %s\n", html);
while ((begin = strcasestr(begin, "<a href=\"")) != NULL) {
begin += 9; /* bypass the header */
end = strchr(begin, '"');
if (end != NULL) {
printf("found '%.*s'\n", (int) (end - begin), begin);
begin = end + 1;
}
else {
puts("invalid url");
return -1;
}
}
}
编译和执行:
pi@raspberrypi:/tmp $ gcc -Wall a.c
pi@raspberrypi:/tmp $ ./a.out
html: <A HREF="http://www.google.com">navigation</a><a href="/a.html">search</a>
found 'http://www.google.com'
found '/a.html'
pi@raspberrypi:/tmp $
注意我知道strcasestr的第二个参数是小写的,所以做tolower(*ne)和*ne就足够了,但是我在当前上下文之外给出了函数的定义
推荐阅读
- ios - 无法获得 url 的下划线并检测 url 后的空格
- reactjs - 如何在不使用映射的情况下使用变量访问数组元素
- qt - 在 QT QML Map 中显示标记
- c# - WPF INotifyPropertyChanged 两种方式绑定奇怪的动作
- python - 如何使用opencv python比较非矩形ROI
- web-scraping - Python 3.7- PhantomJS - Driver.get(url) 与“窗口句柄/名称无效或关闭?”
- javascript - 将 axios 请求的响应推送到数组中
- codeigniter - Codeigniter中的内部连接与多个表
- angular - Angular Subject 不听变化
- c++ - 无法使用 fstream 从二进制文件中读取字符串,而是显示奇怪的符号