拖了好久的说,一开始只是为了自己用一下,正好又刚学python不久,写了一个命令行下可用的,后来突然捡起来觉得还是写个GUI让别人用更好。虽然现在博客已经不流行了,大家都在玩实名制的微博,但还是希望有人需要时可以有的用。接下来主要会看看能不能把日志里的图片和视频扒下来,有任何问题都欢迎和我联系。
利用Python解析新浪博客javascript生成的评论
【前言】sina2wordpress终于有一个大概模样了,目前版本号为0.1
这是本站项目地址,这是代码托管地址
言归正传,目前新浪博客的评论是用JavaScript生成的,直接用urllib2读取的信息中没有评论信息
通过Firefox下的firebug或者Chrome自带的Develop Tools,都可以找到js脚本在运行时GET的数据,具体方法是:打开之后选择“Network”标签,并选择“XHR”分类项,刷新页面并等待加载完成,稍等一会就会看到GET了一条以“comment”开头的html页面。
主要规律是,例如韩寒同学的这篇日志地址是 “http://blog.sina.com.cn/s/blog_4701280b0101854o.html”,那么打开日志页面时GET的就会是 “comment_4701280b0101854o_1.html”,规律不难发现,后面的那个数字就是评论的页数,最后的那个页数可以变为任意整数(没有尝试过上限),当超过实际评论页数时,显示的会是同样的编码,这也就是循环结束条件
此地址为相对路径,打开后是一堆乱码,这就是JavaScript的数据存储形式——json编码。可以简单的类比成Python中的字典,本例中共有两个关键字,一个是“Code”,对应值”A00006″,没发现啥用处,第二个关键字是“data”,其余部分均为data的对应值,利用Python的json模块进行解析可以发现,这就是评论的html代码。不过这里需要注意的是,第二个关键字“data”缺少双引号,直接解析会报错,需要先进行字符串处理,然后再解析。
相关代码如下(完整代码可以参见前言中的代码托管地址):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#根据json解析之后的html代码总结出来的各个关键信息的正则表达式 comment_author_pattern=re.compile(r'<span class="SG_revert_Tit".*?>(.*?)</span>') comment_url_pattern=re.compile(r'<a href="(.*?)" target="_blank">(.*?)</a>') comment_time_pattern=re.compile(r'<em class="SG_txtc">(.*?)</em>') comment_content_pattern=re.compile(r'<div class="SG_revert_Inner SG_txtb".*?>(.*?)</div>', re.S) #这里的re.S很重要 def commentsAnalyze(key): #key为地址中间的标识性字符串 num=1 #表示评论的页数 url=r'http://blog.sina.com.cn/s/comment_%s_%d.html' %(key, num) #生成json编码对应的地址 page=urllib2.urlopen(url).read().replace('data:','"data":',1) #给data添加双引号 while not 'noCommdate' in page: #noCommdata是无评论json编码页面的关键字 data=json.loads(page)['data'] #<strong>最关键的一部</strong>,json代码的解析并有效部分 #通过正则匹配出相关信息,其中url是可能存在的,将稍后处理 author=comment_author_pattern.findall(data) url=[] time=comment_time_pattern.findall(data) content=comment_content_pattern.findall(data) #后处理url,判断前面提取出来的author周边是不是带有<a>标签(超链接)即可 for i in range(len(author)): comment_id+=1 result=comment_url_pattern.search(author[i]) if result: url.append(result.group(1)) author[i]=result.group(2) else: url.append('') num+=1 #评论页数+1 url=r'http://blog.sina.com.cn/s/comment_'+key+'_'+str(num)+'.html' #生成新的页面地址 page=urllib2.urlopen(url).read().replace('data:','"data":',1) #修正data的双引号,重复循环 |
【后记】感谢 @lqs 学长和 北航开源俱乐部BHOSC的同胞们 在此问题上给予的帮助
精简WordPress eXtended Rss (WXR) 文件格式
经过N次Import和数据库清空,终于将之前的WXR文件格式的完备集简化了。
简化原则是适应Sina2WordPress项目的需要,尽可能精简文件大小,删除了导入无效的(如博客标题、博客链接等)和从新浪博客中无法获取的(如评论者的链接和IP等)信息,还有item之前的的作者、分类和标签信息。作者在导入时可以指定的,反而加上会有可能的错误,分类和标签的信息用post中的分类和标签就可以自动统计了。没想明白为什么非要单独列出来,难道是为了空的分类和标签,那还要它干嘛?
一些必不可少的标签及错误总结:
1、wxr_version,缺少会提示“missing/invalid WXR version number”的错误
2、status,否则都会显示成draft
3、post_type,否则无法导入
4、comment_approved,否则无法导入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
< ?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:excerpt="http://wordpress.org/export/1.1/excerpt/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wp="http://wordpress.org/export/1.1/" > <!--RSS版本号和名字空间的扩展,以上为固定内容--> <channel> <wp:wxr_version>1.1</wp:wxr_version> <!--WXR格式版本号--> <item><!--页面或者日志内容,每个为一个item--> <title>Title test</title> <!--标题--> <content:encoded>< ![CDATA[Content_test]]></content:encoded> <!--这里是正文内容--> <wp:post_date>2002-12-21 07:59:59</wp:post_date> <!--发表时间--> <wp:comment_status>open</wp:comment_status> <!--评论开启情况,open / closed--> <wp:status>publish</wp:status> <!--页面或日志状态,publish / draft / pending / private--> <wp:post_type>post</wp:post_type> <!--文章类型,post / page--> <wp:is_sticky>0</wp:is_sticky> <!--文章是否置顶,0 / 1--> <category domain="post_tag" nicename="tag_test">< ![CDATA[Tag Test]]></category> <category domain="category" nicename="category_test">< ![CDATA[Category Test]]></category> <!-- 日志或页面的标签和分类,可多个 domain:标签对应post_tag,分类对应category nicename:对应标签或分类的URL友好名称 <![CDATA[]]>:标签或分类的显示名称 --> <wp:comment><!--评论,可多个--> <wp:comment_id>1</wp:comment_id> <!--评论的id,主要用于博主回复的嵌套评论--> <wp:comment_author>< ![CDATA[anonymous]]></wp:comment_author> <!--评论者用户名--> <wp:comment_date>2012-12-21 07:59:59</wp:comment_date> <!--评论时间--> <wp:comment_content>< ![CDATA[Content of Comment]]></wp:comment_content> <!--评论内容--> <wp:comment_approved>1</wp:comment_approved> <!--评论是否被允许--> <wp:comment_parent>0</wp:comment_parent> <!--父评论,指定所回复的评论--> </wp:comment> </item> </channel> </rss> |