通过一个例子一步一步学习 Python 爬虫。
-
img/@src
提取 img 元素中属性名为 src 的对应的 属性值 - 通过 Chrome 的审查元素得到的 Xpath 路径和网页源代码中的路径有所不同
- post 请求中的可变字段一般先通过登录前的一次 get 请求获取
比较疑惑的一个地方是, 使用 Chrome 右键菜单中的 检查
, 所找到的 tbody
元素在网页源文件中并不存在。把 tbody 去掉也没有影响。于是决定不使用 tbody 标签了。
//tbody/tr/td[@id="main"]/div[@id="content"]/div[@id="stream"]/ol[@class="wa solo"]/li
完整代码如下:
# -*-coding: utf-8 -*-
import requests
from lxml import etree
class FanFou(object):
def getDataForm(self):
base_url = "http://fanfou.com"
token = etree.HTML(requests.get(base_url).text).xpath('//form/p[@class="act"]/input[@name="token"]/@value')[0]
dataform = {
'loginname' : 'qiangyuebing@ali.com',
'loginpass' : 'sanxingnote7',
'action' : 'login',
'token' : token
}
return dataform
def getInfo(self, data):
login_url = "http://fanfou.com/login"
html = requests.post(login_url, data = data).content
# messages = etree.HTML(html).xpath('//tbody/tr/td[@id="main"]/div[@id="content"]/div[@id="stream"]/ol[@class="wa solo"]/li')
messages = etree.HTML(html).xpath('//ol[@class="wa solo"]/li')
info_List = []
for li in messages:
info = {}
info['home_url'] = li.xpath('a/@href')[0] # 个人主页
info['title'] = li.xpath('a[@class="author"]/text()')[0] # 姓名
info['avatar'] = li.xpath('a[@class="avatar"]/img/@src')[0] # 头像地址
info['content'] = li.xpath('span[@class="content"]')[0].xpath('string(.)') # 发言
info['message_time'] = li.xpath('span[@class="stamp"]/a[@class="time"]/text()')[0] # 发言时间
info['app'] = li.xpath('span[@class="stamp"]/span[@class="method"]')[0].xpath('string(.)') # 使用的客户端
info_List.append(info)
return info_List
def savetofile(self, infoList):
base_url = 'http://fanfou.com'
fout = open("result.txt", "a", encoding="utf-8")
for info in infoList:
fout.writelines(u'个人主页: ' + base_url + info['home_url'] + "\n")
fout.writelines(u'姓名: ' + info['title'] + "\n")
fout.writelines(u'头像地址: ' + info['avatar'] + "\n")
fout.writelines(u'发言内容: ' + info['content'] + "\n")
fout.writelines(u'发言时间: ' + info['message_time'] + "\n")
fout.writelines(u'客户端: ' + info['app'] + "\n")
fout.writelines("\n\n")
fout.close()
if __name__ == '__main__':
myfan = FanFou()
dataform = myfan.getDataForm()
infoDict = myfan.getInfo(dataform)
myfan.savetofile(infoDict)
print('download complete')
结果如下:(目前只写入 txt, 随后的文章中会使用数据库)
注意, 例子中的用户名和密码不是真实的, 请使用自己的信息进行替换。
饭否中的帖子不是一次性加载完的, 也没有分页, 当点击 更多
的时候才会加载更多内容, 所以用到了 Ajax 异步加载, 后面的文章会使用这个功能。