美文网首页Python新世界python热爱者
爬虫工程师熬夜写了这篇文章,关于Python爬虫的一些方法总结!

爬虫工程师熬夜写了这篇文章,关于Python爬虫的一些方法总结!

作者: 48e0a32026ae | 来源:发表于2018-10-31 15:54 被阅读4次

爬虫原理与数据抓取

Requests简单使用

添加 headers 和 查询参数

如果想添加 headers,可以传入headers参数来增加请求头中的headers信息。如果要将参数放在url中传递,可以利用 params 参数

学习Python中有不明白推荐加入交流群

                号:516107834

                群里有志同道合的小伙伴,互帮互助,

                群里有不错的学习教程!

import requests

kw = {'wd':'长城'}

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()

response = requests.get("http://www.baidu.com/s?", params = kw, headers = headers)

# 查看响应内容,response.text 返回的是Unicode格式的数据

print (response.text)

# 查看响应内容,response.content返回的字节流数据

print (respones.content)

# 查看完整url地址

print (response.url)

# 查看响应头部字符编码

print (response.encoding)

# 查看响应码

print (response.status_code)

使用response.text 时,Requests 会基于 HTTP 响应的文本编码自动解码响应内容,大多数 Unicode 字符集都能被无缝地解码。 使用response.content 时,返回的是服务器响应数据的原始二进制字节流,可以用来保存图片等二进制文件。

requests默认自带的Accept-Encoding导致或者新浪默认发送的就是压缩之后的网页

但是为什么content.read()没有问题,因为requests,自带解压压缩网页的功能

当收到一个响应时,Requests 会猜测响应的编码方式,用于在你调用response.text 方法时对响应进行解码。Requests 首先在 HTTP 头部检测是否存在指定的编码方式,如果不存在,则会使用 chardet.detect来尝试猜测编码方式(存在误差)

更推荐使用response.content.deocde()

Requests深入

# 如果是json文件可以直接显示

print (response.json())

# unquote将url格式的中文还原

a = requests.utils.unquote('http://www.baidu.com/f?kw=%E6%9D%E6%85%')

print(a)

http://www.baidu.com/f?kw=李子

通过本地环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理:

export HTTP_PROXY="http://12.34.56.79:9527"

export HTTPS_PROXY="https://12.34.56.79:9527"

私密代理验证(特定格式) 和 Web客户端验证(auth 参数)

私密代理

import requests

# 如果代理需要使用HTTP Basic Auth,可以使用下面这种格式:

proxy = { "http": "mr_mao_hacker:sffqry9r@61.158.163.130:16816" }

response = requests.get("http://www.baidu.com", proxies = proxy)

print (response.text)

web客户端验证

如果是Web客户端验证,需要添加 auth = (账户名, 密码)

1 import requests

2

3 auth=('test', '123456')

4

5 response = requests.get('http://192.168.199.107', auth = auth)

6

7 print (response.text)

Cookies

1 import requests

2

3 response = requests.get("http://www.baidu.com/")

4

5 # 7. 返回CookieJar对象:

6 cookiejar = response.cookies

7

8 # 8. 将CookieJar转为字典:

9 cookiedict = requests.utils.dict_from_cookiejar(cookiejar)

10

11 print (cookiejar)

12

13 print (cookiedict)

session

实现人人网登录

import requests

# 1. 创建session对象,可以保存Cookie值

ssion = requests.session()

# 2. 处理 headers

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# 3. 需要登录的用户名和密码

data = {"email":"", "password":""}

# 4. 发送附带用户名和密码的请求,并获取登录后的Cookie值,保存在ssion里

ssion.post("http://www.renren.com/PLogin.do", data = data)

# 5. ssion包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面

response = ssion.get("http://www.renren.com/410043129/profile")

# 6. 打印响应内容

print (response.text)

处理HTTPS请求 SSL证书验证

Requests也可以为HTTPS请求验证SSL证书:

要想检查某个主机的SSL证书,你可以使用 verify 参数(也可以不写)

如果SSL证书验证不通过,或者不信任服务器的安全证书,则会报出SSLError,据说 12306 证书是自己做的

如果我们想跳过 12306 的证书验证,把 verify 设置为 False 就可以正常请求了

SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

非结构化数据与结构化数据提取

XPath与lxml类库

bookstore//book

选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置

/bookstore/book[last()-1]

选取属于 bookstore 子元素的倒数第二个 book 元素

/bookstore/book[position()<3]

选取最前面的两个属于 bookstore 元素的子元素的 book 元素

/bookstore/book[price>35.00]/title

选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00

//book/title | //book/price

选取 book 元素的所有 title 和 price 元素

//title | //price

选取文档中的所有 title 和 price 元素

/bookstore/book/title | //price

选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素

//li//span

获取

  • 标签下的所有 标签
  • //li/a//@class

    获取

  • 标签下的标签里的所有 class
  • //li[last()]/a/@href

    获取最后一个

  • 的 href
  • JSON

    json.loads()

    从json到python的类型转化

    json.dumps()

    从python原始类型向json类型的转化

    chardet是一个非常优秀的编码识别模块,可通过pip安装。chardet.detect()返回字典, 其中confidence是检测精确度

    json.dump()

    将Python内置类型序列化为json对象后写入文

    1 import json

    2

    3 listStr = [{"city": "北京"}, {"name": "大刘"}]

    4 json.dump(listStr, open("listStr.json","w"), ensure_ascii=False)

    5

    6 dictStr = {"city": "北京", "name": "大刘"}

    7 json.dump(dictStr, open("dictStr.json","w"), ensure_ascii=False)

    json.load()

    读取文件中json形式的字符串元素 转化成python类型

    1 import json

    2

    3 strList = json.load(open("listStr.json"))

    4 print strList

    5

    6 # [{u'city': u'\u5317\u4eac'}, {u'name': u'\u5927\u5218'}]

    7

    8 strDict = json.load(open("dictStr.json"))

    9 print strDict

    10 # {u'city': u'\u5317\u4eac', u'name': u'\u5927\u5218'}

    Queue

    Queue是python中的标准库,可以直接import Queue引用;队列是线程间最常用的交换数据的形式

    对于资源,加锁是个重要的环节。因为python原生的list,dict等,都是not thread safe的。而Queue,是线程安全的,因此在满足使用条件下,建议使用队列

    初始化: class Queue.Queue(maxsize) FIFO 先进先出

    包中的常用方法:

    Queue.qsize() 返回队列的大小

    Queue.empty() 如果队列为空,返回True,反之False

    Queue.full() 如果队列满了,返回True,反之False

    Queue.full 与 maxsize 大小对应

    Queue.get([block[, timeout]])获取队列,timeout等待时间

    创建一个“队列”对象

    import Queue

    myqueue = Queue.Queue(maxsize = 10)

    将一个值放入队列中

    myqueue.put(10)

    将一个值从队列中取出

    myqueue.get()

    BeautifulSoup4

    lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml

    1 print soup.name

    2 # [document] #soup 对象本身比较特殊,它的 name 即为 [document]

    3

    4 print soup.head.name

    5 # head #对于其他内部标签,输出的值便为标签本身的名称

    6

    7 print soup.p.attrs

    8 # {'class': ['title'], 'name': 'dromouse'}

    9 # 在这里,我们把 p 标签的所有属性打印输出了出来,得到的类型是一个字典。

    10

    11 print soup.p['class'] # soup.p.get('class')

    12 # ['title'] #还可以利用get方法,传入属性的名称,二者是等价的

    13

    14 soup.p['class'] = "newClass"

    15 print soup.p # 可以对这些属性和内容等等进行修改

    16 #

    The Dormouse's story

    17

    18 del soup.p['class'] # 还可以对这个属性进行删除

    19 print soup.p

    20 #

    The Dormouse's story

    21

    22 print soup.p.string

    23 # The Dormouse's story

    24

    25 print type(soup.p.string)

    26 # In [13]:

    27

    28 # Comment 对象是一个特殊类型的 NavigableString 对象,其输出的内容不包括注释符号

    29 print soup.a

    30 #

    31

    32 print soup.a.string

    33 # Elsie

    34

    35 print type(soup.a.string)

    36 #

    37 # tag 的 .content 属性可以将tag的子节点以列表的方式输出

    38 print soup.head.contents

    39 #[The Dormouse's story]

    40 print soup.head.contents[0]

    41 #The Dormouse's story

    42

    43 # .children 返回的是一个 list 生成器对象,通过遍历获取所有子节点

    44 print soup.head.children

    45 #

    46

    47 for child in soup.body.children:

    48 print child

    49

    50 # 所有子孙节点: .descendants 属性

    51 .contents 和 .children 属性仅包含tag的直接子节点,.descendants 属性可以对所有tag的子孙节点进行递归循环,和 children类似,我们也需要遍历获取其中的内容

    52 for child in soup.descendants:

    53 print child

    动态HTML处理和机器图像识别

    Selenium

    1 # 调用键盘按键操作时需要引入的Keys包

    2 from selenium.webdriver.common.keys import Keys

    3

    4 # 生成当前页面快照并保存

    5 driver.save_screenshot("baidu.png")

    6

    7 # 打印网页渲染后的源代码

    8 print driver.page_source

    9

    10 # 获取当前页面Cookie

    11 print driver.get_cookies()

    12

    13 # ctrl+a 全选输入框内容

    14 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')

    15

    16 # ctrl+x 剪切输入框内容

    17 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')

    18

    19 # 模拟Enter回车键

    20 driver.find_element_by_id("su").send_keys(Keys.RETURN)

    21

    22 # 获取当前url

    23 print driver.current_url

    24

    25 # 关闭当前页面,如果只有一个页面,会关闭浏览器

    26 # driver.close()

    27

    28 # 关闭浏览器

    29 driver.quit()

    页面操作

    1 # 获取id标签值

    2 element = driver.find_element_by_id("passwd-id")

    3 # 获取name标签值

    4 element = driver.find_element_by_name("user-name")

    5 # 获取标签名值

    6 element = driver.find_elements_by_tag_name("input")

    7 # 也可以通过XPath来匹配

    8 element = driver.find_element_by_xpath("//input[@id='passwd-id']")

    9

    10 find_element_by_id

    11 find_elements_by_name

    12 find_elements_by_xpath

    13 find_elements_by_link_text

    14 # 上下两行区别:

    15 # partial 是部分的意思,可以定位a标签文本里的部分内容

    16 find_elements_by_partial_link_text

    17 find_elements_by_tag_name

    18 find_elements_by_class_name

    19 find_elements_by_css_selector

    鼠标动作链

    1 #导入 ActionChains 类

    2 from selenium.webdriver import ActionChains

    3

    4 # 鼠标移动到 ac 位置

    5 ac = driver.find_element_by_xpath('element')

    6 ActionChains(driver).move_to_element(ac).perform()

    7

    8

    9 # 在 ac 位置单击

    10 ac = driver.find_element_by_xpath("elementA")

    11 ActionChains(driver).move_to_element(ac).click(ac).perform()

    12

    13 # 在 ac 位置双击

    14 ac = driver.find_element_by_xpath("elementB")

    15 ActionChains(driver).move_to_element(ac).double_click(ac).perform()

    16

    17 # 在 ac 位置右击

    18 ac = driver.find_element_by_xpath("elementC")

    19 ActionChains(driver).move_to_element(ac).context_click(ac).perform()

    20

    21 # 在 ac 位置左键单击hold住

    22 ac = driver.find_element_by_xpath('elementF')

    23 ActionChains(driver).move_to_element(ac).click_and_hold(ac).perform()

    24

    25 # 将 ac1 拖拽到 ac2 位置

    26 ac1 = driver.find_element_by_xpath('elementD')

    27 ac2 = driver.find_element_by_xpath('elementE')

    28 ActionChains(driver).drag_and_drop(ac1, ac2).perform()

    填充表单

    1 # 导入 Select 类

    2 from selenium.webdriver.support.ui import Select

    3

    4 # 找到 name 的选项卡

    5 select = Select(driver.find_element_by_name('status'))

    6

    7 #

    8 select.select_by_index(1)

    9 select.select_by_value("0")

    10 select.select_by_visible_text(u"未审核")

    以上是三种选择下拉框的方式,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择。注意:

    index 索引从 0 开始

    value是option标签的一个属性值,并不是显示在下拉框中的值

    visible_text是在option标签文本的值,是显示在下拉框的值

    全部取消选择

    alert = driver.switch_to_alert()

    页面切换

    一个浏览器肯定会有很多窗口,所以我们肯定要有方法来实现窗口的切换。切换窗口的方法如下:

    driver.switch_to.window("this is window name")

    也可以使用 window_handles 方法来获取每个窗口的操作对象。例如:

    for handle in driver.window_handles:

    driver.switch_to_window(handle)

    页面前进和后退

    driver.forward() #前进

    driver.back() # 后退

    Cookies

    1 for cookie in driver.get_cookies():

    2 print "%s -> %s" % (cookie['name'], cookie['value'])

    3

    4 # By name

    5 driver.delete_cookie("CookieName")

    6

    7 # all

    8 driver.delete_all_cookies()

    页面等待

    隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。

    显式等待

    显式等待指定某个条件,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常了

    1 from selenium import webdriver

    2 from selenium.webdriver.common.by import By

    3 # WebDriverWait 库,负责循环等待

    4 from selenium.webdriver.support.ui import WebDriverWait

    5 # expected_conditions 类,负责条件出发

    6 from selenium.webdriver.support import expected_conditions as EC

    7

    8 driver = webdriver.Chrome()

    9 driver.get("http://www.xxxxx.com/loading")

    10 try:

    11 # 页面一直循环,直到 id="myDynamicElement" 出现

    12 element = WebDriverWait(driver, 10).until(

    13 EC.presence_of_element_located((By.ID, "myDynamicElement"))

    14 )

    15 finally:

    16 driver.quit()

    如果不写参数,程序默认会 0.5s 调用一次来查看元素是否已经生成,如果本来元素就是存在的,那么会立即返回

    下面是一些内置的等待条件,你可以直接调用这些条件,而不用自己写某些等待条件了

    title_is

    title_contains

    presence_of_element_located

    visibility_of_element_located

    visibility_of

    presence_of_all_elements_located

    text_to_be_present_in_element

    text_to_be_present_in_element_value

    frame_to_be_available_and_switch_to_it

    invisibility_of_element_located

    element_to_be_clickable – it is Displayed and Enabled.

    staleness_of

    element_to_be_selected

    element_located_to_be_selected

    element_selection_state_to_be

    element_located_selection_state_to_be

    alert_is_present

    隐式等待

    不设置,默认等待时间为0,单位为秒

    1 from selenium import webdriver

    2

    3 driver = webdriver.Chrome()

    4 driver.implicitly_wait(10) # seconds

    5 driver.get("http://www.xxxxx.com/loading")

    6 myDynamicElement = driver.find_element_by_id("myDynamicElement")

    def __del__(self):

    '''调用内建的稀构方法,在程序退出的时候自动调用

    类似的还可以在文件打开的时候调用close,数据库链接的断开

    '''

    self.driver.quit()

    # 默认这个方法是对象使用后自动销毁对象用的,在这里修改为对象使用后关闭浏览器

    Tesseract与pytesseract

    1 import pytesseract

    2 from PIL import Image

    3

    4 image = Image.open('test.jpg')

    5 text = pytesseract.image_to_string(image)

    6 print text

    7 对图片进行阈值过滤和降噪处理

    8 from PIL import Image

    9 import subprocess

    10

    11 def cleanFile(filePath, newFilePath):

    12 image = Image.open(filePath)

    13

    14 # 对图片进行阈值过滤(低于143的置为黑色,否则为白色)

    15 image = image.point(lambda x: 0 if x < 143 else 255)

    16 # 重新保存图片

    17 image.save(newFilePath)

    18

    19 # 调用系统的tesseract命令对图片进行OCR识别

    20 subprocess.call(["tesseract", newFilePath, "output"])

    21

    22 # 打开文件读取结果

    23 with open("output.txt", 'r') as f:

    24 print(f.read())

    25

    26 if __name__ == "__main__":

    27 cleanFile("text2.png", "text2clean.png")

    scrapy框架

    保存数据

    scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,,命令如下:

    # json格式,默认为Unicode编码

    scrapy crawl itcast -o teachers.json

    # json lines格式,默认为Unicode编码

    scrapy crawl itcast -o teachers.jsonl

    # csv 逗号表达式,可用Excel打开

    scrapy crawl itcast -o teachers.csv

    # xml格式

    scrapy crawl itcast -o teachers.xml

    元素选取

    contains的用法,or的用法,last()的含义

    response.xpath('//*[contains(@class,"odd") or contains(@class,"even")]/td[last()]/text()').extract()

    0-1000随意设置,数值越低,组件的优先级越高

    parse()方法的工作机制

    因为使用的yield,而不是return。parse函数将会被当做一个生成器使用。scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型

    如果是request则加入爬取队列,如果是item类型则使用pipeline处理,其他类型则返回错误信息

    scrapy取到第一部分的request不会立马就去发送这个request,只是把这个request放到队列里,然后接着从生成器里获取

    取尽第一部分的request,然后再获取第二部分的item,取到item了,就会放到对应的pipeline里处理

    parse()方法作为回调函数(callback)赋值给了Request,指定parse()方法来处理这些请求 scrapy.Request(url, callback=self.parse)

    Request对象经过调度,执行生成 scrapy.http.response()的响应对象,并送回给parse()方法,直到调度器中没有Request(递归的思路)

    取尽之后,parse()工作结束,引擎再根据队列和pipelines中的内容去执行相应的操作

    程序在取得各个页面的items前,会先处理完之前所有的request队列里的请求,然后再提取item

    这一切的一切,Scrapy引擎和调度器将负责到底

    CrawlSpiders

    rule

    CrawlSpider使用rules来决定爬虫的爬取规则,并将匹配后的url请求提交给引擎。所以在正常情况下,CrawlSpider不需要单独手动返回请求了

    link_extractor:是一个Link Extractor对象,用于定义需要提取的链接

    callback: 从link_extractor中每获取到链接时,参数所指定的值作为回调函数,该回调函数接受一个response作为其第一个参数

    注意:当编写爬虫规则时,避免使用parse作为回调函数。由于CrawlSpider使用parse方法来实现其逻辑,如果覆盖了 parse方法,crawl spider将会运行失败

    follow:是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果callback为None,follow 默认设置为True ,否则默认为False

    process_links:指定该spider中哪个的函数将会被调用,从link_extractor中获取到链接列表时将会调用该函数。该方法主要用来过滤

    process_request:指定该spider中哪个的函数将会被调用, 该规则提取到每个request时都会调用该函数。 (用来过滤request)

    Request和Response

    发送POST请求

    可以使用 yield scrapy.FormRequest(url, formdata, callback)方法发送POST请求

    如果希望程序执行一开始就发送POST请求,可以重写Spider类的start_requests(self) 方法,并且不再调用start_urls里的url

    1 class mySpider(scrapy.Spider):

    2 # start_urls = ["http://www.example.com/"]

    3

    4 def start_requests(self):

    5 url = 'http://www.renren.com/PLogin.do'

    6

    7 # FormRequest 是Scrapy发送POST请求的方法

    8 yield scrapy.FormRequest(

    9 url = url,

    10 formdata = {"email" : "mr_mao_hacker@163.com", "password" : "axxxxxxxe"},

    11 callback = self.parse_page

    12 )

    13 def parse_page(self, response):

    14 # do something

    模拟登陆

    使用FormRequest.from_response()方法模拟用户登录

    通常网站通过 实现对某些表单字段(如数据或是登录界面中的认证令牌等)的预填充

    使用Scrapy抓取网页时,如果想要预填充或重写像用户名、用户密码这些表单字段, 可以使用 FormRequest.from_response() 方法实现

    1 import scrapy

    2

    3 class LoginSpider(scrapy.Spider):

    4 name = 'example.com'

    5 start_urls = ['http://www.example.com/users/login.php']

    6

    7 def parse(self, response):

    8 return scrapy.FormRequest.from_response(

    9 response,

    10 formdata={'username': 'john', 'password': 'secret'},

    11 callback=self.after_login

    12 )

    13

    14 def after_login(self, response):

    15 # check login succeed before going on

    16 if "authentication failed" in response.body:

    17 self.log("Login failed", level=log.ERROR)

    18 return

    中间件

    防止爬虫被反

    动态设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息)

    禁用Cookies(也就是不启用cookies middleware,不向Server发送cookies,有些网站通过cookie的使用发现爬虫行为)

    可以通过COOKIES_ENABLED 控制 CookiesMiddleware 开启或关闭

    设置延迟下载(防止访问过于频繁,设置为 2秒 或更高)

    Google Cache 和 Baidu Cache:如果可能的话,使用谷歌/百度等搜索引擎服务器页面缓存获取页面数据

    使用IP地址池:VPN和代理IP,现在大部分网站都是根据IP来ban的

    使用 Crawlera(专用于爬虫的代理组件),正确配置和设置下载中间件后,项目所有的request都是通过crawlera发出

    DOWNLOADER_MIDDLEWARES = {

    'scrapy_crawlera.CrawleraMiddleware': 600

    }

    CRAWLERA_ENABLED = True

    CRAWLERA_USER = '注册/购买的UserKey'

    CRAWLERA_PASS = '注册/购买的Password'

    下载中间件

    1 # middlewares.py

    2

    3 #!/usr/bin/env python

    4 # -*- coding:utf-8 -*-

    5

    6 import random

    7 import base64

    8

    9 from settings import USER_AGENTS

    10 from settings import PROXIES

    11

    12 # 随机的User-Agent

    13 class RandomUserAgent(object):

    14 def process_request(self, request, spider):

    15 useragent = random.choice(USER_AGENTS)

    16

    17 request.headers.setdefault("User-Agent", useragent)

    18

    19 class RandomProxy(object):

    20 def process_request(self, request, spider):

    21 proxy = random.choice(PROXIES)

    22

    23 if proxy['user_passwd'] is None:

    24 # 没有代理账户验证的代理使用方式

    25 request.meta['proxy'] = "http://" + proxy['ip_port']

    26 else:

    27 # 对账户密码进行base64编码转换

    28 base64_userpasswd = base64.b64encode(proxy['user_passwd'])

    29 # 对应到代理服务器的信令格式里

    30 request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd

    31 request.meta['proxy'] = "http://" + proxy['ip_port']

    为什么HTTP代理要使用base64编码: HTTP代理的原理很简单,就是通过HTTP协议与代理服务器建立连接,协议信令中包含要连接到的远程主机的IP和端口号,如果有需要身份验证的话还需要加上授权信息,服务器收到信令后首先进行身份验证,通过后便与远程主机建立连接,连接成功之后会返回给客户端200,表示验证通过,就这么简单,下面是具体的信令格式:

    settings

    BOT_NAME

    默认: 'scrapybot'

    当您使用 startproject 命令创建项目时其也被自动赋值

    CONCURRENT_ITEMS

    默认: 100

    Item Processor(即 Item Pipeline) 同时处理(每个response的)item的最大值

    CONCURRENT_REQUESTS

    默认: 16

    Scrapy downloader 并发请求(concurrent requests)的最大值

    DEFAULT_REQUEST_HEADERS

    默认: 如下

    {

    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

    'Accept-Language': 'en',

    }

    Scrapy HTTP Request使用的默认header。

    DEPTH_LIMIT

    默认: 0

    爬取网站最大允许的深度(depth)值。如果为0,则没有限制

    DOWNLOAD_DELAY

    默认: 0

    下载器在下载同一个网站下一个页面前需要等待的时间。该选项可以用来限制爬取速度, 减轻服务器压力。同时也支持小数

    DOWNLOAD_DELAY = 0.25 # 250 ms of delay

    默认情况下,Scrapy在两个请求间不等待一个固定的值, 而是使用0.5到1.5之间的一个随机值 * DOWNLOAD_DELAY 的结果作为等待间隔

    DOWNLOAD_TIMEOUT

    默认: 180

    下载器超时时间(单位: 秒)

    ITEM_PIPELINES

    默认: {}

    保存项目中启用的pipeline及其顺序的字典。该字典默认为空,值(value)任意,不过值(value)习惯设置在0-1000范围内,值越小优先级越高

    ITEM_PIPELINES = {

    'mySpider.pipelines.SomethingPipeline': 300,

    'mySpider.pipelines.ItcastJsonPipeline': 800,

    }

    LOG_ENABLED

    默认: True

    是否启用logging

    LOG_ENCODING

    默认: 'utf-8'

    logging使用的编码

    LOG_LEVEL

    默认: 'DEBUG'

    log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG

    USER_AGENT

    默认: "Scrapy/VERSION (+http://scrapy.org)"

    爬取的默认User-Agent,除非被覆盖

    PROXIES: 代理设置

    COOKIES_ENABLED = False

    禁用Cookies

    scrapy-redis

    Scrapy-redis提供了下面四种组件(components):(四种组件意味着这四个模块都要做相应的修改)

    Scheduler

    Duplication Filter

    Item Pipeline

    Base Spider

    scrapy-redis的总体思路

    这个工程通过重写scheduler和spider类,实现了调度、spider启动和redis的交互

    实现新的dupefilter和queue类,达到了判重和调度容器和redis的交互,因为每个主机上的爬虫进程都访问同一个redis数据库,所以调度和判重都统一进行统一管理,达到了分布式爬虫的目的

    当spider被初始化时,同时会初始化一个对应的scheduler对象,这个调度器对象通过读取settings,配置好自己的调度容器queue和判重工具dupefilter

    每当一个spider产出一个request的时候,scrapy内核会把这个reuqest递交给这个spider对应的scheduler对象进行调度,scheduler对象通过访问redis对request进行判重,如果不重复就把他添加进redis中的调度池

    当调度条件满足时,scheduler对象就从redis的调度池中取出一个request发送给spider,让他爬取

    当spider爬取的所有暂时可用url之后,scheduler发现这个spider对应的redis的调度池空了,于是触发信号spider_idle,spider收到这个信号之后,直接连接redis读取strart url池,拿去新的一批url入口,然后再次重复上边的工作

    相关文章

    网友评论

      本文标题:爬虫工程师熬夜写了这篇文章,关于Python爬虫的一些方法总结!

      本文链接:https://www.haomeiwen.com/subject/ucmatqtx.html