近期的总结

即将开始一个新的阶段,慢慢积累慢慢进步吧

Scrapy

  • scrapy startproject [project_name]

  • Item定义保存的数据模型,API和dict 基本相同

  • Spider 类是所有必须继承的基本类

    • start_urls 为爬取列表,需要指定或覆写start_requests 方法,若覆写了该方法,start_urls 将不会被使用
    • custom_settings 可以覆盖settings.py 中的配置
    • start_requests() 该方法只会被框架调用一次,必须返回一个可迭代对象(返回一个list或使用yield 实现为生成器)
    • parse(response) 当在request 中未指定callback 时默认对下载的response 调用该方法
  • Request 构造函数参数

    • url 请求路径
    • callback 指定请求收到回复时调用的方法函数,若没有制定则调用parse方法
    • method 指定请求使用的方法,默认GET
    • meta 可以将一个字典变量传入到callback方法的response.meta 参数中,传入时使用浅拷贝方式。是一个能在Request/Response之间很方便的传递一些自定义变量的东西。cookiejar 为保留变量,可以使用同一个cookiejar 值进行统一份cookie的传递
    • dont_filter 标识该请求不会被调度器过滤。当需要对同一个请求发送多次时,需要设置,防止调度器的重复请求过滤
  • errback 请求异常时的回调

  • response 成员变量

    • status 状态码
    • request 产生这个responserequest 对象
    • meta request 对象传入的meta字典
  • XPath 语法

    | 表达式 | 描述 |
    | :—————- | ———————————————————— |
    | nodename | 选取此节点的所有子节点。 |
    | / | 从根节点选取,绝对路径。 |
    | // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
    | . | 选取当前节点。 |
    | .. | 选取当前节点的父节点。 |
    | @ | 选取属性。 |
    | [] | 条件筛选 |
    | text() | 获取节点的内部文字 |
    | following-sibling | 获取兄弟节点,第一个div兄弟节点为 ../following-sibling::div[1] |

    • extract() 将选择器匹配的内容以字符串列表返回
  • pipline

    • 必须实现process_item(self, item, spider) 方法
      • 返回具有数据的dictItem 对象或抛出DropIem 异常丢弃item(被丢弃的item不会被后面的pipeline继续处理)。
      • 该方法在页面下载后的 callback 返回item 后进行调用。
    • 可选实现open_spiderclose_spiderfrom_crawler
    • 通过ITEM_PIPELINES 配置pipline 的执行顺序,由小到大,0-1000
  • Files Pipeline

    • 避免已下载文件重复下载
    • 可自由定义文件存储位置
    • 如果是imagePipeline 还可以进行格式转换、缩略图生成、限制图片下载大小等操作
    • FilesPipeline 中的item 必须有一个file_urls 用于存储所有希望下载的文件地址
    • 使用FILES_EXPIRES 参数可以控制文件的失效时间,防止过度文件去重
    • get_media_requests(item, info) 方法获取每个待下载文件地址,并返回一个Request 对象
  • scrapd-deploy 打包

    • 安装 pip install scarped-client

    • 引入的第三方库需要加入到setup.py

    • 使用到的第三方文件需要在MENIFEST.in 中指定路径

    • 代码中的路径需要使用如下方法获得egg包路径后拼接路径

      1
      2
      3
      4
      5
      6
      7
      8
      def get_egg_dir(default_path=path.abspath(path.join(__file__, '../../..'))):
      try:
      scrapyd_dir = os.environ['PROJECT_DIR']
      project = os.environ['SCRAPY_PROJECT']
      version = os.environ['SCRAPY_EGG_VERSION']
      return path.join(scrapyd_dir, 'eggs', project, version)
      except:
      return default_path
    • scrapyd-deploy --build-egg out.egg 输出egg文件

Linux

  • crontab 定时任务 参考
    • crontab -l 列出所有定时任务
    • crontab -e 编辑定时任务列表
    • 书写方法:min hour day month weekday command
    • / 可用于表示
    • 命令顺序minute hour day month week command
      • minute: 表示分钟,可以是从0到59之间的任何整数。
      • hour:表示小时,可以是从0到23之间的任何整数。
      • day:表示日期,可以是从1到31之间的任何整数。
      • month:表示月份,可以是从1到12之间的任何整数。
      • week:表示星期几,可以是从0到7之间的任何整数,这里的0或7代表星期日。
      • command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。
    • Example:
      • 45 */2 1,10,22 * * /etc/init.d/smb restart 每个月1,10,22日的每隔2小时的第45分钟重启smb服务
      • * * * * * /etc/init.d/smb restart 每分钟重启smb服务一次
    • 特殊字符
      • 星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
      • 逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
      • 中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
      • 正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。
    • 系统执行定时任务时不会加载任何环境变量,需要在任务执行时指定所有环境变量。可以通过加source ~/.bash_profile 的方式加载环境变量。
    • 每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户
    • 可以在crontab列表最前加入LC_ALL=en_US.UTF-8 LANG=en_US.utf-8 限定编码相关的环境变量
  • $(date +%Y-%m-%d_%H:%M).log 可在bash中输出格式化日期的log文件
  • less
    • f/b 向下/上翻页
    • g/G 第一行/最后一行
    • F less版tail -f
    • / 搜索,n/N 向下/上查找
  • iTerm2 操作
    • Ctrl + A 光标移动到开头
    • Ctrl + E 光标移动到结尾
    • Ctrl + K 删除到行尾

Selenium

  • pip install selenium

  • 通过webdriver 打开浏览器,然后模拟人为操作

    1
    2
    3
    4
    5
    6
    driver.get(url)  # 跳转到指定url
    driver.find_element_by_xpath. # 通过xpath获取指定元素对象
    element.clear(). # 清除元素中的文本(一般是对于input等输入式组件,防止其中包含一些default文本)
    element.send_keys("something input") # 对元素模拟键盘输入
    element.send_keys(Keys.RETURN) # 对元素发送一些特殊按键
    driver.close() # 关闭浏览器标签
  • Select 对象可以实例话一个select组件,完成组件option的选取

    1
    2
    3
    4
    5
    6
    7
    8
    select = Select(driver.find_element_by_name('name'))  # 获取select组件

    select.select_by_index(index)
    select.select_by_visible_text("text")
    select.select_by_value(value)
    select.deselect_all()

    select.all_selected_options # 获取所有选项
  • ActionChains 完成拖放操作

    • 拖拽

      1
      2
      3
      4
      5
      ActionChains(driver).click_and_hold(on_element=drag_button).perform()  # 点击组件中心点位置

      ActionChains(driver).move_to_element_with_offset(to_element=drag_button, xoffset=2).perform() # 将鼠标移动到相对于drag_button左上角,向右偏移2px的位置

      ActionChains(driver).release(on_element=drag_button).perform() # 释放点击动作
  • 通过Options 可以限制网页加载过程中图片的下载,加快加载速度,节省带宽

    1
    2
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_experimental_option('prefs', {"profile.managed_default_content_settings.images": 100})
  • webdriver 文件需要有可执行权限,使用os.chmod('/path/to/driver', 0o755)

  • driver.switch_to_frame(iframe) 可以切换到通过脚本函数生成的frame中

HTTP request

GET vs POST

参考

  • GET 请求参数会显示在url中,因此可以通过书签或者其他方式进行重新访问
  • GET 请求对参数个数(2K)和总长度(2048字符)有限制,且只能传输ASCII编码字符,POST 还可传输文件等二进制数据
  • GET 请求可被缓存,POST 不可以
  • 综上,POST 相对安全一些,且相对不容易被hack

class method vs static method

  • 参考
  • static method 中不存在cls变量,也就是不能通过cls访问其中的静态变量
  • class method 中存在cls,因此可以在全局中通过类方法维护某个类变量来改变类的状态
0%