爬虫案例(xpath)

爬虫案例(某某二手房)

步骤

  • 请求模块
# 封装一个函数,用于将url处理成请求对象
def request_by(url,city,page):
    page_url = url%(city,page)
    # 请求头
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    return request.Request(url=page_url,headers=headers)


# 封装一个函数,用于发起请求
def request_data(url,city_list):
    # 对citylist进行遍历
    for city in city_list:
        # 每个城市遍历100页
        for page in range(1,4):
            # 创建每个页面的请求对象
            req = request_by(url=url,city=city,page=page)
            # 发请求
            res = request.urlopen(req)
            print("正在请求城市%s的第%d页"%(city,page))
            sleep(1)
            yield res.read().decode("utf-8")

  • 解析模块
def analysis_data(data):
    for html in data:
        # 创建一个节点树
        html_tree = etree.HTML(html) # 这个函数用于将html字符串转化成html节点树
        # 解析出每一个房屋单元
        house_list = html_tree.xpath("//ul[@class='sellListContent']/li")
        for house in house_list:
            # 创建一个字典用于整合每一个房源的信息
            item = {}
            # title
            item["title"] = house.xpath(".//div[@class='title']/a/text()")[0]
            # 位置
            item["position"] = "".join(house.xpath(".//div[@class='positionInfo']//text()"))
            # 房屋信息
            item["houseInfo"] = "".join(house.xpath(".//div[@class='houseInfo']//text()"))
            # 单价
            item["unitPrice"] = re.findall(pattern=r'[0-9]*',string=house.xpath(".//div[@class='unitPrice']/span/text()")[0])[2]
            # 总价
            item["totalPrice"] = house.xpath(".//div[@class='totalPrice']/span/text()")[0]

            yield item
            # print(item)
  • redis存储模块
def write_to_redis(data):
    # 创建一个redis链接
    rds = redis.StrictRedis(host="**********",port=6379,db=1)
    # 向redis数据库中存入数据
    for item in data:
        rds.lpush("ershoufang",json.dumps(item)) # 某些版本的redis数据库不能直接存字典和对象,必须把字典转成json字符串
  • 调用函数
if __name__ == '__main__':
    url = 'https://%s.******.com/ershoufang/pg%d/'
    # 生成一个城市列表
    city_list = ['sh','sz','gz','hz','tj']
    html_list = request_data(url=url,city_list=city_list)
    house_list = analysis_data(html_list)
    write_to_redis(house_list)

requests 模块

  • requests是一个第三方的请求框架,对urllib进行了二次的封装,简化urllib的一些操作
简单的get请求
res = requests.get(url="https://www.baidu.com")
print(res)	#<Response [200]>
print(res.text) # 字符串格式的响应体		
print(res.content) # 二进制格式的响应体
带参的get请求
url = "https://www.baidu.com/s"
# 请求体
params = {
    "ie":"utf-8",
    "wd":"范冰冰"
}
# 请求头
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
res = requests.get(url=url,params=params,headers=headers)
print(res)
post请求
post_url = "https://fanyi.baidu.com/sug"
# 请求体
data = {
    "kw":"a"
}
res = requests.post(url=post_url,data=data,headers=headers)
print(res.text)

会话处理

  • 为什么引进会话技术?

    requests没有直接接收cookie的功能,

    由于requests不能直接接收cookie,此时再次发请求时并没有携带cookie,后台就检测不到登录信息,就会跳转至登录页

  • 使用session的原因

    • 用Session对象发起请求,不仅可以提交参数还能提交cookie
    • 用Session对象来发起请求,不仅可以接收响应体还能接收cookie
  • 使用方法

import requests

login_url = 'http://www.jokeji.cn/user/c.asp'
# u=112&p=qweqe&sn=1&t=big
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}

# 创建一个requests的Session对象,用于接收并保存cookie
s = requests.Session()

params = {
    "u":"*****",
    "p":"*******",
    "sn":"1",
    "t":"big"
}
# 发起get请求来登录
res = s.get(url=login_url,params=params,headers=headers)

print(res.text)

# 跳转主页url
main_url = "http://www.jokeji.cn/User/MemberJoke.asp"

main = s.get(url=main_url,headers=headers)
print(main.text)

使用requests爬取某网站

  • 分析该网页登录页面需要提供什么信息?
    • 需要提交验证码和两个token值,而这两个token值和验证码都是通过刷新登录页得到的,所以我们在向登录接口发post请求之前首先要想当前的这个登录页面的url发起一个get请求来提取以上信息
  • 登录页的get请求应该用requests来发还用Session?
    • 请求的时候要用Session,因为验证码和token获取要和当前终端cookie对应上
操作流程
# 创建一个Session对象
s = requests.Session()
# 登录页面url
login_page = 'https://so.**.org/user/login.aspx?from=http://so.**.org/user/collect.aspx'
# 访问登录页面来提取验证码和token
login_html = s.get(url=login_page,headers=headers)
# 提取token
login_tree = etree.HTML(login_html.text)

token1 = login_tree.xpath("//input[@id='__VIEWSTATE']/@value")[0]
token2 = login_tree.xpath("//input[@id='__VIEWSTATEGENERATOR']/@value")[0]

# 提取验证码(拼接域名和路由)
code_url = "https://so.*****.org" + login_tree.xpath("//img[@id='imgCode']/@src")[0]
# 下载验证码,下载验证码的时候也要用Session
code_data = s.get(code_url,headers=headers)
with open("code.png","wb") as fp:
    fp.write(code_data.content)
# print(token1,token2)
# 人工识别验证码
code = input("请打开验证码图片查看,并且在此处输入你看到的内容:")

# 发起post请求登录
login_url = "https://so.*****.org/user/login.aspx?from=http%3a%2f%2fso.****.org%2fuser%2fcollect.aspx"
data = {
    '__VIEWSTATE':	token1,
    '__VIEWSTATEGENERATOR':token2,
    'from':	'http://so.***.org/user/collect.aspx',
    'email':'*****',
    'pwd':'*******',
    'code':code,
    'denglu':'登录'
}
res = s.post(url=login_url,data=data,headers=headers)
print(res.text)

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值