spider_day08

多线程爬虫

  • 使用流程
# 1、URL队列
q.put(url)
# 2、线程事件函数
while True:
    if not url_queue.empty():
        ...get()、请求、解析
    else:
        break
# 创建并启动线程
t_list = []
for i in range(5):
    t = Thread(target=parse_page)
    t_list.append(t)
    t.start()
# 阻塞等待回收线程
for i in t_list:
    i.join()

json模块

  • json转python
变量名 = json.loads(res.text))
  • python转json(保存为json文件)
# 保存所抓取数据为json数据
with open(filename,'a') as f:
	json.dump(字典/列表/元组,f,ensure_ascii=False)

selenium+phantomjs/chrome/firefox

  • 特点
1、简单,无需去详细抓取分析网络数据包,使用真实浏览器
2、需要等待页面元素加载,需要时间,效率低
  • 使用流程
from selenium import webdriver

# 创建浏览器对象
browser = webdriver.Firefox()
browser.get('https://www.jd.com/')

# 查找节点
node = browser.find_element_by_xpath('')
node.send_keys('')
node.click()

# 获取节点文本内容
content = node.text

# 关闭浏览器
browser.quit()
  • 设置无界面模式(chromedriver | firefox)
options = webdriver.ChromeOptions()
options.add_argument('--headless')

browser = webdriver.Chrome(options=options)
browser.get(url)

京东爬虫

  • 执行JS脚本,把进度条拉到最下面
1、js脚本
browser.execute_script(
'window.scrollTo(0,document.body.scrollHeight)'
)
2、利用节点对象的text属性获取当前节点及后代节点的文本内容,想办法处理数据

scrapy框架

  • 五大组件
引擎(Engine)
爬虫程序(Spider)
调度器(Scheduler)
下载器(Downloader)
管道文件(Pipeline)
# 两个中间件
下载器中间件(Downloader Middlewares)
蜘蛛中间件(Spider Middlewares)
  • 工作流程
1、Engine向Spider索要URL,交给Scheduler入队列
2、Scheduler处理后出队列,通过Downloader Middlewares交给Downloader去下载
3、Downloader得到响应后,通过Spider Middlewares交给Spider
4、Spider数据提取:
   1、数据交给Pipeline处理
   2、需要跟进URL,继续交给Scheduler入队列,依次循环
  • 常用命令
# 创建爬虫项目
scrapy startproject 项目名

# 创建爬虫文件
cd 项目文件夹
scrapy genspider 爬虫名 域名

# 运行爬虫
scrapy crawl 爬虫名
  • scrapy项目目录结构
Baidu
├── Baidu               # 项目目录
│   ├── items.py        # 定义数据结构
│   ├── middlewares.py  # 中间件
│   ├── pipelines.py    # 数据处理
│   ├── settings.py     # 全局配置
│   └── spiders
│       ├── baidu.py    # 爬虫文件
└── scrapy.cfg          # 项目基本配置文件
  • settings.py全局配置
1、USER_AGENT = 'Mozilla/5.0'
# 是否遵循机器人协议
2、ROBOTSTXT_OBEY = False
# 最大并发数
3、CONCURRENT_REQUESTS = 32
4、DOWNLOAD_DELAY = 1
5、DEFAULT_REQUEST_HEADERS={
   }
6、ITEM_PIPELINES={
   '项目目录名.pipelines.类名':300}

Day07笔记

selenium补充

切换页面

1、适用网站

页面中点开链接出现新的页面,但是浏览器对象browser还是之前页面的对象(url未变)

2、应对方案

# 获取当前所有句柄(窗口)
all_handles = browser.window_handles
# 切换到新的窗口
browser.switch_to_window(all_handles[1])

3、民政部网站案例

​ 3.1 目标: 将民政区划代码爬取到数据库中,按照层级关系(分表 – 省表、市表、县表)

​ 3.2 数据库中建表

# 建库
create database govdb charset utf8;
use govdb;
# 建表
create table province(
p_name varchar(20),
p_code varchar(20)
)charset=utf8;
create table city(
c_name varchar(20),
c_code varchar(20),
c_father_code varchar(20)
)charset=utf8;
create table county(
x_name varchar(20),
x_code varchar(20),
x_father_code varchar(20)
)charset=utf8;

​ 3.3 思路

1、selenium+Chrome打开一级页面,并提取二级页面最新链接
2、增量爬取: 和数据库version表中进行比对,确定之前是否爬过(是否有更新)
3、如果没有更新,直接提示用户,无须继续爬取
4、如果有更新,则删除之前表中数据,重新爬取并插入数据库表
5、最终完成后: 断开数据库连接,关闭浏览器

​ 3.4 代码实现

from selenium import webdriver
import time
import pymysql

class GovementSpider(object):
    def __init__(self):
        # 创建浏览器对象 + 打开一级页面
        self.options = webdriver.ChromeOptions()
        self.options.add_argument('--headless')
        self.browser = webdriver.Chrome(options=self.options)

        self.one_url = 'http://www.mca.gov.cn/article/sj/xzqh/2019/'
        # 数据库相关变量
        self.db = pymysql.connect('192.168.153.134', 'tiger', '123456', 'govdb', charset='utf8')
        self.cursor = self.db.cursor()
        # 定义数据库中三张表的列表,后续使用executemany方法将数据插入数据库
        self.province_list = []
        self.city_list = []
        self.county_list = []

    # 获取首页,并提取最新二级页面链接
    def get_two_url(self):
        self.browser.get(self.one_url)
        # 提取最新二级页面链接节点 + 点击该节点
        td_list = self.browser.find_elements_by_xpath('//td[@class="arlisttd"]/a[contains(@title,"中华人民共和国县以上行政区划代码")]')
        if td_list:
            two_url_element = td_list[0]
            # 增量爬取数据库核对
            two_url = two_url_element.get_attribute('href')

        sel = 'select * from version'
        self.cursor.execute(sel)
        result = self.cursor.fetchall()
        if result:
            version_url = result[-1][0]
        else:
            version_url = ''

        # 和数据库中url做比对
        if two_url == version_url:
            print('已是最新,无需爬取')
        else:
            two_url_element.click()
            # 获取当前所有句柄 + 将browser切换到新的页面
            all_handles = self.browser.window_handles
            self.browser
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值