我的第一次爬网页经历

背景

之前我从来没有爬过网页,一直对scrapy很好奇,这周一粽子让我去爬一下 http://www.calltrace.cn/home.html
工单管理-》已提交结果工单-》举报内容摘要/来电时间,一共有100多条,看起来需要一条一条点开才行。
我之前对网页有了一点小小的积累,大致明白了cookie,post,get,html这方面的知识,因此觉得应该是能够胜任的,因此就愉快得答应了下来。

不过我一开始走了不少弯路,最后抓出网页信息的时候,也是瞎猫碰到死耗子,并不能说以后就能成功了,而且或许这个换台电脑,关闭一下浏览器未必能够成功。
我的学习路线大致是这样的:

1、我先查看了网页源码和调试模式下的element元素审查

    然后我就发现源码里面并没有完整的信息嘛,只是一个html的骨架
    而element里面的信息到时全面的,因此我一开始想着是不是应该把网页整体拉下了,然后去解析html,把数据提取出来,而后的实践我发现至少我这次用半天时间没有做出来。

2、于是我一开始的方法是:学些久仰大名的scrapy,然后我大致了解了scrapy的原理:

    几个教程:
    xpath语法
    request的高级用法
  • spider把response里面的数据提取出来,要不返回item,要不进行下一次请求
  • Items是用来存储数据,就是一个model
  • pipelines 负责对spider返回数据的处理
  • 其它的如中间件,settings我没怎么用到,就不说了
    其中最重要的是yield语法,在scrapy里面,它会产生新的线程,或者保存item,或者给出下一个请求

3、但是,在学了这些之后,我发现完全用不到这次要爬的网站,因为上面的爬虫基于url进行爬取,不过我

要爬的网站里面并没有url。。。后来我看到一个词,叫 动态网页 ,可能说的就是这个
    我只能去查看chrom里面的network,看看是否有get和post请求了,后来我看到了2个请求:
url_frontpage = "http://www.calltrace.cn/Entity/List.do"
url_detail = "http://www.calltrace.cn/Entity/Detail.do"


它们中一个是主页的请求,一个是详情页的请求
主页请求List.do的request中带有参数page,limit,start;response中则返回指定数量的已提交工单的编号
详情页请求Detail.do中请求参数则正好需要上面的已提交工单的编号!
因此,只要先请求List.do,把所有已提交工单的编号都拿到,然后用这个编号请求Detail.do就能获得详情页的所有信息了。


我在postman上试了一下,又填了一个坑:该网站是需要登录的,因此要用cookie访问这些接口,但postman没找到填cookie的地方,后来我又上网搜了一下,发现只要打开postman的拦截器就行了,它会自动把chrome浏览器的cookie填进来

于是,代码就很容易写了,这其中对关键字段的定位,我用了找规律的本办法,想来这样也没关系,顺带处理了异常和多线程访问
# -*- coding: utf-8 -*-

import threading
import requests
import json

cookies = {"JSESSIONID": "D4746970BB45A3A27AE9567C0E02DE32",  # 该sessionid是会变化的
           "rememberme": "true",
           "company": "%E5%B7%A5%E4%BF%A1%E9%83%A8",
           "username": "yudongsheng",
           "password": "63275050"
}
url_frontpage = "http://www.calltrace.cn/Entity/List.do"
url_detail = "http://www.calltrace.cn/Entity/Detail.do"
limit = "500"  # 每页展示的工单条数
count = 0  # 输出的是第几个工单


def get_url_list():
    """
    调用List.do接口,获取所有已提交结果工单的id,构成一个列表返回
    :return:
    """
    querystring = {"_dc":"1488702544010",
                   "entityInfoId":"a9f19f47e32940ae920d144982f52af1",
                   "filterSql":"",
                   "roleId":"x8c8feb4f37b40be8e41626afbd8ee1c",  # 固定值
                   "filterViewId":"x625053ea86b453c9ee0f5c629c48a5b",  # 固定值
                   "originalViewId":"x625053ea86b453c9ee0f5c629c48a5b",  # 固定值
                   "menuId":"x7f2acbbd6e44f888ee25340944b0d4b",  # 固定值
                   "limit":limit,"page":"1","start":"0"}  # 一页展示的工单数
    headers = {
        'cache-control': "no-cache",
        'postman-token': "677a27f7-5545-3d25-c503-65d6c2f5d378"
        }

    response = requests.request("GET", url_frontpage, headers=headers, params=querystring, cookies=cookies)  # 访问列表接口,获取工单ids
    ret1 = json.loads(response.text)
    entityRecordIds = [ele["tjjgGongdanRwgdidFk"]for ele in ret1["data"]]
    return entityRecordIds

def get_jubaoneirongzhaiyao(entityRecordId):
    """
    传入工单id,调用Detail.do接口,获得工单详情
    :param entityRecordId:
    :return:
    """
    global count
    querystring = {"entityInfoId": "daf39beb648143219d2ccbffc9ab94b8",
                   "entityRecordId": entityRecordId,
                   "filterViewId": "",
                   "roleId": "x8c8feb4f37b40be8e41626afbd8ee1c",
                   "specificCompanyId": "",
                   "specificSolutionId": "",
                   "menuId": ""}
    payload = ""
    headers = {
        'cache-control': "no-cache",
        'postman-token': "d1aa3193-a9df-bcbe-361b-8310c4c59df7"
    }

    response = requests.request("POST", url_detail, data=payload, headers=headers, params=querystring, cookies=cookies)
    text = response.text
    ret = json.loads(text)
    # 建议下面一段代码加个锁,这样可以防止乱序
    count += 1
    print(u"第"+str(count)+u"条")
    try:
        print(ret["recordName"]+u"   举报内容摘要   "+ret['sectionList'][1]["items"][2]["items"][0]["value"])  # 获取任务编号和举报内容摘要
    except:
        print ret.get("recordName", u"未知错误  "+ "id:  "+entityRecordId)+u"  举报内容摘要"+u"  空   "
#


def multi_thread_url():
    """
    多线程获取数百个详情页的信息
    :return:
    """
    entityRecordIds = get_url_list()
    print(u"总共有" + str(len(entityRecordIds)) + u"条")
    for entityRecordId in entityRecordIds:
        t =threading.Thread(target=get_jubaoneirongzhaiyao, args=(entityRecordId,))
        t.start()


multi_thread_url()
最后的输出如下图所示:

4、不足

    首先没有进一步了解scrapy,跳过了其中的难点,对于动态网页,应该有其他方式来抓取
    其次可以做一个自动登录的动作,把cookie取到,就不用手动改cookie了
    然后可以把下载的数据保存到excel里面去
    最后,要能够在windows下运行





  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴为您介绍HTML我的经历网页制作。根据提供的引用内容,该网页包含HTML文件、CSS文件和JS文件,其中HTML文件包含首页和二级页面,CSS文件包含全部页面样式,JS文件包含实现动态轮播特效、表单提交、点击事件等功能。如果您想制作类似的网页,可以使用任意HTML编辑软件,如Dreamweaver、HBuilder、Vscode、Sublime、Webstorm、Text、Notepad++等,进行运行、修改和编辑等操作。您可以参考以下步骤: 1.使用HTML编辑软件创建一个新的HTML文件,命名为index.html,作为您的网站首页。 2.在HTML文件中添加所需的内容,如标题、段落、图片、链接等。 3.使用CSS文件为您的网站添加样式,如字体、颜色、布局等。 4.使用JS文件为您的网站添加交互功能,如动态轮播特效、表单提交、点击事件等。 5.在浏览器中打开您的网站,查看效果,并进行必要的修改和编辑。 以下是一个简单的HTML代码示例,用于创建一个包含标题、段落和图片的网页: ```html <!DOCTYPE html> <html> <head> <title>我的经历</title> <style> body { font-family: Arial, sans-serif; background-color: #f0f0f0; } h1 { color: #333; text-align: center; } p { color: #666; text-align: justify; margin: 20px; } img { display: block; margin: 0 auto; max-width: 100%; height: auto; } </style> </head> <body> <h1>我的经历</h1> <p>我是一名程序员,热爱编程,喜欢挑战自己。我曾经在一家知名互联网公司工作,担任前端开发工程师,负责开发公司的网站和移动应用。我喜欢学习新技术,不断提升自己的技能。</p> <img src="myphoto.jpg" alt="我的照片"> </body> </html> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值