写在前面
苦逼的寒假马上结束,整个寒假就只弄了实验室的任务,我真的很快落
这是我们的第二个任务,比第一次任务一要熟练一些了,萌新渐渐熟练操作,o(╥﹏╥)o
废话不多说,开始!
任务要求
- 目标网页:http://www.tljyzx.cn/lbv3/n_newslist_zz.aspx?QFDzuxLlsz5UY8gxwVXiNg==
- 要求:爬取中标信息呀,什么中标候选人,中标的金额呀,能看见的都爬下来的那种
那些政府采购是什么鬼呀!
那么,为了尽快完成这次作业,顺便偷个懒,我们就只进行建设工程的爬取
开始吧~
我们先看看源代码吧,这个是因为万一是ajax动态生成的呢,光看F12里面的Elements里面呈现出来的网页是不够的,那个已经是经过处理的了,至于有哪些,我也不是太清楚的
Step 1 - 分析开始页面
看看源代码
-
很好!里面有我们需要的标题内容,似乎还有发布时间这些!
-
那么页面可以直接用xpath定位提取就可以了
-
当然里面还有我们需要的详情页url地址,虽然只有一半,但是我们可以进行拼接,到时候直接yield scrapy.Request(url=xxx,callback=xxx,meta={‘xxx’:xxx}),这样就可以得到详情页信息了
-
上面三个参数分别对应我们请求的url地址,返回的信息的解析函数,以及传入的字典
-
这里,我们试着在解析函数里面直接打印meta,会发现它是个字典,里面挺多的东西的,而我们只是把我们需要的字典加入到meta,让它带给解析函数而已
-
额,我是不是火星了?
Step 2 - 解决翻页
-
这里,可能是我碰到的最大问题吧
-
怎么说呢?
-
在源代码里我找不到下一页按钮对应的href,也就是属性,本来以为提取下翻页按钮的超链接就行了,但是,它!没!有!
-
那我进行url拼接不行吗?翻页后我们会发现,页面的url没有变化,卒
-
有了第一次任务里的ajax页面处理的经验(ajax页面url也是不会变的),我想试一下抓包
-
Emmmm,说到抓包,都是泪呀
-
同样的,F12,打开Network
-
其中中间那个是用来帮你进行包的分类的,我觉得不错
-
这里暂时是没有东西的,需要刷新页面,不然怎么叫抓包呢,当服务器给我包,我们才能抓到不是吗?
-
然后,页面长这样
- 然后我们点击下一页,看看服务器会给我们些什么东西
- 翻页信息你在哪呀!
- 又是一番折腾,真的是折腾,我根本不知道那个包是我要的。。。
- 在这里强烈要求,学姐学长们教一下我们怎么进行抓包吧,当时真的一脸懵
- 厚着脸皮去问了下组长,“你看页面”“看内容啊”,行吧,我看,我看,我看不懂TAT
- Emmmmm,结果是这样的
- 我们看一下它的信息吧
- 这里我们知道它是post请求,请求的url正是我们第一(所有)页的网址
- 继续看看,看还有些啥
- 还有这个
- “他(雾)是post表单”——来自组长
- 行吧,百度呀!
- 度娘,你说该怎么办!?
- 度娘:你这样,这样,这样,然后这样
- 我:哇卡里玛席达
- 我们这样,新建一个字典,把那个表单中的参数全部输进去,Emmmm,有的似乎是不需要,不管了,都写上先
- 然后这样
- 这里会用到scrapy自带的FormRequest,有点类似requests和urllib里面的request
Step 3 - 寻找表单里的关键数据
- 也就是刚刚图里面那两个等待补充的信息(这两个关键信息一直是变化的)
- 我们试着看在源代码里面找不找得到这个内容
- Lucky!
- 同理,我们可以在网页的后面找到另外一个,推荐快捷键Ctrl+F
- 这个时候,直接xpath或者正则表达式可以直接获得
- 万事俱备,只欠东风
Step 4 - 开始操作
- 其实,做到这里,任务已经算完成80%了
- 但是很不幸,做完任务回头来看,分析问题的时间只占了20%,而剩下的时间全部拿来做信息筛选了。那些详情页的布局就不能整齐一点吗?昂?TAT
- 具体代码就不发了,重要的思路不是吗
一些小细节吧
- 在调试的时候,因为屏幕有局限性,如果爬取内容太多的话,最先出现的一些内容就会消失掉,这是我想的是能不能把那些日志文件打印下来,很明显,是可以的
- 我们需要在settings.py里面添加两行代码就行了
LOG_FILE = "log_name.log"
LOG_LEVEL = "DEBUG"
更多日志输出参考:https://blog.csdn.net/weixin_41666747/article/details/82716688
后记
- 这次任务的页面是关于aspx的,多见于政府消息发布的网页
- 照例补充点东西:关于__VIEWSTATE和__EVENTVALIDATION是干什么的
__VIEWSTATE
ViewState是ASP.NET中用来保存WEB控件回传时状态值一种机制。在WEB窗体(FORM)的设置为runat=“server”,这个窗体(FORM)会被附加一个隐藏的属性_VIEWSTATE。_VIEWSTATE中存放了所有控件在ViewState中的状态值。
ViewState是类Control中的一个域,其他所有控件通过继承Control来获得了ViewState功能。它的类型是system.Web.UI.StateBag,一个名称/值的对象集合。
当请求某个页面时,ASP.NET把所有控件的状态序列化成一个字符串,然后做为窗体的隐藏属性送到客户端。当客户端把页面回传时,ASP.NET分析回传的窗体属性,并赋给控件对应的值
__EVENTVALIDATION
__EVENTVALIDATION只是用来验证事件是否从合法的页面发送,只是一个数字签名,所以一般很短。
“id”属性为“__EVENTVALIDATION”的隐藏字段是ASP.NET 2.0的新增的安全措施。该功能可以阻止由潜在的恶意用户从浏览器端发送的未经授权的请求.
为了确保每个回发和回调事件来自于所期望的用户界面元素,ASP.NET运行库将在事件中添加额外的验证层。服务器端通过检验表单提交请求的内容,将其与“id”属性为“__EVENTVALIDATION”隐藏字段中的信息进行匹配。根据匹配结果来验证未在浏览器端添加额外的输入字段(有可能为用户在浏览器端恶意添加的字段),并且该值是在服务器已知的列表中选择的。ASP.NET运行库将在生成期间创建事件验证字段,而这是最不可能获取该信息的时刻。像视图状态一样,事件验证字段包含散列值以防止发生浏览器端篡改。
说明:“id”属性为“__EVENTVALIDATION”隐藏字段一般在表单的最下方,如果表单在浏览器端尚未解析完毕时,用户提交数据有可能导致验证失败。
Emmmm,在初始页面的时候,我觉得似乎使用CrawlSpider会简单那么一点点,没有试过呢,逃。
第二次任务也就基本完成了吧,怎么说呢,熟练度比第一次要好上许多,还是得多练吧,另外感谢组长的帮助啦~
如果有更好的方法或者不足之处,欢迎大家指正~