用正则获取百度贴吧当日新贴

工作中需要抓百度贴吧指定贴吧每日新贴,包括主题贴和回复贴。
按理说百度应该给吧主提供这样的功能。但我没找到。
百度还提供了个高级搜索功能 http://tieba.baidu.com/f/search/adv 。搜索结果可以按时间倒序排列,可惜必须设关键字或用户名。所以也不能满足需求。
想了个变通的办法。
1)每分钟爬一次首页,取到首页上最后回复者的用户名。
2)使用高级搜索,设定吧名和用户名搜索并提取发贴日期为结果。

[root@iZlmsymZ ~]$wget http://tieba.baidu.com/f?kw=%C9%BD%CE%F7 -O - | grep -Po 'href="(/p/[0-9]{10}).*?j_user_card.*?\>(.*?)\<.*?threadlist_reply_date j_reply_data.*?>[ ]*([0-9]{1,2}:[0-9]{2})' - | sed -r s/'href="(\/p\/[0-9]{10}).*?j_user_card[^>]*>([^<]*)<.*?threadlist_reply_date j_reply_data.*?>[ ]*([0-9]{1,2}:[0-9]{2})'/'\1\t\2\t\3'/g

 

wget -- linux 下获取 http页面的工具 -O - 表示输出到管道(而不是文件)

grep --linux 正则表达式工具

-P  使用 prel语法

-o  只输出匹配到的内容(而不是一行)

(/p/[0-9]{10}) 首页贴子的链接,格式为 a href="/p/3444444444"
.*? 非贪婪匹配任意字符
j_user_card.*?\>(.*?) 查找发贴人昵称,值为(.*?)
threadlist_reply_date j_reply_data.*?>[ ]*([0-9]{1,2}:[0-9]{2})  最后回复日期,值为([0-9]{1,2}:[0-9]{2})
首页中不能获取到最新回复贴的url。为了获取最新的帖子(无论是主题还是回复),需要以到 http://tieba.baidu.com/f/search/ures? 查询。查询条件是吧名和用户名。在找到的结果中,如果发贴时间匹配,那么就可以认为是刚才在首页查到的新贴,从而采集url.
wget http://tieba.baidu.com/f?kw=山西 -O - | grep -Po 'j_user_card.*?\>.*?\<' - | sed -r s/'j_user_card[^>]*>([^<]*)<'/'http:\/\/tieba\.baidu\.com\/f\/search\/ures\?ie=utf-8\&kw=山西\&un=\1'/g
j_user_card 是用户名所在的标签标识。用grep找到后,用sed提取并连接成url。结果如下:
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=佛光普照五台山
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=不见风雨见彩虹
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=★冰月寒心★
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=小伟苦笑
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=小伟苦笑
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=领域神王
http://tieba.baidu.com/f/search/ures?ie=utf-8&kw=山西&un=chenxin0357
……

 

[root@iZ62jhlmZ ~]$wget http://tieba.baidu.com/f?kw=山西 -O - | grep -Po 'j_user_card.*?\>.*?\<' - | sed -r s/'j_user_card.*?>([^<]*)<'/'\/f\/search\/ures\?ie=utf-8\&kw=山西\&un=\1'/g | wget --base=http://tieba.baidu.com -i - -O - | grep -Po '<div class="s_post".*?class="p_green p_date".*?>' >urlcheck.txt

 

上面使用 "wget -i - -O -"打开sed 组织的url,并使用grep提取相关内容到 urlcheck.txt中。 

 

 

grep -Po '<div class="s_post".*?class="p_green p_date".*?>'

在高级查询中查询到的记录,我们只取当天的。

[root@iZ62jhlmsZ ~]$grep "$(date --rfc-3339='date')"

 所以,提取一个用户当天发贴的语句是:

wget http://tieba.baidu.com/f?kw=山西 -O - | grep -Po 'j_user_card.*?\>.*?\<' - | sed -r s/'j_user_card.*?>([^<]*)<'/'\/f\/search\/ures\?ie=utf-8\&kw=山西\&un=\1'/g | wget --base=http://tieba.baidu.com -i - -O - | grep -Po "<div class=\"s_post\">.*?<font class=\"p_green p_date\">$(date --rfc-3339='date').*?<\/font>" |  sed s/'^.*<a.*href="\(.*\)" class.*>\(.*\)<\/a>.*<div.*>\(.*\)<\/div>.*<font.*>\(.*\)<\/font>.*<font.*>.*\([-0-9: ]\{16\}\)<\/font>.*$'/'\1\t\2\t\3\t\4\t\5'/g

 实际sed操作会出错,试着转成utf-8编码就正常了。

 iconv --from-code=latin1 --to-code=utf-8

原因解释:

"sed的执行会和locale相关。比如说如果文件的编码是gbk的,而locale是utf-8,这时候你所有关于正则表达式的知识都是不起作用的。根据我的经验用sed处理有中文字符处理的文件,最好把locale设置成LC_ALL=C,进行处理,或者你能保证文件的编码和locale是一致的情况下。" 

export LC_ALL=C

推荐使用 LC_ALL=C 因为转成utf-8会严重影响正则匹配的效率。

sed 的另一个问题是它不支持非贪婪匹配。所以在书写的时候费了很大周折。

另外还得删除重复的记录。

awk '!a[$0]{a[$0]=1;print  "/f/search/ures?rn=10&ie=utf-8&kw=山西&un="$0}' ./tiebaapp/tiebaactiveuser.lst&& :>./tiebaapp/tiebaactiveuser.lst |  wget -q  --base=http://tieba.baidu.com -i - -O - | grep -Po "<div class=\"s_post\">.*?<font class=\"p_green p_date\">$(date --rfc-3339='date').*?<\/font>" |  iconv --from-code=latin1 --to-code=utf-8 | sed s/'^.*<a.*href="\(.*\)" class.*>\(.*\)<\/a>.*<div.*>\(.*\)<\/div>.*<font.*>\(.*\)<\/font>.*<font.*>.*\([-0-9: ]\{16\}\)<\/font>.*$'/'\1\t\2\t\3\t\4\t\5'/g
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值