pcrec語言
❶ 如何優雅地使用c語言編寫爬蟲
前言
大家在平時或多或少地都會有編寫網路爬蟲的需求。一般來說,編寫爬蟲的首選自然非python莫屬,除此之外,java等語言也是不錯的選擇。選擇上述語言的原因不僅僅在於它們均有非常不錯的網路請求庫和字元串處理庫,還在於基於上述語言的爬蟲框架非常之多和完善。良好的爬蟲框架可以確保爬蟲程序的穩定性,以及編寫程序的便捷性。所以,這個cspider爬蟲庫的使命在於,我們能夠使用c語言,依然能夠優雅地編寫爬蟲程序。
爬蟲的特性
配置方便。使用一句設置函數,即可定義user agent,cookie,timeout,proxy以及抓取線程和解析線程的最大數量。
程序邏輯獨立。用戶可以分別定義爬蟲的解析函數,和數據持久化函數。並且對於解析到的新url,用戶可以使用cspider提供的addUrl函數,將其加入到任務隊列中。
便捷的字元串處理。cspider中提供了基於pcre的簡單的正則表達式函數,基於libxml2的xpath解析函數,以及用於解析json的cJSON庫。
高效的抓取。cspider基於libuv調度抓取線程和解析線程,使用curl作為其網路請求庫。
使用cspider的步驟
獲取cspider_t。
自定義user agent,cookie,timeout,proxy以及抓取線程和解析線程的最大數量。
添加初始要抓取的url到任務隊列。
編寫解析函數和數據持久化函數。
啟動爬蟲。
例子
先來看下簡單的爬蟲例子,會在後面詳細講解例子。
#include<cspider/spider.h>
/*
自定義的解析函數,d為獲取到的html頁面字元串
*/
void p(cspider_t *cspider, char *d, void *user_data) {
char *get[100];
//xpath解析html
int size = xpath(d, "//body/div[@class='wrap']/div[@class='sort-column area']/div[@class='column-bd cfix']/ul[@class='st-list cfix']/li/strong/a", get, 100);
int i;
for (i = 0; i < size; i++) {
//將獲取到的電影名稱,持久化
saveString(cspider, get[i]);
}
}
/*
數據持久化函數,對上面解析函數中調用的saveString()函數傳入的數據,進行進一步的保存
*/
void s(void *str, void *user_data) {
char *get = (char *)str;
FILE *file = (FILE*)user_data;
fprintf(file, "%s\n", get);
return;
}
int main() {
//初始化spider
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; ll=108288; viewed=1130500_24708145_6433169_4843567_1767120_5318823_1899158_1271597; __utma=30149280.927537245.1446813674.1446983217.1449139583.4; __utmz=30149280.1449139583.4.4.utmcsr=accounts.douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/login; ps=y; [email protected]; dbcl2=58742090:QgZ2PSLiDLQ; ck=T9Wn; push_noty_num=0; push_doumail_num=7; ap=1; __utmb=30149280.0.10.1449139583; __utmc=30149280";
//設置要抓取頁面的url
cs_setopt_url(spider, "so.tv.sohu.com/list_p1100_p20_p3_u5185_u5730_p40_p5_p6_p77_p80_p9_2d1_p101_p11.html");
//設置user agent
cs_setopt_useragent(spider, agent);
//cs_setopt_cookie(spider, cookie);
//傳入解析函數和數據持久化函數的指針
cs_setopt_process(spider, p, NULL);
//s函數的user_data指針指向stdout
cs_setopt_save(spider, s, stdout);
//設置線程數量
cs_setopt_threadnum(spider, DOWNLOAD, 2);
cs_setopt_threadnum(spider, SAVE, 2);
//FILE *fp = fopen("log", "wb+");
//cs_setopt_logfile(spider, fp);
//開始爬蟲
return cs_run(spider);
}
例子講解
cspider_t *spider = init_cspider();獲取初始的cspider。cs_setopt_xxx這類函數可以用來進行初始化設置。其中要注意的是: cs_setopt_process(spider,p,NULL);與cs_setopt_save(spider,s,stdout);,它們分別設置了解析函數p和數據持久化函數s,這兩個函數需要用戶自己實現,還有用戶自定義的指向上下文信息user_data的指針。
在解析函數中,用戶要定義解析的規則,並對解析得到的字元串可以調用saveString進行持久化,或者是調用addUrl將url加入到任務隊列中。在saveString中傳入的字元串會在用戶自定義的數據持久函數中得到處理。此時,用戶可以選擇輸出到文件或資料庫等。
最後調用cs_run(spider)即可啟動爬蟲。
具體的API參數可在這里查看
總結
趕快使用cspider爬蟲框架來編寫爬蟲吧!如果在使用過程中發現bug,歡迎反饋。
望採納,謝謝
❷ C語言的正則表達式相關提問。
prce是著名的開源正則庫,源碼是C。包括php,perl,python等語言都在直接或間接使用該庫。
pcre *re 指向整個庫對象或結構體的指針,
pcre 意思Perl Compatible Regular Expressions,perl語言兼容型正則(庫)
re意思regular expression正則
頭文件、源碼去pcre官網下載。
頭文件的詳解,就要看文檔,學習調用和使用該庫。
文檔都寫著。
另外這個庫是為開發者准備的正則中間件,嵌入程序中,使程序能解析正則。
不是專為正則的初學者練習正則而設置。學習文檔會不少,
需要熟練整個c庫操作流程和常用原理後直接去看源碼。
❸ 如何在線安裝pcre
pcre是一個c語言正規匹配庫根據不同的發行版所提供的工具有不同的檢查方法比如debian系可以使用dpkg來查看比如使用dpkg -l | grep pcre 通過grep匹配然後從輸出的列表中查找是否有相應安裝的東西比如arch可以使用pacman -Qs來進行檢查gentoo可以使用emerge -pl查看等等總之不同的發行版查詢的方法不同另一方面也可以使用man或者info這種方法間接查詢,雖然並不太准備但也不失一種方法比如使用man pcre_exec或者info pcre,如果沒有結果可能就沒有安裝或者也可以去/usr/include目錄下查看是否有pcre.h這個頭文件以及到/lib或者/usr/lib等等地方查看是否有相關庫以及使用gcc編譯一個使用了pcre庫的源代碼使用-lpcre參數進行鏈接查看當然這些方法並不準備,只能作為參考,還是應該熟悉自己發行版所提供的工具一般為包管理工具
❹ c語言 正則庫 pcre 教程 (windows環境)
1、編譯PCRE正則表達式庫
(1) (MinGW + MSYS)
將PCRE源碼包直接拷貝到MSYS目錄下,(如:C:\MSYS\1.0\pcre\)
運行msys.bat啟動MSYS,
在命令行輸入
cd / // 回根目錄
cd pcre // 進入PCRE目錄
./configure // 配置編譯
make // 編譯全部
完成後,會在C:\MSYS\1.0\pcre\.libs\ 下生成所需要的文件:
libpcre-0.dll // PCRE的動態鏈接庫
libpcre.dll.a // 調用PCRE動態鏈接庫所用的LIB
libpcre.a // PCRE靜態鏈接庫
再配合上C:\MSYS\1.0\pcre\目錄下的"pcre.h",就可以在程序中加入正則表達式支持了:)
(2) (於windows平台手動編譯pcre,轉載)
將 config.h.generic 重命名為 config.h
設置其中的 HAVE_BCOPY 參數為 0 (因為windows平台無b()函數)
重命名 pcre.h.generic 為 pcre.h.
重命名 pcre_chartables.c.dist 為 pcre_chartables.c.
編譯 dftables.c 成可執行文件,要加入參數 -DHAVE_CONFIG_H,以便導入 config.h 文件中的設置
/* 重命名 pcre_chartables.c.dist 為 pcre_chartables.c */
運行編譯的可執行文件 dftables.exe ,參數為 pcre_chartables.c
即 dftables.exe pcre_chartables.c
新建工程,包含下列文件,編譯成lib文件即可
pcre_internal.h
ucp.h
ucpinternal.h
ucptable.h
pcre_chartables.c
pcre_compile.c
pcre_config.c
pcre_dfa_exec.c
pcre_exec.c
pcre_fullinfo.c
pcre_get.c
pcre_globals.c
pcre_info.c
pcre_maketables.c
pcre_newline.c
pcre_ord2utf8.c
pcre_refcount.c
pcre_study.c
pcre_tables.c
pcre_try_flipped.c
pcre_ucp_searchfuncs.c
pcre_valid_utf8.c
pcre_version.c
pcre_xclass.c
這樣就可以生成 libpcre.a 文件了 (vc,bcc生成的是pcre.lib,大同小異)
2、使用生成的 libpcre.a (靜態鏈接庫)
在你的程序中添加:
#define PCRE_STATIC // 開啟靜態鏈接庫支持(一定要添加該行,否則無法使用靜態鏈接庫)
#include "pcre.h" // PCRE頭文件
並且添加 libpcre.a 到工程中,然後就可以在程序中使用PCRE函數了:)
編譯選項 添加 /MT ,無頭文件預編譯.
3、使用生成的 libpcre-0.dll 和 libpcre.dll.a (動態鏈接庫)
在你的程序中添加:
#include "pcre.h" // PCRE頭文件
並且添加 libpcre.dll.a 到工程中,然後就可以在程序中使用PCRE函數了:)
================================================================================
命令行下的批處理解決方法 .如果已經下載,可以不用第一行.
goto START
首先確保控制台環境中有:
1、VC6命令行編譯環境
2、wget.exe、unzip.exe、sed.exe、mv.exe
然後執行這個批處理文件,就可以得到VC版本的pcr.lib。
:START
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.7.zip
unzip pcre-7.7.zip
cd pcre-7.7
sed -e "s/#define HAVE_BCOPY 1/#define HAVE_BCOPY 0/g" config.h.generic > config.h
mv pcre.h.generic pcre.h
mv pcre_chartables.c.dist pcre_chartables.c
cl -MD -DHAVE_CONFIG_H dftables.c
dftables.exe pcre_chartables.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_chartables.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_compile.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_config.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_dfa_exec.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_exec.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_fullinfo.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_get.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_globals.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_info.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_maketables.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_newline.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_ord2utf8.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_refcount.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_study.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_tables.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_try_flipped.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_ucp_searchfuncs.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_valid_utf8.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_version.c
cl -O1 -MD -DHAVE_CONFIG_H -c pcre_xclass.c
lib -out:libpcr.lib pcre_chartables.obj pcre_compile.obj pcre_config.obj pcre_dfa_exec.obj pcre_exec.obj pcre_fullinfo.obj pcre_get.obj pcre_globals.obj pcre_info.obj pcre_maketables.obj pcre_newline.obj pcre_ord2utf8.obj pcre_refcount.obj pcre_study.obj pcre_tables.obj pcre_try_flipped.obj pcre_ucp_searchfuncs.obj pcre_valid_utf8.obj pcre_version.obj pcre_xclass.obj
這樣就出來了: pcre.h + libpcr.lib
==============================================================================
最近使用VC編譯了一下她的源代碼,其實步驟很簡單, 如下
1 一些源文件改名
config.h.generic 改名為 config.h (注意裡面的配置)
pcre.h.generic 改名為 pcre.h
pcre_chartables.c.dist 改名為 pcre_chartables.c
2 建立VC工程
建立一個VC的DLL工程,去掉原有的包含文件
將PCRE的所有pcre_*.c都加進去, pcre後面沒有_的不要加, 後綴名是.cc的不要加
可以參考上面的.還有.h 文件也是要的.
3 修改工程設置
增加工程預編譯宏 HAVE_CONFIG_H
不使用預編譯頭 Not Using Precompiled Headers
編譯選項 添加 /MT
OK 完成以上三步,就可以在 VC 上編譯通過了。
4 編譯結果
使用時只需要編譯出來的 .DLL .Lib 和 源代碼目錄的 pcre.h
❺ 這個c語言題目怎麼在子函數里換字元串
圖片看得並不是太清楚
大概看清是字元串替換
其實字元串替換注意的就是替換後的長度與替換前長度的不同
如果替換後的長度比替換前的長度要長則原有存儲字元串的數組就會溢出
所以需要替換時動態更改數組大小
下面是我曾經寫的一個簡單的代碼
它可以進行字元串替換
並且還簡單地支持正則表達式來對字元串進行替換
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pcre.h>
char*strrep(constchar*str,constchar*need,constchar*repto,intsub)
{
pcre*re;
constchar*errptr;
interroffset;
int*ovector;
intsrc_len=strlen(str);//要處理的字元串的長度
intrep_len=strlen(repto);//要替換的字元串的長度
intoffset=0;//匹配後在字元串中的偏移量
char*res=NULL;//保存最終結果
intres_len=0;//替換後的字元串的長度
intlen;//當前已替換後的字元串的長度
char*temp;//臨時變數
if((ovector=malloc(sizeof(int)*(sub+1)*3))==NULL)//開辟足夠大的內存來保存匹配後的偏移量
returnNULL;
if((re=pcre_compile(need,0,&errptr,&erroffset,NULL))==NULL)
returnNULL;
while(pcre_exec(re,NULL,str,src_len,offset,0,ovector,(sub+1)*3)>0)//循環匹配,不然只能匹配到一個結果
{
res_len+=ovector[sub*2]-offset+rep_len;//計算當前替換後字元串的長度
if(res)
{
len=strlen(res);
temp=malloc(sizeof(char)*len+1);
snprintf(temp,len+1,"%s",res);
free(res);//臨時保存之前替換的結果
res=malloc(sizeof(char)*res_len+1);
snprintf(res,len+1,"%s",temp);
free(temp);//增大內存
strncat(res,str+offset,ovector[sub*2]-offset);//將不需要替換的字元串復制
strncat(res,repto,rep_len);//進行替換
}
else
{
res=malloc(sizeof(char)*res_len+1);//第一次匹配
snprintf(res,ovector[sub*2]+1,"%s",str);//復制不需要替換的字元串
strncat(res,repto,rep_len);//進行替換
}
offset=ovector[sub*2+1];//增加偏移量,進行下一循環
}
if(offset!=0&&offset<src_len)//如果所替換的字元串後面還有數據則進行復制
{
temp=malloc(sizeof(char)*res_len+1);
snprintf(temp,res_len+1,"%s",res);
free(res);
res=malloc(sizeof(char)*res_len+src_len-offset+1);
snprintf(res,res_len+src_len-offset+1,"%s%s",temp,str+offset);
free(temp);
}
pcre_free(re);//這里的兩個地方是讓我頭痛了一陣的地方,釋放的時候總是出現不「科學」的事情,後來發現是開辟內存時沒有指定類型導致出錯(前面的sizeof)這里特意注釋下
free(ovector);
returnres;
}
intmain(intargc,char**argv)
{
char*res;
constchar*src="<title>1234</title>456</title><title>789</title><title>fjdsklfjdsklf</title>";
res=strrep(src,"<title>(.*?)</title>","替換後的結果",1);
if(res==NULL)
printf("%s ",src);
else
{
printf("%s ",res);
free(res);
}
return0;
}
❻ 怎麼通過C語言讀取網頁裡面的數據
簡單的請求格式
GET /index.php HTTP/1.0
host:www.zixue7.com
當我們和伺服器連接上之後,發送上面的數據過去,伺服器就會返回 index.php 這個頁面給我們。
GET 這個 是表示 以什麼方式請求,HTTP中還有很多其他的請求方式,常用的就 GET POST (更詳細的 可以點開上面 http協議 那個鏈接)
GET 後面緊跟一個空格 然後 給出,要獲取的資源的名稱, /index.php 就表示獲取網站伺服器根目錄下 index.php 執行後所產生的內容,我們也可以改成 GET / HTTP/1.0 這就表示獲取默認首頁的內容 。 GET /1.html HTTP/1.0 就是獲取 伺服器根目錄下 1.html的內容,很容易理解吧。
接下來隔一個空格 跟上 HTTP/1.0 表示 http協議的版本,這個是固定的 。
第二行 host:www.zixue7.com 用來指定 訪問哪個主機。 大家都知道,一個伺服器可以放很多個網站,每個網站有不同的域名,所以我們需要用這個host來指定 我們要訪問的是哪個網站,這樣 才能正確得訪問到我們想訪問的網站。
第一步,連接伺服器。
第二步,按照http協議,發送請求數據,然後就是接受返回的內容。
沒錯,就這么簡單。
在編寫程序之前,我們先用一個小工具來模擬一下這個過程,好讓我們對http協議了解更深入一些。
telnet工具 如果是 win7下的朋友 猛戳這里-->win7開啟telnet功能
到此為止,我假設大家電腦上已經開啟了 telnet功能,正題開始。
telnet 他是一個基於tcp/ip 協議的程序,為我們用戶提供一個 與其他電腦通信的工具,我們可以使用他來和其他電腦進行連接通信。
開始->運行->輸入telnet回車, 出現一個黑框如下。
我們這時就可以輸入命令,來連接遠程主機,比如我們這次是要連接我們自學去論壇 的伺服器,
那麼我們就輸入 open www.zixue7.com 80 然後回車。
open 是打開的意思 後面跟上 要打開那個主機 然後 後面跟上埠, web伺服器默認使用的是80埠,所以 要加上80埠(不加埠 telnet默認是23埠)。
然後會出現下圖的情況,這時候 我們就可以輸入命令了,輸入的命令都將被發送到自學去論壇的伺服器上面。大家注意一下 下圖紅色箭頭所指出的部分,那裡就是一個輸入游標,不用管其他的字。
這就代表 我們已經和遠程主機連接上了,就相當於我們上節課中 客戶端執行到 connect 函數 之後 就是要調用 send函數發送數據了,在這里 我們只需要按鍵盤輸入到黑色窗口中 就會發送到服務端。
我們依次輸入以下內容,(注意,不能按退格,輸入錯誤了,就重新打開telnet,重新操作。)
❼ 怎麼檢查 linux是否安裝 pcre
1、連接上相應的linux主機,進入到等待輸入shell指令的linux命令行狀態下。
❽ 除了pcre,支持linux c語言的正則表達式庫有哪些
REEC我沒用過,我平時用的是#include <regex.h>
原來寫過一個代碼例子在csdn上面,C 和C++都能用
http://download.csdn.net/detail/ace_fei/4722736
❾ C語言,如何對網頁進行操作
首先,你這個想法還是很不錯的,我以前也想這么做過。不過,學習html語言在這里肯定是次要的,主要的還是要學會分析的方法,而不是掌握被分析的內容,你說是吧?如果要用程序抓取網頁自動保存到本地,就要會用socket編程,或者學習使用libcurl庫,這些都比學html語言有用的多,不做網頁抓取的時候,這些知識依然非常有用。而且,不同的網頁,內容不同,規律可能也不同。比如你給的那個例子網址,我右鍵查看了源代碼,裡面就根本沒有所謂的<td>、<tr>標簽,即它的表格不是通過這些標簽來實現的。所以,讓你去看這些標簽,就是南轅北轍了。網頁分析,說到底還是字元串處理和分析。所以,你如果真的想學,不如好好學一下正則表達式和字元串處理相關的函數,以及函數庫,比如tidy庫等。正則表達式是用來匹配一類字元串的,方便找規律,也方便處理,你稍微學習一點點就知道有多麼的強大,多麼的有用了。而且,正則表達式跟語言無關,什麼語言都能用得到,學這個不虧的。標准C庫中沒有正則表達式相關的函數,一般來說C中使用兩種正則表達式庫,一為POSIX
C正則庫,二為perl正則庫PCRE。相比較而言PCRE要強大些,POSIX
C正則庫就足夠使用。下面,這幾個鏈接裡面有網頁分析的一些例子,雖然不都是C語言來處理的。但是,思路都是一致的。
所以,說到底,還是正則表達式、正則函數庫、字元串處理函數這些才是根本。先說這些,希望對你有所幫助。如果你在學習過程中還有什麼問題,歡迎隨時交流:)C#的: http://www.jb51.net/article/16618.htmC#的: http://mytiu.blog.163.com/blog/static/1059718452009127112226478/這里還有一段C語言的代碼,
是將下載下來的網頁源代碼處理成沒有標簽的純文字文本#include
<tidy.h>#include
<buffio.h>#include
<stdio.h>#include
<errno.h>int
main(int
argc,
char
**argv
){const
char*
input
=
"<title>Foo</title>
Foo!";TidyBuffer
output
=
{0};TidyBuffer
errbuf
=
{0};int
rc
=
-1;Bool
ok;TidyDoc
tdoc
=
tidyCreate();
//
Initialize
"document"printf(
"Tidying:\t%s\n",
input
);ok
=
tidyOptSetBool(
tdoc,
TidyXhtmlOut,
yes
);
//
Convert
to
XHTMLif
(
ok
)rc
=
tidySetErrorBuffer(
tdoc,
&errbuf
);
//
Capture
diagnosticsif
(
rc
>=
0
)rc
=
tidyParseString(
tdoc,
input
);
//
Parse
the
inputif
(
rc
>=
0
)rc
=
tidyCleanAndRepair(
tdoc
);
//
Tidy
it
up!if
(
rc
>=
0
)rc
=
tidyRunDiagnostics(
tdoc
);
//
Kvetchif
(
rc
>
1
)
//
If
error,
force
output.rc
=
(
tidyOptSetBool(tdoc,
TidyForceOutput,
yes)
?
rc
:
-1
);if
(
rc
>=
0
)rc
=
tidySaveBuffer(
tdoc,
&output
);
//
Pretty
Printif
(
rc
>=
0
){if
(
rc
>
0
)printf(
"\nDiagnostics:\n\n%s",
errbuf.bp
);printf(
"\nAnd
here
is
the
result:\n\n%s",
output.bp
);}elseprintf(
"A
severe
error
(%d)
occurred.\n",
rc
);tidyBufFree(
&output
);tidyBufFree(
&errbuf
);tidyRelease(
tdoc
);return
rc;}