不知道网页链接如何爬取数据(一)

前言:有些时候,我们在查一些比较老的数据,由于网站升级,或者改版之类的,我们无法得到我们想要数据的网址,也就无法爬取数据,下面,我将带大家一起来分析一下自己的案例。

  1. 明确需求
    背景:在网上搜自己的名字,居然找到一份文档,大概是这样的样子2015年普通高校招生录取名单公示(五) (sxkszx.cn) 然后就顺腾摸瓜,想找到全部的数据——2015年全部的数据

  2. 查找数据
    刚开始,由于找到了网站,2015年普通高校招生录取名单公示(五) (sxkszx.cn),网址是http://www.sxkszx.cn/,我想在网站搜索,但是发现网站没有搜索功能,而且,更要命的是,这个每一页,没有上一页,下一页的链接,这样我们就找不到相关联的数据。
    而且,我们发现,网址的拼接也是很奇怪,http://www.sxkszx.cn/news/2015722/n82552675.html,news代表新闻,2015722代表发布日期,后面的n82552675就很奇怪,如果改成n82552676则会404,也就是无法单纯的修改最后一位来完成地址的模拟

  3. 使用搜索引擎增强搜索力度
    现在进入了困境,我们无法在该网站查找。不过我们可是使用
    2015年普通高校招生录取名单 site:sxkszx.cn
    来进行网站的查找,这样是使用搜索引擎来进行该网站的搜索,在百度地址栏输入搜索即可。
    然后我们会找到

    image.png

    很多数据被找到了,然后我们分析一下,发现其中缺少了一些公示,这意味这数据不太完整。

  4. 网站地址分析 + 试探
    现在问题又回到了原点,我们不知道网页的网址,那么就无法爬取数据。但是,现在要比最开始好很多,因为现在除了录取名单五以外,还多了很多,以供我们分析。

    • 整理一下,来分析一下数据的异同
image.png

为了能够看出其中的异同,我把数据一行一行列了出来,然后行号就是公示名单的数字标号(空缺部分表示目前未知的网站链接)

现在分析一下网址,我们发现,最后四位数字好像是递增的


image.png

对,这有点像是,新闻在数据库中存储的编号id,意味着这是第2669篇新闻,那么,第2670篇新闻的网址应该是怎样的呢?
推测如下

http://www.sxkszx.cn/news/日期/n四位不知名数字2670
且日期应当是在2015.7.22当天,或者之后

讲道理,我们这里应该要分析 四位不知名数字 的含义,或者讨论它是如何生成的,但是笔者想了很多,都没能猜到,之前猜测或者与时间/文章名字/等等,但是都不太对,总之没能猜到。

  • 由于我们没猜到,所以我们有一个最朴素的想法,我们遍历0000-9999不就可以了吗?找到那个可以正确返回的链接
    对,这个想法很正确。
下面的这一段代码,返回了一个列表,列表中包含了从0000-9999的所有可能的网址链接
def gene_urls():
    base_url = "http://www.sxkszx.cn/news/"
    date = "2015820"
    newsId = "2745"
    urls = []
    for i in range(1, 10000):
        s = str(i).zfill(4)
        url = base_url + date + "/n" + s + newsId + ".html"
        urls.append(url)
    return urls

写到这里,大家可能觉得,这不很简单吗?直接

for url in urls:
  response = requests.get(url)
  if response.status.code == 200:
      print url
      break

但是,这是很朴素的单线程,我们做一个计算
我们大概空缺的是

日期     新闻id
722      2675
723      2676
...         
83

         ...
         2696

我们发现,一次尝试,都要花费很长的时间,如果我们想要全部试探,需要很长的时间,且,requests要不断断开,建立连接,花销很大。

下面,我们尝试多线程。
下面是一份很长的代码,大家不用关心具体怎么实现的,只要知道
single_thread 代表单线程
multi_thread 代表多线程
即可

# 不断尝试url,当返回不是404,则加入my_urls.txt中

import requests
import threading
import requests.adapters
import time

base_url = "http://www.sxkszx.cn/news/"
date = "2015722"
newsId = "2678"

# f = open("my_urls.txt", 'w+')

flag = 0
# count = 0


def gene_urls():
    urls = []
    for i in range(1, 10000):
        s = str(i).zfill(4)
        url = base_url + date + "/n" + s + newsId + ".html"
        urls.append(url)
    return urls


def test_url(url):
    # response = requests.get(url=url, timeout=30)
    # if response.status_code == 200:
    #     print(url)

    # try:
    #     with requests.get(url, timeout=5) as r:
    #         if r.status_code == 200:
    #             flag = 1
    #             print(url)
    # except:
    #     print("处理异常中...")
    #     time.sleep(5)
    global flag
    if flag == 0:
        response = None
        global count
        try:
            # 设置重连次数
            requests.adapters.DEFAULT_RETRIES = 5
            s = requests.session()
            # 设置连接活跃状态为False
            s.keep_alive = False
            response = requests.get(url, stream=False, timeout=10)
            if response.status_code == 200:
                flag = 1
                print(url)
            # 关闭请求  释放内存
            response.close()
            del (response)
        except Exception as indentfier:
            time.sleep(5)


def single_thread(need_test_urls):
    for url in need_test_urls:
        global flag
        if flag == 0:
            test_url(url)
        else:
            break


def multi_thread(need_test_urls):
    threads = []
    for url in need_test_urls:
        threads.append(
            threading.Thread(target=test_url, args=(url,))
        )

    for thread in threads:
        thread.start()

    for thread in threads:
        thread.join()

    print("ok")


if __name__ == "__main__":
    u = gene_urls()
    multi_thread(u)
    # single_thread(u)

但是问题到这里还没有结束,尽管编写上面的代码,已经踩了很多的坑,包括 如requests未断开;未手动断开(采用with 语句,自动断开会导致他会慢慢断开,还是会报错,max tries,服务器中止...);
但是新的问题又来了,我发现这个代码在有的 日期 + 新闻id上可以运行出结果来,有的则不会,具体原因我也不太清楚,评论区的小伙伴有知道的,可以告诉一下我,谢谢~

  1. scrapy框架的使用
    最后的最后,我实在受不了了,我大概明白,应该是并发的时候,导致requests的连接无法断开,或者断开需要时间,但是还没有断开的这个期间,新的请求已经发送了,这样就会有一部分请求是没有效果的,也就是一部分链接被卡掉了。

而这个,是目前的我所解决不了的。

于是我想着试一下scrapy,因为我之前听过scrapy,但是没有用过,想着用它来解决并发问题,会不会好点。

先说实验结果,最终成功解决了并发问题,对于每一个 日期 + 新闻id 所产生的链接列表,大概在1mins内可以得到结果,已经算是很快了。

再说下去,就要讲scrapy框架了,但是现在我好饿,我先去吃个饭饭,宝宝饿了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,812评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,626评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,144评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,052评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,925评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,035评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,461评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,150评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,413评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,501评论 2 307
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,277评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,159评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,528评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,868评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,143评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,407评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,615评论 2 335

推荐阅读更多精彩内容