代码review_学习笔记_1

Posted 是蓝鲸啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码review_学习笔记_1相关的知识,希望对你有一定的参考价值。

代码review(一)

问题:获取详情页链接的xpath语句id值是不固定的
解决:先获取所有的id值,再将id值拼接到xpath语句中获取详情页链接
总结:观察html代码,找到规律

# 获取全局信息
result = response.xpath('//*[@id="mp-pusher"]//table')
# 获取所有drugname标签
lists = result .xpath('.//tr/td/div/div/a/@href').extract()
# 存放drugname标签,循环处理drugname标签字符串
new_list = []
for i in lists:
    new_i = i.replace('#', '')
    new_list.append(new_i)
# 将处理好的标签拼接xpath语句,提取所有url
for j in new_list:
    url = f'.//*[@id="{j}"]/li/a/@href'
    # 获取所有详情页页链接
    link_list = result .xpath(url).extract()
    # 拼接完整的详情 页链接
    for k in link_list:
        urls = str('**********') + k
        yield scrapy.Request(
            urls,
            callback=self.new_parse
        )        

问题:爬取HMA需要点击选项后获取cookie,才能取到数据
解决:使用selenium模拟浏览器操作,获取cookie
总结:通过selenium实现自动获取cookie,在headers中添加’Cookie’: getCookie()

from selenium import webdriver
from selenium.webdriver.support.ui import Select  # select类,下拉菜单使用
def getCookie(self):
    # 获取谷歌驱动
    driver = webdriver.Chrome()
    # 访问指定网站
    driver.get("*****url*****")
    # 选择标签
    Select(driver.find_element_by_name('[0]Type')).select_by_value('RTE')
    Select(driver.find_element_by_name('[0]Placeholder')).select_by_value('1')
    time.sleep(2)
    # 点击提交
    driver.find_element_by_xpath(r'//*[@id="searchform"]/div[4]/div/div/div/div/div/div/div/div/input[3]').click()
    # 获取cookie 返回字典类型的列表
    cookies = driver.get_cookies()
    # 将driver获取的字典类型的cookie提取name和value封装成字符串
    cookie = []
    for i in cookies:
        cookie.append(i['name'] + '=' + i['value'])
	# 获取到数据后关闭浏览器
    driver.close()
    return ';'.join(cookie)

问题:使用selenium模拟浏览器被识别为爬虫
解决:使用 Google 的Chrome Devtools-Protocol(Chrome 开发工具协议)简称CDP。selenium使用driver.execute_cdp_cmd,传入需要调用的 CDP 命令和参数即可
总结:自动提前在网站自带的所有js之前执行这个语句,隐藏window.navigator.webdriver

# 在driver.get前调用driver.execute_cdp_cmd
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
                Object.defineProperty(navigator, 'webdriver', {
                  get: () => undefined
                })
              """
    })

问题:使用sqlalchemy连接两个不同地址的数据库,完成查询和批量更新操作
解决:初始化两个engine,创建两个session完成操作
总结:将Table_1的id和Table_2查询到的数据合并成一个字典,将字典存入mappings中,完成批量更新,有效提升更新效率

# 建立查询条件,并打印信息
# 查询info数据作为Table_2的筛选条件,refe数据作为更新的索引
user_info = session1.query(Table_1.info,Table_1.refe_id).filter_by(refe_type="article",is_del=0).all()
mappings = []
count = 1
for i, j in user_info:
    count += 1
    if i.get("pmid"):
        result = session2.query(Table_2.article_id).filter_by(article_pmid=i["pmid"]).first()
        if result: # result为row类型
        	# 创建字典,'references_id'值作为索引,'article_id'值为要更新的数据
            info = {'refe_id': j, 'article_id': result[0]}
        else: # result为None
            info = {'refe_id': j, 'article_id': result}

    elif i.get("doi"):
        result = session2.query(Table_2.article_id).filter_by(article_doi=i["article_doi"]).first()
        if result:
            info = {'refe_id': j, 'article_id': result[0]}
        else:
            info = {'refes_id': j, 'article_id': result}
    else:
        result = None
        info = {'refe_id': j, 'article_id': result}
    print(count, info)
    mappings.append(info)
    if count % 1000 == 0:
        session1.bulk_update_mappings(Table_1, mappings)
        session1.flush()
        session1.commit()
        mappings[:] = []
session1.bulk_update_mappings(Table_1, mappings)
session1.flush()
session1.commit()

以上是关于代码review_学习笔记_1的主要内容,如果未能解决你的问题,请参考以下文章

Android内核源码bionic目录下的子目录arch-arm源码分析笔记

ANDROID_MARS学习笔记_S02_007_Animation第一种使用方式:代码

Python学习笔记__5章 模块

C++Review4_代码的组织

2016py学习笔记:模块/

Python学习笔记__8.4章 文档测试