Python编程-利用爬虫配合dedecms全自动采集发布

《Python编程-利用爬虫配合dedecms全自动采集发布》要点:
本文介绍了Python编程-利用爬虫配合dedecms全自动采集发布,希望对您有用。如果有疑问,可以联系我们。

之前想实现一个爬虫,实时采集别人的文章,根据自己的规则去修改采集到的文章,然后自动发布.决定用dedecms做新闻发布,还可以自动生成html,自动把远程图片本地化等一些优点,为了安全,完全可以把前后台分离.

起初想用scrapy爬虫框架去实现,觉得定制开发的话用scrapy只能用到里面的一些基础的功能,有一些情况要跟着框架的规则走,如果自己写的话可以自己写规则去处理,也有优点爬虫、处理器等,最后还是自己写了一个demo.

首先分析需求,python做爬虫,dedecms做发布,起初先考虑了发布功能,实现了模拟登陆,或者研究dedecms的数据库设计,直接写到数据库,实际中没有这样去做,开始做模拟登陆的时候,需要改dedecms的代码去掉验证码,不然还要实现验证码识别,这个完全没有必要,因为要发布的是自己的网站,自己也有账户、密码、发布文章权限,然后就改了下dedecms的登陆功能,加了一个登陆接口,分析了dedecms的发布文章HTTP数据包.这块搞定了后就开始设计爬虫了,最后设计的感觉和scrapy的一些基础的处理机制很像.

做dedecms的登陆接口如下:

后台目录下的config.php 34行找到

/**

//检验用户登录状态

$cuserLogin = new userLogin();

if($cuserLogin->getUserID()==-1)

{

header(“location:login.php?gotopage=”.urlencode($dedeNowurl));

exit();

}

**/

改为下面

//http://127.0.0.2/dede/index.php?username=admin&password=admin

123456789101112$cuserLogin = new userLogin();if($cuserLogin->getUserID()==-1) {if($_REQUEST['username'] != ''){$res = $cuserLogin->checkUser($_REQUEST['username'],$_REQUEST['password']);if($res==1) $cuserLogin->keepUser();}if($cuserLogin->getUserID()==-1) {header("location:login.php?gotopage=".urlencode($dedeNowurl));exit();}}

这样只要请求:http://127.0.0.2/dede/index.php?username=admin&password=admin 就可以得到一个sessionid,只要用这个sessionid去发布文章就可以了.

发布文章的HTTP数据包如下:

#http://127.0.0.2/dede/article_add.php

POST /dede/article_add.php HTTP/1.1

Host: 127.0.0.2

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3

Accept-Encoding: gzip,deflate

Referer: http://127.0.0.2/dede/article_add.php?cid=2

Cookie: menuitems=1_1%2C2_1%2C3_1; CNZZDATA1254901833=1497342033-1472891946-%7C1473171059; Hm_lvt_a6454d60bf94f1e40b22b89e9f2986ba=1472892122; ENV_GOBACK_URL=%2Fmd5%2Fcontent_list.php%3Farcrank%3D-1%26cid%3D11; lastCid=11; lastCid__ckMd5=2f82387a2b251324; DedeUserID=1; DedeUserID__ckMd5=74be9ff370c4536f; DedeLoginTime=1473174404; DedeLoginTime__ckMd5=b8edc1b5318a3923; hasshown=1; Hm_lpvt_a6454d60bf94f1e40b22b89e9f2986ba=1473173893; PHPSESSID=m2o3k882tln0ttdi964v5aorn6

Connection: keep-alive

Upgrade-Insecure-Requests: 1

Content-Type: multipart/form-data; boundary=—————————2802133914041

Content-Length: 3639

—————————–2802133914041

Content-Disposition: form-data; name=”channelid”

1

—————————–2802133914041

Content-Disposition: form-data; name=”dopost”

save

—————————–2802133914041

Content-Disposition: form-data; name=”title”

2222222222

—————————–2802133914041

Content-Disposition: form-data; name=”shorttitle”

—————————–2802133914041

Content-Disposition: form-data; name=”redirecturl”

—————————–2802133914041

Content-Disposition: form-data; name=”tags”

—————————–2802133914041

Content-Disposition: form-data; name=”weight”

100

—————————–2802133914041

Content-Disposition: form-data; name=”picname”

—————————–2802133914041

Content-Disposition: form-data; name=”litpic”; filename=””

Content-Type: application/octet-stream

—————————–2802133914041

Content-Disposition: form-data; name=”source”

—————————–2802133914041

Content-Disposition: form-data; name=”writer”

—————————–2802133914041

Content-Disposition: form-data; name=”typeid”

2

—————————–2802133914041

Content-Disposition: form-data; name=”typeid2″

—————————–2802133914041

Content-Disposition: form-data; name=”keywords”

—————————–2802133914041

Content-Disposition: form-data; name=”autokey”

1

—————————–2802133914041

Content-Disposition: form-data; name=”description”

—————————–2802133914041

Content-Disposition: form-data; name=”dede_addonfields”

—————————–2802133914041

Content-Disposition: form-data; name=”remote”

1

—————————–2802133914041

Content-Disposition: form-data; name=”autolitpic”

1

—————————–2802133914041

Content-Disposition: form-data; name=”needwatermark”

1

—————————–2802133914041

Content-Disposition: form-data; name=”sptype”

hand

—————————–2802133914041

Content-Disposition: form-data; name=”spsize”

5

—————————–2802133914041

Content-Disposition: form-data; name=”body”

2222222222

—————————–2802133914041

Content-Disposition: form-data; name=”voteid”

—————————–2802133914041

Content-Disposition: form-data; name=”notpost”

0

—————————–2802133914041

Content-Disposition: form-data; name=”click”

70

—————————–2802133914041

Content-Disposition: form-data; name=”sortup”

0

—————————–2802133914041

Content-Disposition: form-data; name=”color”

—————————–2802133914041

Content-Disposition: form-data; name=”arcrank”

0

—————————–2802133914041

Content-Disposition: form-data; name=”money”

0

—————————–2802133914041

Content-Disposition: form-data; name=”pubdate”

2016-09-06 23:07:52

—————————–2802133914041

Content-Disposition: form-data; name=”ishtml”

1

—————————–2802133914041

Content-Disposition: form-data; name=”filename”

—————————–2802133914041

Content-Disposition: form-data; name=”templet”

—————————–2802133914041

Content-Disposition: form-data; name=”imageField.x”

41

—————————–2802133914041

Content-Disposition: form-data; name=”imageField.y”

6

—————————–2802133914041–

#更新生成html请求

http://127.0.0.2/dede/task_do.php?typeid=2&aid=109&dopost=makeprenext&nextdo=

GET /dede/task_do.php?typeid=2&aid=109&dopost=makeprenext&nextdo= HTTP/1.1

Host: 127.0.0.2

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0

Accept: text/html,deflate

Referer: http://127.0.0.2/dede/article_add.php

Cookie: menuitems=1_1%2C2_1%2C3_1; CNZZDATA1254901833=1497342033-1472891946-%7C1473171059; Hm_lvt_a6454d60bf94f1e40b22b89e9f2986ba=1472892122; ENV_GOBACK_URL=%2Fmd5%2Fcontent_list.php%3Farcrank%3D-1%26cid%3D11; lastCid=11; lastCid__ckMd5=2f82387a2b251324; DedeUserID=1; DedeUserID__ckMd5=74be9ff370c4536f; DedeLoginTime=1473174404; DedeLoginTime__ckMd5=b8edc1b5318a3923; hasshown=1; Hm_lpvt_a6454d60bf94f1e40b22b89e9f2986ba=1473173893; PHPSESSID=m2o3k882tln0ttdi964v5aorn6

Connection: keep-alive

Upgrade-Insecure-Requests: 1

通过上面数据包可以分析到如下结果:

POST http://127.0.0.2/dede/article_add.php

需要配置的参数:

channelid:1 #普通文章提交

dopost:save #提交方式

shorttitle:” #短标题

autokey:1 #自动获取关键词

remote:1 #不指定缩略图,远程自动获取缩略图

autolitpic:1 #提取第一个图片为缩略图

sptype:auto #自动分页

spsize:5 #5k大小自动分页

notpost:1 #禁止评论

sortup:0 #文章排序、默认

arcrank:0 #阅读权限为开放浏览

money: #消费金币0

ishtml:1 #生成html

title:”文章标题” #文章标题

source:”文章来源” #文章来源

writer:”文章作者” #文章作者

typeid:”主栏目ID2″ #主栏目ID

body:”文章内容” #文章内容

click:”文章点击量” #文章点击量

pubdate:”提交时间” #提交时间

然后开始模拟dedecms发布文章测试了,python代码如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859#!/usr/bin/python#coding:utf8import requests,random,time#访问登陆接口保持cookiessid = requests.session()login_url = "http://127.0.0.2/dede/index.php?username=admin&password=admin"header = { "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0","Referer" :"http://127.0.0.2"}#登陆接口获取Cookiesloadcookies = sid.get(url = login_url,headers = header)#进入增加文章页面#get_html = sid.get('http://127.0.0.2/dede/article_add.php?channelid=1',headers = header)#print get_html.content#定义固定字段article = {'channelid':1,#普通文章提交'dopost':'save',#提交方式'shorttitle':'',#短标题'autokey':1,#自动获取关键词'remote':1,#不指定缩略图,远程自动获取缩略图'autolitpic':1,#提取第一个图片为缩略图'sptype':'auto',#自动分页'spsize':5,#5k大小自动分页'notpost':1,#禁止评论'sortup':0,#文章排序、默认'arcrank':0,#阅读权限为开放浏览'money': 0,#消费金币0'ishtml':1,#生成html'click':random.randint(10,300),#随机生成文章点击量'pubdate':time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()),#s生成当前提交时间}#定义可变字段article['source'] = "文章来源" #文章来源article['writer'] = "文章作者" #文章作者article['typeid'] = "2" #主栏目ID#定义提交文章请求URLarticle_request = "http://127.0.0.2/dede/article_add.php""""#测试提交数据article['title'] = "测试_文章标题" #文章标题article['body'] = "测试_文章内容" #文章内容#提交后会自动重定向 生成html,http返回状态为200则成功!res = sid.post(url = article_request,data = article,headers = header)print res"""for i in range(50): article['title'] = str(i) + "_文章标题" #文章标题 article['body'] = str(i) + "_文章内容" #文章内容 #print article res = sid.post(url = article_request,headers = header) print res

其次就是分析爬虫需求阶段了,如下:

收集采集页面:

http://www.tunvan.com/col.jsp?id=115

http://www.zhongkerd.com/news.html

http://www.qianxx.com/news/field/

http://www.ifenguo.com/news/xingyexinwen/

http://www.ifenguo.com/news/gongsixinwen/

每一个采集页面和要改的规则都不一样,发布文章的栏目可能也有变化,要写多个爬虫,一个爬虫实现不了这个功能,要有爬虫、处理器、配置文件、函数文件(避免重复写代码)、数据库文件.

数据库里面主要是保存文章url和标题,主要是判断这篇文章是否是更新的,如果已经采集发布了就不要重复发布了,如果不存在文章就是最新的文章,需要写入数据库并发布文章.数据库就一个表几个字段就好,采用的sqlite3,数据库文件db.dll建表如下:

123456CREATE TABLE history (id INTEGER PRIMARY KEY ASC AUTOINCREMENT,url VARCHAR( 100 ),title TEXT,DATE DATETIME DEFAULT ( ( datetime( 'now','localtime' ) ) ));

架构设计如下:

│ db.dll #sqlite数据库

│ dede.py #测试dede登陆接口

│ function.py #公共函数

│ run.py #爬虫集开始函数

│ settings.py #爬虫配置设置

│ spiders.py #爬虫示例

│ sqlitestudio-2.1.5.exe #sqlite数据库编辑工具

│ __init__.py #前置方法供模块用

dede.py如下:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#!/usr/bin/python#coding:utf8import requests,timeimport lxml#定义域名domain = "http://127.0.0.2/"admin_dir = "dede/"houtai = domain + admin_dirusername = "admin"password = "admin"#访问登陆接口保持cookiessid = requests.session()login_url = houtai + "index.php?username=" + username + "&password=" + passwordheader = { "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0","Referer" : domain}#登陆接口获取Cookiesloadcookies = sid.get(url = login_url,headers = header)#定义固定字段article = {'channelid':1,#s生成当前提交时间}#定义可变字段article['source'] = "文章来源" #文章来源article['writer'] = "文章作者" #文章作者article['typeid'] = "2" #主栏目ID#定义提交文章请求URLarticle_request = houtai + "article_add.php""""#测试提交数据article['title'] = "11测试_文章标题" #文章标题article['body'] = "11测试_文章内容" #文章内容#提交后会自动重定向 生成html,headers = header)print res""""""for i in range(50): article['title'] = str(i) + "_文章标题" #文章标题 article['body'] = str(i) + "_文章内容" #文章内容 #print article res = sid.post(url = article_request,headers = header) print res"""

function.py如下:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455# coding:utf-8from settings import *#检查数据库中是否存在文章,0为不存在,1为存在def res_check(article): exec_select = "SELECT count(*) FROM history WHERE url = '%s' AND title = '%s' " res_check = cur.execute(exec_select % (article[0],article[1])) for res in res_check: result = res[0] return result#写入数据库操作def res_insert(article): exec_insert = "INSERT INTO history (url,title) VALUES ('%s','%s')" cur.execute(exec_insert % (article[0],article[1])) conn.commit()#模拟登陆发布文章def send_article(title,body,typeid = "2"): article['title'] = title #文章标题 article['body'] = body #文章内容 article['typeid'] = "2" #print article #提交后会自动重定向 生成html,http返回状态为200则成功! res = sid.post(url = article_request,headers = header) #print res if res.status_code == 200 : #print u"send mail!" send_mail(title = title,body = body) print u"success article send!" else: #发布文章失败处理 pass#发邮件通知send_mail(收件,标题,内容)def send_mail(title,body): shoujian = "admin@0535code.com" # 设置服务器,用户名、密码以及邮箱的后缀 mail_user = "610358898" mail_pass="你的邮箱密码" mail_postfix="qq.com" me=mail_user+"<"+mail_user+"@"+mail_postfix+">" msg = MIMEText(body,'html','utf-8') msg['Subject'] = title #msg['to'] = shoujian try: mail = smtplib.SMTP() mail.connect("smtp.qq.com")#配置SMTP服务器 mail.login(mail_user,mail_pass) mail.sendmail(me,shoujian,msg.as_string()) mail.close() print u"send mail success!" except Exception,e: print str(e) print u"send mail exit!"

run.py如下:

1234# -*- coding: utf-8 -*-import spiders #开始第一个爬虫 spiders.start()

settings.py如下:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778# coding:utf-8import re,sys,os,requests,lxml,string,time,loggingfrom bs4 import BeautifulSoupfrom lxml import etreeimport smtplibfrom email.mime.text import MIMETextimport sqlite3import HTMLParser#刷新系统reload(sys)sys.setdefaultencoding( "utf-8" )#定义当前时间#now = time.strftime( '%Y-%m-%d %X',time.localtime())#设置头信息headers={ "User-Agent":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/42.0.2311.152 Safari/537.36","Accept":"*/*","Accept-Language":"zh-CN,en;q=0.3","Accept-Encoding":"gzip,deflate","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8","Connection":"keep-alive","X-Requested-With":"XMLHttpRequest",}domain = u"<a href='http://010bjsoft.com'>北京软件外包</a>".decode("string_escape") #要替换的超链接html_parser = HTMLParser.HTMLParser() #生成转义器########################################################dede参数配置#定义域名domain = "http://127.0.0.2/"admin_dir = "dede/"houtai = domain + admin_dirusername = "admin"password = "admin"#访问登陆接口保持cookiessid = requests.session()login_url = houtai + "index.php?username=" + username + "&password=" + passwordheader = { "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",#s生成当前提交时间}#定义可变字段article['source'] = "文章来源" #文章来源article['writer'] = "文章作者" #文章作者#定义提交文章请求URLarticle_request = houtai + "article_add.php"########################################################数据库配置#建立数据库连接conn = sqlite3.connect("db.dll")#创建游标cur = conn.cursor()

spiders.py如下:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970# coding:utf-8from settings import *from function import *#获取内容,文章url,文章内容xpath表达式def get_content( url = "http://www.zhongkerd.com/news/content-1389.html",xpath_rule = "//html/body/div[3]/div/div[2]/div/div[2]/div/div[1]/div/div/dl/dd" ): html = requests.get(url,headers = headers).content tree = etree.HTML(html) res = tree .xpath(xpath_rule)[0] res_content = etree.tostring(res) #转为字符串 res_content = html_parser.unescape(res_content) #转为html编码 输出 res_content = res_content.replace('\t','').replace('\n','') #去除空格 .replace(' ',''),换行符,制表符 return res_content#获取结果,url列表def get_article_list(url = "http://www.zhongkerd.com/news.html" ): body_html = requests.get(url,headers = headers).content #print body_html soup = BeautifulSoup(body_html,'lxml') page_div = soup.find_all(name = "a",href = re.compile("content"),class_="w-bloglist-entry-link") #print page_div list_url = [] for a in page_div: #print a #print a.get('href') #print a.string list_url.append((a.get('href'),a.string)) #print get_content(a.get('href')) else: #print list_url return list_url#处理采集页面def res_content(url): content = get_content(url) #print content info = re.findall(r'<dd>(.*?)</dd>',content,re.S)[0] #去掉dd标签 re_zhushi = re.compile(r'<!--[^>]*-->') #HTML注释 re_href = re.compile(r'<\s*a[^>]*>[^<](.*?)*<\s*/\s*a\s*>') #去出超链接,替换 re_js = re.compile(r'<\s*script[^>]*>[^<](.*?)*<\s*/\s*script\s*>') #去出 javascript re_copyright = re.compile(r'<p\s*align=\"left\">(.*?)</p>') #去出 版权信息 #r'<p\s*align=\"left\">' 注意处理换行要 info = re_zhushi.sub('',info,re.S) info = re_href.sub(domain,re.S) #print content #exit() info = re_copyright.sub(u"",re.S) info = info.replace(u'\xa0',u' ') #防止gbk转btf输出错误 #print info return info#处理结果def caiji_result(): article_list = get_article_list() #print article_list #判断是否数据库中是否有,是否写入数据库 for article in article_list: #print res_check(article) #判断是否需要写入 if not res_check(article): #print "no" #u"不存在需要写入" res_insert(article) #写入后需要发布文章 body = res_content(article[0]) send_article(title = article[1],body = body) else: #print "yes" #u"已经存在不需要写入" pass#爬虫调用函数def start(): caiji_result()

__init__.py用于发布模块时用.

写完了、是不是发现和scrapy基础功能有点像呢...

作者:网痴

欢迎参与《Python编程-利用爬虫配合dedecms全自动采集发布》讨论,分享您的想法,编程之家 jb51.cc为您提供专业教程。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1、想好字段名! 这里取一个test 商品发布模板:post_trade.htm 在商品发布模板贴内新建一个文本框!
一、后台 → 全局 → 关闭站点(为了不影响数据库备份) 二、数据备份
<?php /** [Discuz!] (C) 2001-2099 Comsenz Inc. config_global.php Build at 2012-07-06 10:16:22 */
今天给大家讲讲 如何把已经切割好的html页面或者模仿的页面转换成可供DIY的页面
打开网站根目录下/template/default/common header_common.htm文件找到 <title><!--{if !empty($navtitle)}-->$navtitle - <!--{/if}--><!--{if empty($nobbname)}--> $_G['se
打开网站根目录/source/module/portal/portal_list.php搜 category_get_list 在里面加入以下代码:添加一下代码
请问discuz的右侧工具栏(有回到顶部,返回板块),但是我想再添加点东西,可是我百度了,也从源码里找了好久,都没找到解决方法,请问可以教一下吗?
这里建议直接使用163邮箱,因为 我测试了 qq邮箱,yeah邮箱 均不能用。 第一步 去163注册一个邮箱,具体怎么注册 想必大家都会。注册好进入163 看下图
这些天百度和google了不知道多少遍,发现discuz的官方文档和二次开发资料少得可怜。调用个编辑器这样采用的功能官方文档居然没有,网友的分享多少也有些不完整;中途差点放弃。最后实在没办法兼不甘心,自己啃源码去
UPDATE `表名称` SET `click` = click+ROUND(RAND() * 6666+ 666) WHERE `click` <5000 复制代码
discuz在数据库批量更新(替换)板块id(fid/gid) UPDATE `fx_forum_thread` SET `fid` = replace(fid,'2','52') WHERE `fid` =2
想在自己的写上置顶的帖子    <div class="announcement_con"> <ul>
进入网站目录:/source/include/post 找到:post_newthread.php备份:post_newthread.php编辑:post_newthread.php搜索:
C::t('forum_attachment')->fetch_all_by_id('aid',$v['tid'] ); 执行上面的代码,会返回对应帖子的附件信息!
版本 dx 3.3 估计3.4一样有这个问题,ie内核的浏览器下在上传后,缩略图都是显示xx。这个问题主要还是https下,对图片输出的时候 不能使用
论坛人气弱?想改阅读数的站长可以围观! 找到:source/module/forum/forum_viewthread.php文件搜索代码:
<!--{if $allowpostreply && !$_G['forum_thread']['archiveid']}--> <a id="post_reply" onclick="showWindow('reply','forum.php?mod=post
SQL语句 UPDATE 表名称 SET 字段名 = REPLACE( 字段名,  '旧字符串',  '新的字符串' )
discuz 帖子内容页面的,上一篇,下一篇代码 上一篇: <a href="forum.php?mod=redirect&goto=nextoldset&tid=$_G[tid]" title="{lang last_thread}"><img src=&quo
1.php文件内判断 if(!$_G['uid']) {                         showmessage('to_login','',arra