# 深入浅出爬虫之道: Python、Golang与GraphQuery的对比

深入浅出爬虫之道: Python、Golang与GraphQuery的对比

本文将分别使用 PythonGolang 以及 GraphQuery 来解析某网站的 素材详情页面 ,这个页面的特色是具有清晰的数据结构,但是DOM结构不够规范,无法通过单独的选择器定位页面元素,对页面的解析造成了一些曲折。通过这个页面的解析过程,深入浅出的了解爬虫的解析思想与这些语言之间的异同。

  • 深入浅出爬虫之道: Python、Golang与GraphQuery的对比

    • 一、前言

      • 1. 语义化的DOM结构
      • 2. 稳定的解析代码
    • 二、进行页面的解析
      • 使用Python进行页面的解析

        • 1. 获取title节点
        • 2. 获取size节点
        • 3. 完整的Python代码
      • 使用Golang进行页面的解析
      • 使用GraphQuery进行解析
        • 1. 在Golang中调用GraphQuery
        • 2. 在Python中调用GraphQuery
    • 三、后记

一、前言

在前言中,为了防止在后面的章节产生不必要的困扰,我们将会首先了解一些基本的编程理念。

1. 语义化的DOM结构

这里我们讲的语义化的DOM结构,不仅仅包括 语义化的html标签,也包括了语义化的选择器,在前端开发中应该注意的是,所有的动态文本都应该有单独的 html 标签包裹,并最好赋予其语义化的 class 属性或 id 属性,这在版本功能的迭代中,对前端和后端的开发都是大有裨益的,比如下面的HTML代码:

<div class="main-right fr">
    <p>编号:32490230</p>
    <p class="main-rightStage">模式:RGB</p>
    <p class="main-rightStage">体积:16.659 MB</p>
    <p class="main-rightStage">分辨率:72dpi</p>
</div>

这就是不够语义化的前端代码,32504070RGB16.659 MB72dpi这些值都是动态属性, 会跟随编号的改变而改变,在规范的开发中,应该将这些 动态变化的属性,分别用 <span> 这类行内标签包裹起来,并赋予其一定的语义化选择器,在上面的HTML结构中大致可以推测出这是后端直接使用 foreach 渲染出的页面,这是不符合前后端分离的思想的,如果有一天他们决定使用 jsonpAjax 渲染这些属性, 由前端进行渲染,工作量无疑会上一个层次。语义化的DOM结构更倾向于下面这样:

<p class="main-rightStage property-mode">
    模式:<span>RGB</span>
</p>

也可以将 property-mode 直接作为 spanclass 属性,这样这些属性无论是后端渲染,还是前端动态渲染都减轻了产品迭代产生的负担。

2. 稳定的解析代码

语义化的DOM结构 之后,我们来谈谈稳定的解析代码, 对于下面的DOM结构:

<div class="main-right fr">
    <p>编号:32490230</p>
    <p class="main-rightStage">模式:RGB</p>
    <p class="main-rightStage">体积:16.659 MB</p>
    <p class="main-rightStage">分辨率:72dpi</p>
</div>

如果我们想要提取 模式 信息,当然可以采取下面的步骤:

  1. 选取 class 属性中包含 main-rightdiv
  2. 选取这个 div 中第二个 p 元素,取出其包含的文本
  3. 删除文本中的 模式:, 得到模式为 RGB

虽然成功获取到了想要的结果,但是这样的解析方法,我们认为它是 不稳定的,这个不稳定是指 在其祖先元素、兄弟元素等自身以外的元素节点发生一定程度的结构改变时,导致解析错误或失败 的情况, 比如如果有一天在 模式 所在的节点之前增加了一个 尺寸 的属性:

<div class="main-right fr">
    <p>编号:32490230</p>
    <p class="main-rightStage">尺寸:4724×6299像素</p>
    <p class="main-rightStage">模式:RGB</p>
    <p class="main-rightStage">体积:16.659 MB</p>
    <p class="main-rightStage">分辨率:72dpi</p>
</div>

那么我们之前的解析将会发生错误(什么?你觉得不可能发生这样的变动?请对比 Page1Page2)。

那我们应该如何写出更稳定的解析代码呢,对于上面的DOM结构,我们可以有下面几种思路:

思路一: 遍历 class 属性为 main-rightStagep 节点,依次判断节点的文本是否以 模式 开头, 如果是, 取出其 后的内容,缺点是逻辑太多,不易维护且降低了代码可读性。

思路二: 使用正则表达式 模式:([A-Z]+) 进行匹配,缺点是使用不当可能造成效率问题。

思路三: 使用 CSS选择器中的 contains 方法,比如 .main-rightStage:contains(模式), 就可以选取文本中包含 模式,且 class 属性中包含 main-rightStage 的节点了。但缺点是不同语言和不同库对这种语法的支持程度各有不同,缺乏兼容性。

使用哪种方法,仁者见仁智者见智,不同的解析思路带来的解析的 稳定性、代码的 复杂程度运行效率兼容性 都是不同的, 开发者需要从各种因素中进行权衡, 来写出最优秀的解析代码。

二、进行页面的解析

在进行页面数据的抽取之前,首先要做的是明确我们需要哪些数据、页面上提供了哪些数据,然后设计出我们需要的数据结构。首先打开 待解析页面, 由于其最上方的 浏览量收藏量下载量等数据是动态加载的, 在我们的演示中暂时不需要,而这个页面右边的 尺寸模式 等数据,通过上面 Page1Page2 的对比,可以得知这些属性是不一定存在的,因此将它们一起归到 metainfo 中。因此我们需要获得的数据如下图所示:

由此我们可以很快设计出我们的数据结构:

{
    title
    pictype
    number
    type
    metadata {
        size
        volume
        mode
        resolution
    }
    author
    images []
    tags []
}

其中 sizevolumemoderesolution由于可能不存在,因此归入到了 metadata 下, images 是一个图片地址的数组,tags 是标签数组,在确定了要提取的数据结构,就可以开始进行解析。

使用Python进行页面的解析

Python库的数量非常庞大,有很多优秀的库可以帮助到我们,在使用Python进行页面的解析时,我们通常用到下面这些库:

  1. 提供 正则表达式 支持的 re
  2. 提供 CSS选择器 支持的 pyquerybeautifulsoup4
  3. 提供 Xpath 支持的 lxml
  4. 提供 JSON PATH 支持的 jsonpath_rw

这些库在 Python 3 下获得支持的,可以通过 pip install 进行安装。

由于 CSS选择器 的语法比 Xpath 语法要更加简洁,而在方法的调用上,pyquerybeautifulsoup4 要更加方便,因此在 2 和 3 之间我们选择了 pyquery

下面我们会以 titletype 属性的获取作为例子进行讲解, 其他节点的获取是同理的。首先我们先使用 requests 库下载这个页面的源文件:

import requests
from pyquery import PyQuery as pq
response = requests.get("http://www.58pic.com/newpic/32504070.html")
document = pq(response.content.decode(‘gb2312‘))

下面使用Python进行的解析都将依次为前提进行。

1. 获取title节点

打开 待解析页面,在标题上右键, 点击 查看元素,可以看到它的DOM结构如下:

这时我们注意到, 我们想要提取出的标题文本 大侠海报金庸武侠水墨中国风黑白,并没有被html标签包裹,这是不符合我们上面提到的 语义化的dom结构 的。同时,使用CSS选择器,也是无法直接选取到这个文本节点的(可以使用Xpath直接选取到,本文略)。对于这样的节点,我们可以有下面两种思路:

思路一: 先选取其父元素节点, 获取其 HTML 内容,使用正则表达式, 匹配在 </div><p 之间的文本。

思路二: 先选取其父元素节点,然后删除文本节点之外的其他节点,再直接通过获取父元素节点的文本,得到想要的标题文本。

我们采取思路二,写出下面的Python代码:

title_node = document.find(".detail-title")
title_node.find("div").remove()
title_node.find("p").remove()
print(title_node.text())

输出结果与我们期望的相同, 为 大侠海报金庸武侠水墨中国风黑白

2. 获取size节点

尺寸 上右键查看元素,可以看到下图所示的DOM结构:

我们发现这些节点不具有语义化的选择器,并且这些属性不一定都存在(详见Page1Page2 的对比)。在 稳定的解析代码 中我们也讲到了对于这种结构的文档可以采取的几种思路,这里我们采用正则解析的方法:

import re
context = document.find(".mainRight-file").text()
file_type_matches = re.compile("尺寸:(.*?像素)").findall(context)
filetype = ""
if len(file_type_matches) > 0:
    filetype =  file_type_matches[0]
print(filetype)

由于获取 sizevolumemoderesolution 这些属性,都可以采取类似的方法,因此我们可以归结出一个正则提取的函数:

def regex_get(text, expr):
    matches = re.compile(expr).findall(text)
    if len(matches) == 0:
        return ""
    return matches[0]

因此,在获取 size 节点时,我们的代码就可以精简为:

size = regex_get(context, r"尺寸:(.*?像素)")

3. 完整的Python代码

到这里,我们解析页面可能遇到的问题就已经解决了大半,整个Python代码如下:

import requests
import re
from pyquery import PyQuery as pq

def regex_get(text, expr):
    matches = re.compile(expr).findall(text)
    if len(matches) == 0:
        return ""
    return matches[0]

conseq = {}

## 下载文档
response = requests.get("http://www.58pic.com/newpic/32504070.html")
document = pq(response.text)

## 获取文件标题
title_node = document.find(".detail-title")
title_node.find("div").remove()
title_node.find("p").remove()
conseq["title"] = title_node.text()

## 获取素材类型
conseq["pictype"] = document.find(".pic-type").text()

## 获取文件格式
conseq["filetype"] =  regex_get(document.find(".mainRight-file").text(), r"文件格式:([a-z]+)")

## 获取元数据
context = document.find(".main-right p").text()
conseq[‘metainfo‘] = {
    "size": regex_get(context, r"尺寸:(.*?像素)"),
    "volume": regex_get(context, r"体积:(.*? MB)"),
    "mode": regex_get(context, r"模式:([A-Z]+)"),
    "resolution": regex_get(context, r"分辨率:(\d+dpi)"),
}

## 获取作者
conseq[‘author‘] = document.find(‘.user-name‘).text()

## 获取图片
conseq[‘images‘] = []
for node_image in document.find("#show-area-height img"):
    conseq[‘images‘].append(pq(node_image).attr("src"))

## 获取tag
conseq[‘tags‘] = []
for node_image in document.find(".mainRight-tagBox .fl"):
    conseq[‘tags‘].append(pq(node_image).text())

print(conseq)

使用Golang进行页面的解析

Golang 中解析 htmlxml 文档, 常用到的库有以下几种:

  1. 提供 正则表达式 支持的 regexp
  2. 提供 CSS选择器 支持的 github.com/PuerkitoBio/goquery
  3. 提供 Xpath 支持的 gopkg.in/xmlpath.v2
  4. 提供 JSON PATH 支持的 github.com/tidwall/gjson

这些库,你都可以通过 go get -u 来获取,由于在上面的Python解析中我们已经整理出了解析逻辑,在Golang中只需要复现即可,与 Python 不同的是,我们最好先为我们的数据结构定义一个 struct,像下面这样:

type Reuslt struct {
    Title    string
    Pictype  string
    Number   string
    Type     string
    Metadata struct {
        Size       string
        Volume     string
        Mode       string
        Resolution string
    }
    Author string
    Images []string
    Tags   []string
}

同时,由于我们的 待解析页面 是非主流的 gbk 编码,所以在下载下来文档之后,需要手动将 utf-8 的编码转换为 gbk 的编码,这个过程虽然不在解析的范畴之内,但是也是必须要做的步骤之一, 我们使用了 github.com/axgle/mahonia 这个库进行编码的转换,并整理出了编码转换的函数 decoderConvert

func decoderConvert(name string, body string) string {
    return mahonia.NewDecoder("gbk").ConvertString(body)
}

因此, 最终的 golang 代码应该是下面这样的:

package main

import (
    "encoding/json"
    "log"
    "regexp"
    "strings"

    "github.com/axgle/mahonia"
    "github.com/parnurzeal/gorequest"

    "github.com/PuerkitoBio/goquery"
)

type Reuslt struct {
    Title    string
    Pictype  string
    Number   string
    Type     string
    Metadata struct {
        Size       string
        Volume     string
        Mode       string
        Resolution string
    }
    Author string
    Images []string
    Tags   []string
}

func RegexGet(text string, expr string) string {
    regex, _ := regexp.Compile(expr)
    return regex.FindString(text)
}

func decoderConvert(name string, body string) string {
    return mahonia.NewDecoder("gbk").ConvertString(body)
}

func main() {
    //下载文档
    request := gorequest.New()
    _, body, _ := request.Get("http://www.58pic.com/newpic/32504070.html").End()
    document, err := goquery.NewDocumentFromReader(strings.NewReader(decoderConvert("gbk", body)))
    if err != nil {
        panic(err)
    }
    conseq := &Reuslt{}
    //获取文件标题
    titleNode := document.Find(".detail-title")
    titleNode.Find("div").Remove()
    titleNode.Find("p").Remove()
    conseq.Title = titleNode.Text()

    // 获取素材类型
    conseq.Pictype = document.Find(".pic-type").Text()
    // 获取文件格式
    conseq.Type = document.Find(".mainRight-file").Text()
    // 获取元数据
    context := document.Find(".main-right p").Text()
    conseq.Metadata.Mode = RegexGet(context, `尺寸:(.*?)像素`)
    conseq.Metadata.Resolution = RegexGet(context, `体积:(.*? MB)`)
    conseq.Metadata.Size = RegexGet(context, `模式:([A-Z]+)`)
    conseq.Metadata.Volume = RegexGet(context, `分辨率:(\d+dpi)`)
    // 获取作者
    conseq.Author = document.Find(".user-name").Text()
    // 获取图片
    document.Find("#show-area-height img").Each(func(i int, element *goquery.Selection) {
        if attribute, exists := element.Attr("src"); exists && attribute != "" {
            conseq.Images = append(conseq.Images, attribute)
        }
    })
    // 获取tag
    document.Find(".mainRight-tagBox .fl").Each(func(i int, element *goquery.Selection) {
        conseq.Tags = append(conseq.Tags, element.Text())
    })
    bytes, _ := json.Marshal(conseq)
    log.Println(string(bytes))
}

解析逻辑完全相同,代码量和复杂程度相较 python版 差不多,下面我们来看一下新出现的 GraphQuery 是如何做的。

使用GraphQuery进行解析

已知我们想要得到的数据结构如下:

{
    title
    pictype
    number
    type
    metadata {
        size
        volume
        mode
        resolution
    }
    author
    images []
    tags []
}

GraphQuery 的代码是下面这样的:

{
    title `xpath("/html/body/div[4]/div[1]/div/div/div[1]/text()")`
    pictype `css(".pic-type")`
    number `css(".detailBtn-down");attr("data-id")`
    type `regex("文件格式:([a-z]+)")`
    metadata `css(".main-right p")` {
        size `regex("尺寸:(.*?)像素")`
        volume `regex("体积:(.*? MB)")`
        mode `regex("模式:([A-Z]+)")`
        resolution `regex("分辨率:(\d+dpi)")`
    }
    author `css(".user-name")`
    images `css("#show-area-height img")` [
        src `attr("src")`
    ]
    tags `css(".mainRight-tagBox .fl")` [
        tag `text()`
    ]
}

通过对比可以看出, 它只是在我们设计的数据结构之中添加了一些由反引号包裹起来的函数。惊艳的是,它能完全还原我们上面在 PythonGolang 中的解析逻辑,而且从它的语法结构上,更能清晰的读出返回的数据结构。这段 GraphQuery 的执行结果如下:

{
    "data": {
        "author": "Ice bear",
        "images": [
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a0",
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a1024",
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a2048",
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a3072"
        ],
        "metadata": {
            "mode": "RGB",
            "resolution": "200dpi",
            "size": "4724×6299",
            "volume": "196.886 MB"
        },
        "number": "32504070",
        "pictype": "原创",
        "tags": ["大侠", "海报", "黑白", "金庸", "水墨", "武侠", "中国风"],
        "title": "大侠海报金庸武侠水墨中国风黑白",
        "type": "psd"
    },
    "error": "",
    "timecost": 10997800
}

GraphQuery 是一个文本查询语言,它不依赖于任何后端语言,可以被任何后端语言调用,一段 GraphQuery 查询语句,在任何语言中可以得到相同的解析结果。

它内置了 xpath选择器,css选择器,jsonpath 选择器和 正则表达式 ,以及足量的文本处理函数,结构清晰易读,能够保证 数据结构解析代码返回结果 结构的一致性。

项目地址: github.com/storyicon/graphquery

GraphQuery 的语法简洁易懂, 即使你是第一次接触它, 也能很快的上手, 它的语法设计理念之一就是 符合直觉, 我们应该如何执行它呢:

1. 在Golang中调用GraphQuery

golang 中,你只需要首先使用 go get -u github.com/storyicon/graphquery 获得 GraphQuery 并在代码中调用即可:

package main

import (
    "log"

    "github.com/axgle/mahonia"
    "github.com/parnurzeal/gorequest"
    "github.com/storyicon/graphquery"
)

func decoderConvert(name string, body string) string {
    return mahonia.NewDecoder("gbk").ConvertString(body)
}

func main() {
    request := gorequest.New()
    _, body, _ := request.Get("http://www.58pic.com/newpic/32504070.html").End()
    body = decoderConvert("gbk", body)
    response := graphquery.ParseFromString(body, "{ title `xpath(\"/html/body/div[4]/div[1]/div/div/div[1]/text()\")` pictype `css(\".pic-type\")` number `css(\".detailBtn-down\");attr(\"data-id\")` type `regex(\"文件格式:([a-z]+)\")` metadata `css(\".main-right p\")` { size `regex(\"尺寸:(.*?)像素\")` volume `regex(\"体积:(.*? MB)\")` mode `regex(\"模式:([A-Z]+)\")` resolution `regex(\"分辨率:(\\d+dpi)\")` } author `css(\".user-name\")` images `css(\"#show-area-height img\")` [ src `attr(\"src\")` ] tags `css(\".mainRight-tagBox .fl\")` [ tag `text()` ] }")
    log.Println(response)
}

我们的 GraphQuery 表达式以 单行 的形式, 作为函数 graphquery.ParseFromString 的第二个参数传入,得到的结果与预期完全相同。

2. 在Python中调用GraphQuery

Python 等其他后端语言中,调用 GraphQuery 需要首先启动其服务,服务已经为 windowsmaclinux 编译好,到 GraphQuery-http 中下载即可。

在解压并启动服务后,我们就可以愉快的使用 GraphQuery 在任何后端语言中对任何文档以图形的方式进行解析了。Python调用的示例代码如下:

import requests

def GraphQuery(document, expr):
    response = requests.post("http://127.0.0.1:8559", data={
        "document": document,
        "expression": expr,
    })
    return response.text

response = requests.get("http://www.58pic.com/newpic/32504070.html")
conseq = GraphQuery(response.text, r"""
    {
        title `xpath("/html/body/div[4]/div[1]/div/div/div[1]/text()")`
        pictype `css(".pic-type")`
        number `css(".detailBtn-down");attr("data-id")`
        type `regex("文件格式:([a-z]+)")`
        metadata `css(".main-right p")` {
            size `regex("尺寸:(.*?)像素")`
            volume `regex("体积:(.*? MB)")`
            mode `regex("模式:([A-Z]+)")`
            resolution `regex("分辨率:(\d+dpi)")`
        }
        author `css(".user-name")`
        images `css("#show-area-height img")` [
            src `attr("src")`
        ]
        tags `css(".mainRight-tagBox .fl")` [
            tag `text()`
        ]
    }
""")
print(conseq)

输出结果为:

{
    "data": {
        "author": "Ice bear",
        "images": [
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a0",
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a1024",
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a2048",
            "http://pic.qiantucdn.com/58pic/32/50/40/70d58PICZfkRTfbnM2UVe_PIC2018.jpg!/fw/1024/watermark/url/L2ltYWdlcy93YXRlcm1hcmsvZGF0dS5wbmc=/repeat/true/crop/0x1024a0a3072"
        ],
        "metadata": {
            "mode": "RGB",
            "resolution": "200dpi",
            "size": "4724×6299",
            "volume": "196.886 MB"
        },
        "number": "32504070",
        "pictype": "原创",
        "tags": ["大侠", "海报", "黑白", "金庸", "水墨", "武侠", "中国风"],
        "title": "大侠海报金庸武侠水墨中国风黑白",
        "type": "psd"
    },
    "error": "",
    "timecost": 10997800
}

三、后记

复杂的解析逻辑带来的不仅仅是代码可读性的问题,在代码的维护和移植上也会造成很大的困扰,不同的语言和不同的库也为代码的解析结果造成了差异,GraphQuery 是一个全新的开源项目,它的主旨就是让开发者从这些重复繁琐的解析逻辑中解脱出来,写出高可读性、高可移植性、高可维护性的代码。欢迎实践、持续关注与代码贡献,一起见证 GraphQuery 与开源社区的发展!

原文地址:https://www.cnblogs.com/gomaster/p/9889487.html

时间: 2024-10-01 21:02:09

# 深入浅出爬虫之道: Python、Golang与GraphQuery的对比的相关文章

爬虫学习 04.Python网络爬虫之requests模块(1)

爬虫学习 04.Python网络爬虫之requests模块(1) 引入 Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用. 警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症.冗余代码症.重新发明轮子症.啃文档症.抑郁.头疼.甚至死亡. 今日概要 基于requests的get请求 基于requests模块的post请求 基于requests模块ajax的get请求 基于requests模块ajax的post请求 综合项目练习:爬取国家药品监

爬虫学习 06.Python网络爬虫之requests模块(2)

爬虫学习 06.Python网络爬虫之requests模块(2) 今日内容 session处理cookie proxies参数设置请求代理ip 基于线程池的数据爬取 知识点回顾 xpath的解析流程 bs4的解析流程 常用xpath表达式 常用bs4解析方法 了解cookie和session - 无状态的http协议 如上图所示,HTTP协议 是无状态的协议,用户浏览服务器上的内容,只需要发送页面请求,服务器返回内容.对于服务器来说,并不关心,也并不知道是哪个用户的请求.对于一般浏览性的网页来说

爬虫学习 05.Python网络爬虫之三种数据解析方式

爬虫学习 05.Python网络爬虫之三种数据解析方式 引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据解析.因为大多数情况下的需求,我们都会指定去使用聚焦爬虫,也就是爬取页面中指定部分的数据值,而不是整个页面的数据.因此,本次课程中会给大家详细介绍讲解三种聚焦爬虫中的数据解析方式.至此,我们的数据爬取的流程可以修改为: 指定url 基于r

爬虫学习 08.Python网络爬虫之图片懒加载技术、selenium和PhantomJS

爬虫学习 08.Python网络爬虫之图片懒加载技术.selenium和PhantomJS 引入 今日概要 图片懒加载 selenium phantomJs 谷歌无头浏览器 知识点回顾 验证码处理流程 今日详情 动态数据加载处理 一.图片懒加载 什么是图片懒加载? 案例分析:抓取站长素材http://sc.chinaz.com/中的图片数据 #!/usr/bin/env python # -*- coding:utf-8 -*- import requests from lxml import

爬虫学习 16.Python网络爬虫之Scrapy框架(CrawlSpider)

爬虫学习 16.Python网络爬虫之Scrapy框架(CrawlSpider) 引入 提问:如果想要通过爬虫程序去爬取"糗百"全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法). 方法二:基于CrawlSpider的自动爬取进行实现(更加简洁和高效). 今日概要 CrawlSpider简介 CrawlSpider使用 基于CrawlSpider爬虫文件的创建 链接提取器 规则解析器 今日详

开源爬虫Labin,Nutch,Neritrix介绍和对比

开源爬虫Labin,Nutch,Neritrix介绍和对比 2 6 从网上找了一些开源spider的相关资料,整理在下面: Larbin开发语言:C++http://larbin.sourceforge.net/index-eng.htmllarbin是个基于C++的web爬虫工具,拥有易于操作的界面,不过只能跑在LINUX下,在一台普通PC下larbin每天可以爬5百万个页面(当然啦,需要拥有良好的网络) 简介 Larbin是一种开源的网络爬虫/网络蜘蛛,由法国的年轻人 Sébastien A

Python按行读文件对比

1. 最基本的读文件方法: # File: readline-example-1.py file = open("sample.txt") while 1:     line = file.readline()     if not line:         break     pass # do something 一行一行得从文件读数据,显然比较慢:不过很省内存. 在我的机器上读10M的sample.txt文件,每秒大约读32000行 2. 用fileinput模块 # File

回复:《golang VS php 性能对比》

连接:http://www.oschina.net/question/29420_138135 看到有一篇博文介绍Golang与PHP性能对比,在此回复一下.这测试结果明显是误导人的. 1,PHP未开启OpCache,那么每次都要读磁盘文件.并且编译PHP为OpCode.性能自然会差,开启OpCache试试吧. 2.php+redis一定要扩展版本的redis客户端,原因是redis扩展是长连接的,可以避免短连接带来的网络开销. 3.php-fpm或者Apache,就算只开20个进程.redis

python介绍 编程语言分类及对比 python解释器安装(多版本共存) 变量 数据类型(三种)

python介绍编程语言分类及对比python解释器安装(多版本共存)变量数据类型(三种) 一:python介绍 1.python是什么? python是一门编程语言,编程语言就是一门语言 语言就是一个事物与另外一个事物沟通的工具 而编程语言则是人与计算机沟通的介质 2.为什么要跟计算机沟通:为了奴役计算机 奴隶主-------(人类的语言)-------->奴隶 奴隶主-------(编程语言)-------->计算机 3.什么是编程 奴隶主把想让计算机替自己做事情的逻辑用编程语言给表达出来