Discuz! 是一套由康盛创想开发的通用社区论坛软件系统,成熟度高、覆盖率大。用户可以在不需要任何编程的基础上,通过简单的设置和安装,在互联网上搭建起具备完善功能、很强负载能力和可高度定制的论坛服务。Discuz! 的基础架构采用 PHP + MySQL 实现。

1. 实战环境

由 Ubuntu、Nginx、PHP、MySQL 配置的 Discuz! Docker 环境可从以下链接中下载:

Docker 镜像下载地址

提取码:esdm

1.1 环境配置

1.1.1 配置 Python 环境

Python、requests、pyquery

Python 依赖安装:

pip install requests pyquery

1.1.2 导入 Docker 镜像

$ sudo docker load ubuntu-nginx-php-mysql-discuz-exp-2.tar

1.1.3 启动环境

查看 ubuntu-nginx-php-mysql-discuz:exp-2 的 IMAGE ID

$ sudo docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

ubuntu-nginx-php-mysql-discuz exp-2 368753f87d4f 22 hours ago 1.02GB

镜像的 IMAGE ID 为 368753f87d4f

启动 ubuntu-nginx-php-mysql-discuz:exp-2

$ sudo docker run -itd {IMAGE ID}

1.1.4 进入 Docker 容器

查看已运行的 Docker 容器

$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

a37b8fa69b5d 368753f87d4f "/bin/bash" 40 seconds ago Up 38 seconds optimistic_hypatia

容器的 CONTAINER ID 为 a37b8fa69b5d

进入容器

$ sudo docker attach {CONTAINER ID}

1.1.5 在容器中启动服务

启动 Nginx PHP Mysql 服务,进入 /root 文件夹,运行 start.sh

# cd /root

# bash start.sh

1.1.6 获取容器的 IP 地址

# ifconfig

eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02

inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:32 errors:0 dropped:0 overruns:0 frame:0

TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:3721 (3.7 KB) TX bytes:0 (0.0 B)

容器的 IP 地址为 172.17.0.2

在键盘上依次按下 Ctrl + P + Q 退出容器并后台继续运行

1.2 实战目标

在 Chrome 浏览器中,输入 Discuz! 论坛的网址 http://172.17.0.2,即可看到论坛的页面。论坛中共有 3 个板块:默认板块、寻找 flag、登陆后寻找 flag。登陆后寻找 flag 仅在用户登录后可见。

寻找 flag 板块中共有 69 个主题,登陆后寻找 flag 板块共有 90 个主题。分别在这两个板块的某一个主题中,隐藏着 flag。

实战目标:编写爬虫,分别遍历两个板块中的所有帖子,从中寻找的到 flag。

flag 的形式为 {flag is XXXXXX}

注:为降低难度,Discuz! 论坛已关闭登录验证码

2. "寻找 flag" 板块分析

2.1 确定板块的 URL

首先在 Chrome 浏览器中,进入 寻找 flag 板块。

观察 Chrome 浏览器中的 URL 地址:

http://172.17.0.2/forum.php?mod=forumdisplay&fid=36

包含了两个请求参数,mod=forumdisplay,fid=36。

Discuz! 字段说明

字段

含义

说明

fid

板块 ID

论坛上每个版块的编号

tid

主题 ID

每个主题帖的唯一编号

pid

帖子 ID

每个帖子的唯一编号

uid

用户 ID

每个注册用户的编号

因此可知,寻找 flag 板块 ID 为 36。

2.2 确定板块的总页数

观察板块页面的最下方,可看到页面的导航按钮。

进入 Chrome 调试模式(Ctrl + Shift + I),检查上图中的元素,可看到网页的源代码

可看到总页数出现在 title="共 4 页" 中,因此可用 正则表达式 获取到板块的总页数。正则表达式为 title="共 ([\d]+) 页"。

获取板块总页数的 Python 代码:

resp = requests.get('%s/forum.php'

'?mod=forumdisplay'

'&fid=%s' % (config.discuz_url, config.discuz_post_fid))

total_page = int(re.findall(r'title="共 ([\d]+) 页"', resp.content)[0])

2.3 确定板块每页的链接

分别点击页面导航按钮中的第 2 页、第 3 页,观察 Chrome 地址栏中的 URL。

http://172.17.0.2/forum.php?mod=forumdisplay&fid=36&page=2

参数 mod=forumdisplay,fid=36、page=2。

http://172.17.0.2/forum.php?mod=forumdisplay&fid=36&page=3

参数 mod=forumdisplay,fid=36、page=3。

将 URL 中的 page 参数修改为 1,访问 http://172.17.0.2/forum.php?mod=forumdisplay&fid=36&page=1 ,发现可进入第 1 页

因此,板块中的第几页由 URL 的 page 参数控制。

http://172.17.0.2/forum.php?mod=forumdisplay&fid=36&page=%s

Python 中访问第 page 页的代码:

resp = requests.get('%s/forum.php'

'?mod=forumdisplay'

'&fid=%s'

'&page=%s' % (config.discuz_url, config.discuz_post_fid, page))

2.4 确定每个主题的链接

在 Chrome 调试页面中,检查主题列表

主题列表均在 id 为 threadlisttableid 的 table 标签中。每个主题以 tbody 标签的形式出现。

注意:id="separatorline" 的 tbody 不是主题。

Python 使用 pyquery 获取到主题列表:

articles = pq(resp.content)('#threadlisttableid tbody')

在 tbody 标签中,可以看到,主题的 URL 出现在 class 为 xst 的 a 标签中,URL 为该标签的 href 属性。

Python 获取主题的 title 及 URL

# 确定 title 和 url

title = tbody_pq.find('th a.xst').text()

url = tbody_pq.find('th a.xst').attr('href')

2.5 遍历所有主题获取 flag

由于已知 flag 的形式为 {flag is XXXXXX},因此可使用正则表达式直接在主题请求的响应内容中寻找 flag。正则表达式为 ({flag[^}]*})。

# 请求帖子的 url

resp = requests.get('%s/%s' % (config.discuz_url, url))

# 正则表达式寻找 flag

flag = re.findall(r'({flag[^}]*})', resp.content)

3. "登陆后寻找 flag" 板块分析

由于该板块对登陆后用户可见,首先在论坛中注册一个用户。

用户名:test

密码:testtest

邮箱:test@test.com

3.1 登录分析

注册成功后会直接进入登录后的页面,由于爬虫需要模拟登录的过程,首先退出登录。

在登录框内输好用户名、密码后,打开 Chrome 调试页面,进入 Network 中,勾选 Preserve log。

点击 登录 按钮,Chrome 会截取到登录的请求。

在 POST 的请求中,URL包含了 5 个参数

Key

Value

mod

logging

action

login

loginsubmit

yes

infloat

yes

lssubmmit

yes

inajax

1

Form Data 中包含了 5 个参数

Key

Value

fastloginfield

username

username

test

password

testtest

quickforward

yes

handlekey

ls

可见,用户名、密码在 From Data 中的 username、password。

Python 构造 请求 url 及 Form Data:

url = '%s/member.php' \

'?mod=logging' \

'&action=login' \

'&loginsubmit=yes' \

'&infloat=yes' \

'&lssubmit=yes' \

'&inajax=1' % config.discuz_url

data = {

'fastloginfield': 'username',

'username': config.discuz_username,

'password': config.discuz_password,

'quickforward': 'yes',

'handlekey': 'ls'

}

在登录成功的响应头中,包含了 set-cookie。

为了使请求能够自动处理好 Cookie 的问题,使用:

req = requests.session()

由于 Chrome 自身的原因,无论登录成功与失败,登录的响应内容均无法正常显示。

可在 Python 代码中,取消以下两行的注释,观察成功、失败的响应内容。

# print resp.content

# exit()

登录失败的响应如下:

if(typeof errorhandle_ls=='function') {errorhandle_ls('登录失败,您还可以尝试 3 次', {'loginperm':'3'});}]]>

登录成功的响应如下:

window.location.href='http://172.17.0.2/./';]]>

因此,可通过判断响应内容是否包含 window.location.href,作为是否成功登录的依据。

Python 判断是否成功登录:

if 'window.location.href' in resp.content:

print '[+] Login success'

else:

print '[-] Login failed'

exit()

3.2 继续分析

接下来的分析过程与 (2. "寻找 flag" 板块分析)[] 中相似。

4. 运行代码

4.1 配置 config.py

discuz_url 为论坛的 URL,注意尾部没有斜杠。

discuz_post_fid 为 寻找 flag 的板块 ID。

discuz_post_login_fid 为 登陆后寻找 flag 的板块 ID。

discuz_username 和 discuz_password 分别为用户名及密码。

discuz_url = 'http://172.17.0.2'

discuz_post_fid = 36

discuz_post_login_fid = 37

discuz_username = 'test'

discuz_password = 'testtest'

4.2 运行

运行 python main_a.py,在 寻找 flag 的板块中寻找 flag:

运行 python main_b.py,在 登陆后寻找 flag 的板块中寻找 flag:

5 实践设计思路

为了避免直接利用 Discuz! 自带的搜索功能搜索到 flag,我将 flag 藏到了图片的 url 链接中。

[img=1,1]https://www.bjcc.gov.cn/resources/pc/img/logo.png?{flag is XXXX}[/img]

在帖子中 flag 出现的代码

python爬取discuz_爬虫技术实践(二)Discuz! 按板块爬取帖子内容实战相关推荐

  1. python初学者爬虫教程(二)动态网页抓取

    python爬虫教程(二)动态网页抓取 解析真实地址抓取 通过selenium 模拟浏览器抓取 selenium 安装与测试 selenium爬取一条评论 selenium获取文章的所有评论 sele ...

  2. 如何快速掌握 Python 数据采集与网络爬虫技术

    摘要: 本文详细讲解了 python 网络爬虫,并介绍抓包分析等技术,实战训练三个网络爬虫案例,并简单补充了常见的反爬策略与反爬攻克手段.通过本文的学习,可以快速掌握网络爬虫基础,结合实战练习,写出一 ...

  3. 如何快速掌握Python数据采集与网络爬虫技术

    云栖君导读:本文详细讲解了python网络爬虫,并介绍抓包分析等技术,实战训练三个网络爬虫案例,并简单补充了常见的反爬策略与反爬攻克手段.通过本文的学习,可以快速掌握网络爬虫基础,结合实战练习,写出一 ...

  4. python数据采集有哪些技术_如何快速掌握Python数据采集与网络爬虫技术

    一.数据采集与网络爬虫技术简介 网络爬虫是用于数据采集的一门技术,可以帮助我们自动地进行信息的获取与筛选.从技术手段来说,网络爬虫有多种实现方案,如PHP.Java.Python ....那么用pyt ...

  5. Python案例:破译爬虫项目实践活动日期密码

    Python案例:破译爬虫项目实践活动日期密码 一.下达编程任务 寒假期间,李铁有幸成为外星人教育Python爬虫项目实践活动的参与者.外星人教育给参加活动的同学都发了一条短信,告知了实践活动日期,但 ...

  6. python制作电脑软件_利用PYTHON制作桌面版爬虫软件(二)

    今天继续新的专题.主要讲解[利用PYTHON制作桌面版爬虫软件]下的如何实现界面功能(一).该讲主要包括以下三个内容:掌握如何编写主函数,运行界面. 了解pywin32模块. 如何用python识别Q ...

  7. python爬虫之app数据抓取_Python爬虫入门教程 29-100 手机APP数据抓取 pyspider

    1. 手机APP数据----写在前面 继续练习pyspider的使用,最近搜索了一些这个框架的一些使用技巧,发现文档竟然挺难理解的,不过使用起来暂时没有障碍,估摸着,要在写个5篇左右关于这个框架的教程 ...

  8. python 北上资金_python爬虫技术:北向资金数据自动爬取!

    好久不见!今天我们继续python的话题啦.python现在势头凶得很,没事刷抖音.刷朋友圈.看公众号,弹出的广告总少不了python."python带你发家致富,财富自由!"广告 ...

  9. 【Python 爬虫】(二)使用 Requests 爬取豆瓣短评

    文章目录 Requests库介绍 Requests库安装 Requests库的简单用法 实战 爬虫协议 Requests库介绍 Requests库官方的介绍有这么一句话:Requests,唯一的一个非 ...

最新文章

  1. TensorRT Samples: MNIST(Plugin, add a custom layer)
  2. CSS教你玩转背景background-position(1)
  3. THUWC 2018(游记)
  4. comboBox.DataSource绑定
  5. LAMP 搭建BBS论坛实战
  6. 【面试必备】java写spark好不好
  7. php layui 框架,Thinkphp5+Layui高颜值内容管理框架
  8. php导出csv带图片,PHP导出CSV文件:刚测试过,这个导出CSV可以
  9. arcmap导出地图快捷键_谷歌点坐标导出为excel表格
  10. c#点击按钮调出另一个窗体_在类库或winform项目中打开另一个winform项目窗体的方法...
  11. 1603错误_iPhone恢复iTunes未知错误怎么办【解决方法】
  12. Dataframe列赋值值后全部为NAN
  13. Cadence Allegro智能创建PCB封装库
  14. 深度学习中常用的激励函数
  15. 视频教程-2020软考网络规划设计师基础知识视频教程-软考
  16. 操作系统原理:文件系统
  17. CAP、BASE理论
  18. 声谱图(spectrogram)、FBank(Mel_spectrogram)和 MFCC(Mel倒谱)到底用哪个作为NN输入?
  19. Linux 中各个文件夹的作用
  20. 鹅厂java面试真题汇总

热门文章

  1. VMware虚拟机配置IP地址
  2. Advanced IP Scanner教程 详细使用方法
  3. [vue]vue接入AntV G2Plot
  4. 如何利用百度短链接接口将一个长链接变成短链接
  5. apmserv mysql密码_apmserv中修改mysql的root与phpmyadmin密码方法介绍
  6. 投影仪用光学引擎行业现状调研及趋势分析报告
  7. 那些年我们一起手写过的单例
  8. wps批量将文档括号内的字符串修改颜色
  9. 电脑之间快速传输超大文件(100GB以上)的方法
  10. ASCII、Unicode、UTF-8